Event-Driven Architecture – How to Handle Initial State in an Event-Driven Architecture?

Architectureevent-programming

In an event-driven architecture each component only acts when an event is sent through the system.

Imagine a hypothetical car with a brake pedal and a brake light.

  • The brake light turns on when it receives a brake_on event, and off when it receives a brake_off event.
  • The brake pedal sends a brake_on event when it is pressed down, and a brake_off event when it is released.

This is all well and good, until you have the situation where the car is turned on with the brake pedal already pressed down. Since the brake light never received a brake_on event, it will stay off – clearly an undesirable situation. Turning the brake light on by default only reverses the situation.

What could be done to resolve this 'initial state problem'?

EDIT: Thank you for all the responses. My question was not about an actual car. In cars they solved this problem by continuously sending the state – therefore there is no startup issue in that domain. In my software domain, that solution would use many unnecessary CPU cycles.

EDIT 2: In addition to @gbjbaanb's answer, I'm going for a system in which:

  • the hypothetical brake pedal, after initialization, sends an event with its state, and
  • the hypothetical brake light, after initialization, sends an event requesting a state event from the brake pedal.

With this solution, there are no dependencies between components, no race conditions, no message queues to go stale, and no 'master' components.

Best Answer

There are many ways to do this, but I prefer to keep a message-based system as decoupled as possible. This means the overall system cannot read the state of any component, nor any component read the state of any other (as that way lies spaghetti ties of dependancies).

So, while the running system will look after itself, we need a way to tell each component to start itself up, and we already have such a thing in the component registration, ie at startup the core system has to inform each component that it is now registered (or will ask each component to return its details so it can be registered). This is the stage at which the component can perform its startup tasks, and can send messages as it would do in normal operation.

So the brake pedal, when the ignition is started, would receive a registration/check message from the car management and it would return not only a "I'm here and working" message, but it would then check its own state and send the messages for that state (eg a pedal depressed message).

The problem then becomes one of startup dependancies, as if the brake light is not yet registered then it will not receive the message, but this is easily resolved by queuing all of these messages until the core system has completed its startup, registration and check routine.

The biggest benefit is that there is no special code required to handle initialisation except that you already have to write (ok, if your message-sending for brake pedal events is in a brake-pedal handler you will have to call that in your initialisation too, but that's usually not a problem unless you've written that code tied heavily to the handler logic) and no interaction between components except those that they already send to each other as normal. Message passing architectures are very good because of this!

Related Topic