Comments (6)
I have a few questions about this.
Aren't process managers defined as "the opposite to an aggregate" as in
- an aggregate receives commands and emits domain events
- a process manager receives domain events and emits commands
or are they something else?
But, for the sake of it, I can try implementing it by adding some syntactic sugar to the existing building blocs
If Eventuous supports them as syntactic sugar, would its state be also event sourced? Because process managers don't usually have the technical limitation to be short lived, right?
Here comes the question if I need to wire an existing app service that processes commands coming via HTTP also to consume command messages.
To me, if there is a process manager is because there is no need for http commands, as the transaction is initiated automatically without the need of a UI. In other words, I see process managers as a replacement to UI and http communication.
For example, in a Restaurant domain where there are orders, waiters and each waiter wants to have a list of things that could do next each time it goes to the kitchen, this could be modelled with the following 3 aggregates.
Waiter producing events like
- AvailableSet
- UnavailableSet
and Order producing events like
- OrderPrepared
- OrderPicked (with waiter Id)
- OrderDelivered
and WaiterTodoQueue, as a queue of tasks associated to a specific waiter, producing events like
- OrderSuggestionAdded
- OrderSuggestionRemoved
Customers create orders and someone prepares them. Waiters pick prepared orders.
A waiter goes to a read model (fed by WaiterTodoQueue) and picks one of the suggestions. When picked, this suggestion disappears from other waiters' todo queues. When a waiter delivers it, the order is delivered.
If I want a "process manager" called Dispatcher in charge of keeping waiters busy by suggesting to them orders to be picked, I would want this dispatcher to have state + behaviour (probably business logic).
So the Dispatcher would keep track of available waiters and orders prepared in order to dispatch/send commands to *WaiterTodoQueue, this Dispatcher is indeed something that receives events and emits commands (towards WaiterTodoQueue aggregate).
The problem is that the Dispatcher state, if event sourced, could grow rapidly and become slower unless it uses snapshots or similar.
Most processes are natural and not orchestrated
Does that mean that the Dispatcher in the example above could be modelled differently without using orchestration?
TL;DR: What's the definition of process manager? Is its state event sourced? Can things always be modelled without introducing orchestration (something that receives events and emits commands)?
from eventuous.
What you describe as "aggregate" is basically a decider, which can be done using aggregates. Eventuous command services are quote close to that pattern.
Process managers, in general, receive messages and send messages. Whether the PM reacts to commands is discussable, but a process is usually started by a command anyway.
What I was looking in this issue initially is event-sourced state. As we have the state store now, the state object can be used in functional services, as well as in PMs. So, that's covered.
My assumption is that atm the only missing thing is multi-subscription support. Probably it's not even needed for the first iteration. But, definitely, it is needed later as I'd expect PMs to react on integration events, which might be emitted to different topics/streams. The question is more about the API rather than what's behind it. Doing AddSubscription(...).AddProcessManager<T>()
and using the same instance of T
across subscriptions is the easiest, and it will definitely work. I was thinking into a PM-first registration API like AddProcess<T>().SubscribeTo<T1, T2>().SubscribeTo<T3, T4>()
, but it's much more work.
from eventuous.
There is one thing I don't get - let's assume that I need to conduct two aggregate types - A
and B
. Then I create a new instance of ProcessManager/Aggregate that handles the process, let's call it PM
. How should I property identify instance of PM based on events from A and B that only contain AId, or BId respectively? Do I need to create a projection that allows finding PMId based on AId or BId?
In other words, how should I identify a particular PMId for handling an event coming from a particular A (thus containing just AId).
from eventuous.
As with anything else, you need to figure out some way to correlate the two sides
in some cases there's a parent-child relationship, and you don't need multiple instances - for those cases maybe the child id will sufffice
In the more general case, if you consider the process a workflow, you might mint a fresh identity for the instance
One benefit of this is that each instance of the process has an independent set of events and/or state and you don't get long streams. Of course that can potentially also be a problem if you have a need to coordinate the multiple running instances.
The you can make anything enlisted in it aware of same; either
- by feeding the id of the flow into each side out of band/naturally
- or when kicking off the process, you seed it with the ids of the participants, and make the first step to make those aware of their enlistment
(Will be interested to see/hear if Eventuous has any specific affordances wrt this, but for me process managers are just programming)
from eventuous.
You are right, especially with the parent-child relationship, you don't need another entity. My concern is exactly about the second case you mentioned - creating a new process manager instance with ids of its participants. What is the best way to notify the manager back when an event from any of its participants arrive.
The only idea I have is to create a projection that provides links from participantId
s back to managerId
and event subscription for all participant events that 'gateways' them to the respective owning manager. This should work (provided that there is not partitioning for events and thus participant or manager cannot get behind?) but just feels like a lot of boilerplate code for quite a typical case.
Feeding managerId
to all participants feels a little bit like leaking abstraction, but might be appropriate in many cases, though.
Thank you for these ideas and brainstorming ;-)
from eventuous.
I would tend to have a reactor that sees all the events.
It should be handling the events in bulk across streams and forwarding them en masse
The question is how, based on solely the event, it determines the PM to route to either
- the event carries enough context to let you route it
- or you need to go back to the source to determine the PM to feed it to
Once you know where to go, submitting an event to the PM is just a transaction against the workflow aggregate
(IIRC in there is a that sample in https://github.com/jet/dotnet-templates that does that, but the general principle applies regardless)
from eventuous.
Related Issues (20)
- MapEventuousSpyglass interferes with UseAuthentication and UseAuthorization HOT 1
- Using MapDiscoveredCommands with multiple aggregates results in error 'No handler found for command Object ' HOT 16
- Ability to return a custom return type for a command API reponse HOT 5
- SQL Server __schema__.Streams.StreamName is too big to be indexed
- Unable to create isolated Aggregates with State and Id HOT 5
- SQL Server Subscription skips an event on non-initial startup
- Provide StreamContext in UpdateBuilder<TBuilder>.Configure() for MondoDb HOT 1
- With the SQL Server event store, event handlers are sometimes called twice for each event HOT 4
- Health check stays "healthy" even if Event Handler throws an exception HOT 5
- Transient error drops the subscription. (Connection reset by peer) HOT 6
- Add subscription drop/resubscribe tests
- Add subscription measure for RDBMS subs HOT 1
- Error at schema initialization (PostgresException: '42704: type public.stream_message[] does not exist) HOT 1
- Eventuous should always return `Result<TState>` HOT 2
- Does it make sense to keep `Aggregate` without state? HOT 8
- Preserve original exception stacktrace in command service HOT 1
- Enable custom configuration of NpgsqlDataSourceBuilder when using AddEventuousPostgres HOT 1
- DuplicateTypeException in CommandService HOT 11
- "Can not start an Activity that was already started" in BaseProducer
- Memory leak (CancellationTokenSource) in AsyncHandlingFilter HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from eventuous.