github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/design/projectors/README.md (about) 1 ### Abstract 2 3 Projectors design 4 5 ### Terms 6 - Projector (Проектор) 7 - Common: Describes the way how events are applied to projection 8 - Heeus: Provides a function which generates *Intents* based on the information from *Event* and current *State* 9 - State (состояние) 10 - Provides reading from Storages 11 - Intents (намерения) 12 - A declaration of Create or Update modifications in Storage that will be applied in the result of projector execution 13 - Modifications declared by Intents are not applied before the extension function ends 14 - Storage 15 - Provides I/O access for extensions (to e.g. Views, Records, WLog, HTTP, Mailer, etc) 16 - Projection (Проекция, Read Model, Query Model) 17 - Common: Projection is about deriving current state from the stream of events. [(c)](https://abdullin.com/post/event-sourcing-projections/) 18 - Состояние, вычисленное на основе анализа потока событий 19 - Common: "Projection is a left-fold over the sequence of events" [(c)](https://domaincentric.net/blog/event-sourcing-projections) [Greg Young](https://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf) 20 - [Левоассоциативная свертка](https://ru.wikipedia.org/wiki/%D0%A1%D0%B2%D1%91%D1%80%D1%82%D0%BA%D0%B0_%D1%81%D0%BF%D0%B8%D1%81%D0%BA%D0%B0) списка 21 - In terms of Heeus: cumulative result of *all applied intents* of the projector. 22 - Example: one projector may generate one or more Views. A *combination of these views* is a projection 23 - Internal Projection 24 - A projection which is kept in the AppStorage; 25 - WLog, Table, View; 26 - Read Model is the set of internal projectors; 27 - External Projection 28 - A projection which is kept outside of the AppStorage; 29 - Actualizer (Feeder, Актуализатор, Кормилец) 30 - A component which *feeds Projector* with events from PLog 31 - Applies intents to storages 32 - Async Actualizer 33 - Feeds projectors asynchronously with Command Processor: no guarantee that projection is updated before CP finishes handling the event. 34 - Each Projector fed by it's own Async Actualizer 35 - Sync Actualizer 36 - Feeds projectors within Command Processor => projection is updated before event handling is finished 37 - This type of actualizer will be soon eliminated 38 - Actualizer Factory (Фабрика Актуализатора) 39 - A function which creates actualizer instance for the app partition for certain projector 40 - Actualizer Offset (Смещение проектора) 41 - The number of the last PLog event which is guaranteed fed to the projector and applied to storages 42 43 ### Concepts 44 45 ```mermaid 46 erDiagram 47 AppSchema ||--o{ ViewSpec: declares 48 ViewSpec ||--|| ViewProjectorFactory: "used to build" 49 CustomProjectorSpec { 50 string Name 51 bool NonBuffered 52 func Func 53 } 54 AppSchema ||--o{ CustomProjectorSpec: declares 55 CustomProjectorSpec ||--|| CustomProjectorFactory: "used to build" 56 BuiltInProjectorFactory ||--|| ProjectorFactory: "is a" 57 CustomProjectorFactory ||--|| ProjectorFactory: "is a" 58 ViewProjectorFactory ||--|| ProjectorFactory: "is a" 59 ActualizerFactory ||--|{ Actualizer: "creates per AppPartition" 60 ActualizerFactory ||--|{ Projector: "creates per AppPartition" 61 Projector ||--|| Actualizer: "fed by" 62 Projector ||--o{ Intent: "declares Storages modification" 63 Projector ||--|| State: "reads from Storages using" 64 Projector ||--|| Event: "gets as a param" 65 State ||--|| Actualizer: "provided by" 66 Event ||--|| Actualizer: "provided by" 67 Intent }o--|| Actualizer: "applied by" 68 Actualizer }|--|| PLog: "reads from" 69 Actualizer }|--|| CommandProcessor: "notified by" 70 ProjectorFactory }|--|| ActualizerFactory: "used by" 71 State ||--|{ Storage: "reads from" 72 Actualizer ||--|{ Storage: "applies intents to" 73 ``` 74 ### Principles 75 - As we don't use "Prepare" function, Projector is *not an IOperator anymore*, but a function with three arguments: *workpiece*, *State* and *Intents* 76 - Async Actualizers (AA): 77 - State 1: 78 - Changes to storage applied immediately after every event 79 - State 2.0: 80 - AA Buffers changes to storages and applies them by timer or when the buffer is full 81 - there is a possibility to set projection as "non%-buffered". In this case changes applied after every event 82 - Sync Actualizers (SA): 83 - State 1: 84 - SA handle single event in a Fork. Every SA applies it's changes independently 85 - State 2.0: 86 - SA handle single event in a Fork. Changes to storages applied when all projectors for the event are handled with no errors 87 88 ### Detailed design 89 90 - [Async Actualizers](./async-act.md) 91 - [Sync Actualizers](./sync-act.md) 92 - [Idempotency](./idempotency.md) 93 94 ### References 95 - [State 2.0](./README.md) 96 - [Extension Engines / WASM ABI](./ext-engines.md) 97 - [Lazy Projections](./lazy-projections.md) 98