[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