[Zope3-dev] event service and channel
Gary Poster
garyposter@earthlink.net
Thu, 18 Apr 2002 11:34:39 -0400
I'm building some event channel and service code, and have run into a few
interesting decisions that I'd like to see if anyone has some feedback on.
Here are the topics, so you can quickly decide what you're interested in;
I'll get into them below.
1. what publishEvent bubble pattern whould we use through multiple placeful
event services?
2. what subscribe pattern should we use for multiple placeful event services?
3. While some objects, like the ObjectHub, will be special event channels, we
will want standard event channels for events of certain types: where should
they live?
Discussion
Like most services, event services have placeful and placeless versions. The
placeless ("global") version of the event service has limited usefulness
because subscriptions to it do not persist. Placeful ("local") event
services will be the main workhorses.
Placeful event services can be held in any placeful service manager. While
we probably will not regularly want many event services (event channels being
sufficient for must purposes) it is certainly conceivable that we will want
multiple event services in the tree. It is this situation that I focus on
for the first two questions.
1. (publishEvent bubble pattern)
Given
* the global event service
* two placeful event services, one in a root folder and one in a child
folder beneath it;
* and an event fired in the child folder via a call something like
"publishEvent(context, eventObject)"
what should the default event bubbling be? This is my vote, based to some
degree on what is built now:
1. publishEvent function finds the closest event service to context, which
in this case is the placeful event service in the child folder.
2. publishEvent function calls that service's publishEvent method with the
eventObject
3. child event service notifies all subscribers, except possibly the
caller
4. child event service finds the next (parent event service), which in
this case is the one in the root folder
5. child event service calls the next event service's publishEvent with
the eventObject *and itself* (change to method signature needed for
optional "caller")
6. root folder event service notifies all subscribers, excepting the
caller, if it is a subscriber
7. root folder event service finds global event service
8. root folder calls global event service's publishEvent method with
the eventObject and itself
9. global event service notifies all subscribers except caller
So, this would mean an additional "caller=None" at the end of the
IEventService publishEvent method signature.
Presumably also at some point we may want an event service to be able to
decide to turn off publishing events to its parents, either filtered or just
entirely off. I figure we can deal with that later.
There would be many other possible patterns to follow which I won't lengthen
this email with, but if what I suggest is bothersome then we can look into
them.
2. (subscribe pattern)
Given the same arrangement of event services from question 1, when an object
calls "subscribe" (the hookable function "subscribe(context, subscriber,
event_types=(None,), filter=None)") from within the child placeful event
service, what should happen? should the subscription be registered with the
child or passed on to the parent?
The "do what I mean" behavior would, I think, be to pass the subscription to
the highest available placeful event service. Otherwise, if the child event
service handled the subscription, and it were not subscribed itself to the
parent event service for that type of event, then the object requesting a
subscription might not get the events it expects and needs.
However, this policy clearly needs to be configurable. Where? should the
subscribe hook include an optional argument to only subscribe locally?
should the event service have a switch? both? event services will obviously
have this kind of control whenever we want them to, but if we want the
subscribe hook to have the necessary signature then it might be nice to know
now. Thoughts?
The unsubscribe pattern would be easier I guess--pass the unsubscribe request
to the local event service and then the local event service will act on it
and pass it on up, so the request is handled by all pertinent event services.
Or not? Do we need a switch somewhere in that hook too so that the
unsubscribe can only happen locally? I think maybe so.
Left to my own devices, I suppose I will add a simple switch to the subscribe
and unsubscribe hook and method signatures as to whether to act locally or
globally...but I'd much prefer feedback.
3. (Event channels)
This is less pressing, but...
While some objects, like the Object Hub, are specialized event channels,
Tres' design also includes named event channels, which seem like a great
idea. If a certain event type will be subscribed to by many objects, make
that event have its own channel, and subscribe to it. Careful channel design
could significantly reduce the churn of processing a given event publication.
How should these named event channels be accessible? Where should they live?
What, in terms of Component Architecture, are they, even?
One idea is that they can live in event service as parts, and one can find
and subscribe to them via a different method of the event service.
They could be services themselves, but that seems contrary to the idea of
services, both theoretically (are they essential to the functioning of Zope?)
and practically (the number of event channels could conceivably grow fairly
high).
They could be utilities, but they again don't seem to match the
description--particularly, if utilities are only accessible via interfaces,
that would not match Tres design nor be as useful.
They are not content.
It seems to me they ought to have their own management service, like an
EventChannelManager or something like that. They would have to then further
have some similar functionality to service definitions (that map names to
interfaces) so that event channel names are mapped to descriptions, and that
names in a lower EventChannelManager do not mask names in a higher one
(unless so desired).
Once again: thoughts?
Gary