platform-main — effects runtime data flow
EffectsRootModule's constructor runs exactly once, and the
order of its three statements isn't incidental — get it wrong and every
root-registered effect would silently never fire, with no error anywhere to
point at why. Traced end to end during the
code review of effects_root_module.ts.
EffectsRunner subscribes to
effectSources.toActions() and dispatches every emitted
action to the Store. Guarded by a stored
Subscription so a second start() is a no-op.
EffectSources' internal stream.
Why step 1 has to come before step 2:
EffectSources composes a plain RxJS Subject for
its internal sources$ — not a ReplaySubject. A
plain Subject drops any next() call made before
a subscriber exists. If the loop in step 2 ran first, every
addEffects() call would push into sources$ with
nobody listening yet, and toActions()
would never see any of it. Starting the runner first guarantees the
subscription exists before anything is pushed in.