We’ve gone on enough about organization of the work for a while, so today we’ll kick off a series on concurrency with autonomous components and particularly Eventide.
We only get two minutes per day with these emails, so today’s is going to focus on why it isn’t as simple as just launching additional instances of your component.
You’ve probably dealt with concurrency with your HTTP servers—you just stood up more of them. That works great for something stateless like an HTTP server.
That works less great for components because components are stateful. You can think of them as state machines. Merely standing up additional components will lead you to severe errors.
Why?
Each Consumer in an Eventide project operates on its own cadence. You have no guarantees of the order of operations between Consumers. If you simply start more instances of a component, consider what would happen with an account in the account-component
example.
You have an account with the following commands in its command stream, none of them have been processed, and you have two consumers:
If these separate consumers are free to process these commands, they’ll likely end up processing the same commands. They can both pass their handler’s idempotence check and both write the corresponding Opened
events. So the account got open twice.
We’ve talked about how to prevent this by using the expected_version
option when writing messages, and that will protect you from the duplicate processing. But that gives you a best case of duplicated processing. There are times when you’d want that, a very fast hot failover, but that probably isn’t what you’re after when you run concurrent instances of a component.
Next time we’ll look at Consumer Groups and how you can get your different instances to process different messages.