neos / neos-development-collection

The unified repository containing the Neos core packages, used for Neos development.
https://www.neos.io/
GNU General Public License v3.0
260 stars 221 forks source link

Replace `CatchUpHooks` with `ContentRepositoryHooks` #4992

Open bwaidelich opened 5 months ago

bwaidelich commented 5 months ago

The current implementation of the CatchUpHookInterface is a bit weird and flaky. It's a very low-level API even though I expect it to be one of the main extension points for Neos 9.x.

One of the main issues is the relation to one specific projection because that leads to low-level dependencies and quirky constructs like the ProjectionsAndCatchUpHooksFactory.

Suggestion

I suggest to drop the concept in favor of ContentRepositoryHooks that can be registered globally (per CR instance). With the architectural changes of #4746 this should allow for the same kind of flexibility, i.e. a hook is invoked before an event is applied and afterwards, so the implementation can access the read model(s) in a controlled manner:

sequenceDiagram
  activate EventPersister
  EventPersister->>EventStore: load()
  activate EventStore
  EventStore-->>EventPersister: EventStream
  deactivate EventStore
  EventPersister->>ContentRepositoryHook: onBeforeBatch()
  rect rgba(200, 200, 200, .1)
  loop 
    EventPersister->>ContentRepositoryHook: onBeforeEvent(event, eventEnvelope)
    EventPersister->>Projection: apply(event, eventEnvelope)
    EventPersister->>ContentRepositoryHook: onAfterEvent(event, eventEnvelope)
  end
  end
  EventPersister->>ContentRepositoryHook: onAfterBatch()
  deactivate EventPersister

Migration of existing Hooks

Changing an existing CatchUpHookInterface implementation should be rather trivial, because the interfaces will be mostly similar I assume

CatchUp of individual projections

The above should work fine, as long as all projections are on the same checkpoint. This is the case by default (with the reworked catch up mechanism).

But what if it's not, for example because a new projection was added or replayed?

My current gut feeling is: We simplify things greatly if we assume the default case (and make sure that's always given). That would mean: When replaying/catching up individual projections, hooks are not triggered.