You raise an event when something interesting happens to you, you think
it is important, but you don't care enough to know who is interested.
you are even less interested in to personally going and to each an
every interested party and letting them know. So - instead, you raise
and event, and let the poor buggers take care of any implications by
themselves. We raise the event "now" when the change happened - it is
only important now anyway...
Looking from the "poor buggers"
-the event consumer point of view things are more complicated. There
are events which are cyclic in nature like stock price updates, the
blips from a sonar etc. if you missed one, then it isn't really
important you'd get the right information in the next update (actually,
that isn't entirely true - see later in this post). Then, there are the
events which only occur once. sometime it isn't important for you to
listen to them if you are not up and running in the same time. Other
times you can't afford to lose an event for instance if your ordering
service (or component for that matter) communicates with the invoicing
one using events you don't want to miss the event of a new order else
you would loose money.
This basically means that the event
producer and the event consumer are coupled in time - one way to solve
it is to make sure both of these services are available at the same
time i.e. if the invoices crashed, then processing orders should be
suspended (note that this doesn't mean that you don't accept orders
just that you don't process them).
Ok - maybe we can just raise the
event "transactionally" - this would probably work, but we need to
remember that the event producer doesn't really care about the event
consumers, why would it want to fail because of them?!
Maybe a
better way would be to "raise" the event over some reliable transport
- this has a few problems. one is that we've passed the problem to the
connection between the event producer and the transport. It might be
acceptable to have a transaction between the event producer and the
transport. However, as I've already said the producer doesn't care much
about the consumers..
We can have persistent subscriptions for
existing consumers to prevent events from getting lost which make both
creates a er minor problem that new consumers can't see past events but
also has the risk of existing subscribers disappearing and their queue
can then grow endlessly (or until an administrator would remove the
subscription)
Ok, let's try to look at the problem from a
different angle. looking at the events, what we can really see is that
an event has a time-to-live (TTL) as far as the event consumer is
concerned. For instance in the case of the cyclic events the TTL is the
interval until the next event. Actually, even with cyclic events the
TTL might be larger - if we are also interested in analyzing trends or
ab normal occurrences (which is why I said it isn't entirely true we
don't care about old events). In case of one-time events the TTL might
be indefinite or maybe even then it might be some definite value (one
day, week, year etc.). Since we can't know about the TTL of consumers
it can be a good idea to make past events available somehow.
Thus,
when you design an event centric architecture like EDA (whether on top
of SOA or not) it is important to think about event consumers - we
don't want to think about specific consumers since it negates the
benefits of thinking in events, but I would say that you want to think
about event consumers in general, after all your component is also an
event consumer (do unto others as you would have them do unto you)
One option,
which I already talked about,
is to make past events available as a feed. Event consumers can then
come at their own leisure and consume past event (this can be in
addition to to raising the events in real-time). This provides a
partial solution as the maximal TTL is determined by the event producer
(after which the event is deleted from the feed). This may be
acceptable but you must be aware of that.
The other option is to to
log all the events and provide an API to retrieve past events. In a
sense the max TTL is still at the hands of the event producer only if
you use a database it would probably be a large time compared with a
feed. Alternatively the events can be logged on by a central "always
present" event aggregator (in a manner similar to the
aggregated reporting pattern I described for SOA).
To sum all this - events they seem only to matter in the instance in
time they are created, we are used to that thinking from building OO
systems where all the components are co-located in the same
address-space and time (even there I can think of scenarios where we
would want past events) - in a distributed world events need to have a
TTL, the TTLs can vary and are determined by the events consumers.
Lastly, as I demonstrated in the paragraph above, there are several
strategies we can use to help solve the event TTL dilemma (and there
are probably a few others).