pyeventsourcing / eventsourcing

A library for event sourcing in Python.
https://eventsourcing.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
1.41k stars 129 forks source link

Use ProcessApplication build materialized view #270

Closed filwaline closed 3 months ago

filwaline commented 3 months ago

Is it a good choice to use a standalone ProcessApplication for constructing a materialized view, or should I adopt the recorder pattern, as demonstrated in the documentation searchable-timestamps, to develop my materialized view?

class MaterializedView(ProcessApplication):
    @singledispatchmethod
    def policy(
        self, domain_event: DomainEventProtocol, processing_event: ProcessingEvent
    ) -> None:
        """Default policy"""

    @policy.register(cls=Aggregate.Created)
    def _(
        self, domain_event: DomainEventProtocol, process_event: ProcessingEvent
    ) -> None:
        # Perform database operations, such as INSERT SQL statements.

    @policy.register(cls=Aggregate.Event)
    def _(
        self, domain_event: DomainEventProtocol, process_event: ProcessingEvent
    ) -> None:
        # Perform database operations, such as UPDATE SQL statements.
johnbywater commented 3 months ago

Good question. The possibilities are endless, but yes, you can use a ProcessAppliation to pull and process events, and extend a recorder to atomically execute queries on a materialised view with the recording of tracking records.

There's an example of this in the docs here: https://eventsourcing.readthedocs.io/en/latest/topics/examples/content-management-system.html

It extends this example which does the same thing synchronously, by running the policy when aggregates are saved. https://eventsourcing.readthedocs.io/en/latest/topics/examples/searchable-content.html

The "searchable content" example is very similar to the "searchable timestamps". So the same ideas would carry over to doing it as an "event-driven system" rather than as a "single application". That is, you can define your recorder and use it both ways. The policy would be the same. The difference between "event-driven system" and "single application" is when the policy is called, and also with an event-driven system you need to orchestrate the components somehow (for example with a "system definition" and a "system runner").

Please note, this is just one way of doing it. You can decompose the ideas and craft your own mechanisms as much as you want. But the central idea is the atomic recording of the update to the materialised view, either (1) atomic with the saving of the aggregate(s), or (2) processed in a "reliable" way, by atomically recording the position in an upstream sequence of an event that is processed along with the new state that results from processing that event.

Hope that helps @filwaline! Thanks for your interest in these topics!

filwaline commented 3 months ago

Thanks for the clarification! It's reassuring to know that my approach with ProcessApplication aligns well. Personally, the event-driven style resonates more with me, as it feels more explicit in its design.