Skip to content

refactor(eventbus): extract PathPropagator from the three handleEntityReparented variants #207

Description

@asphaltbuffet

Strength: Worth exploring
Category: in-process, structural

⚠️ Touches ADR-0005 and ADR-0009

Both ADRs record that path-changed events are skipped during import/rebuild. This refactor preserves the decision but moves it inside a named module instead of being threaded through three handler variants and a special-case in ReplayEvent. Worth flagging for ADR review — the ADRs may want a small note pointing at the new module.

Problem

Three handler variants of handleEntityReparented* all walk descendants — once to emit path-changed events, once to skip them (replay), once to preview them (import). The descendant-walk logic is duplicated. The replay-vs-dispatch decision lives outside the handlers in ReplayEvent, not in the handlers themselves.

Located:

  • internal/eventbus/handlers.gohandleEntityReparented, handleEntityReparentedProjectionOnlyTx, handleEntityReparentedComputePayloadsTx
  • internal/eventbus/bus.goReplayEvent special-cases EntityReparentedEvent to choose a variant

Solution

Introduce PathPropagator with three named modes:

  • .Apply(tx, reparent) — apply reparent + emit path-changed events
  • .ApplyProjectionOnly(tx, reparent) — write projection rows only (replay path)
  • .ComputePayloads(tx, reparent) — return prospective payloads (import path)

The descendant walk lives in one private method; the three modes differ only in what they emit. handleEntityReparented shrinks to one call into PathPropagator. ReplayEvent's branch becomes a method dispatch on the propagator.

Wins

  • Locality: descendant walk in one place
  • Leverage: ADRs enforced by module shape, not by convention
  • Interface names the three replay modes
  • Removes special-case branch from ReplayEvent
  • Tests target propagation directly
  • Composes cleanly with the event-registry refactor

Composes with

Source

Architecture review 2026-05-31, candidate #4 (Worth exploring). Distinct from #204 (registry collapse) — this issue addresses the descendant-walk duplication, not the event-type enumeration.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions