Events system

30 views
Skip to first unread message

Vlad K.

unread,
Dec 13, 2011, 6:10:24 PM12/13/11
to pylons-...@googlegroups.com

Hi all!

In my Pyramid app I want to implement an event system, basically for
plugins to hook to various events that raise in the life of the
application. These events are each different, some allow one hook (by
raising an exception if another hook tries to register for same event),
some many, they handle various kinds of data, etc... My approach is the
following:


class SomeEvent(EventBase):
"""Event raised in this or that condition, does X, requires Y, ..."""
HANDLERS = []

@classmethod
Register(cls, callable):
"""Decorator that registers a handler for this event."""
cls.HANDLERS.append(callable)
return callable

def __init__(self, request):
self.request = request
...

def dispatch(self):
for h in self.HANDLERS:
h(self)
...


@events.SomeEvent.Register
def some_handler(event):
...


So basically we have a plugin with a handler some_handler, which we
register for the particular event via its decorator. Now, I don't want
to reinvent the wheel, and this approach seems rather straightforward,
unit-testable and simple to implement, plus the events are then
self-documenting. I was wondering if there is a better solution, or
perhaps I can reuse some part of the Pyramid framework? ZCL?

Also, can I reuse Venusian to scan the plugins package and thus do "auto
import" of plugins at app startup time, instead of having the
requirement to manually import each plugin so that the decorators would
trigger and register the handlers (I really want the "plug and play"
solution with dropping a module in the plugins package dir and calling
it done)?


Thanks.

--

.oO V Oo.

John Anderson

unread,
Dec 13, 2011, 6:13:58 PM12/13/11
to pylons-...@googlegroups.com

Vlad K.

unread,
Dec 13, 2011, 6:25:47 PM12/13/11
to pylons-...@googlegroups.com

Ah, great, excellent, I totally forgot about this... thought they were
limited to Pyramid configuration only and failed to re-read the docs
properly. Except I don't see a way how to enforce single handler for
particular events, and raise if multiple subscribers exist. Track count
with a class member?

Thanks!

.oO V Oo.

> --
> You received this message because you are subscribed to the Google
> Groups "pylons-discuss" group.
> To post to this group, send email to pylons-...@googlegroups.com.
> To unsubscribe from this group, send email to
> pylons-discus...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/pylons-discuss?hl=en.

jerry

unread,
Dec 14, 2011, 4:11:04 AM12/14/11
to pylons-discuss
I would appreciate some confirmation/explanation on the Pyramid event
system -- is event/subscribe restricted to Pyramid running on one
physical server?

Thanks.

Jerry

On Dec 14, 7:13 am, John Anderson <son...@gmail.com> wrote:

> this is how you would create custom events:https://github.com/sontek/pyramid_signup/blob/master/pyramid_signup/e...
>
> this is how you would fire the event:https://github.com/sontek/pyramid_signup/blob/master/pyramid_signup/v...
>
> and this is how you would subscribe to the event:https://github.com/sontek/pyramid_signup/blob/master/pyramid_signup/t...

Michael Merickel

unread,
Dec 14, 2011, 4:24:05 AM12/14/11
to pylons-...@googlegroups.com
Pyramid's event system is simply the ZCA registry.

You can add subscribers to data types/interfaces, and you can notify those subscribers via the registry.

class MyEvent(object):
    pass

@subscribe(MyEvent)
def do_something(event):
    # do stuff with the event

e = MyEvent()
registry.notify(e)

where registry comes from request.registry or config.registry

Chris McDonough

unread,
Dec 14, 2011, 4:25:29 AM12/14/11
to pylons-...@googlegroups.com
On Wed, 2011-12-14 at 01:11 -0800, jerry wrote:
> I would appreciate some confirmation/explanation on the Pyramid event
> system -- is event/subscribe restricted to Pyramid running on one
> physical server?

Yes.

- C

jerry

unread,
Dec 14, 2011, 6:15:48 AM12/14/11
to pylons-discuss
Thanks Michael and Chris.

From the framework design point of view, such event system is
invaluable. But for application development, I fail to see its added
value compared to simple function call. And it makes parsing variables
harder.

E.g., I'd naively design Michael's example as --

class MyEvent(object):
def __call__(self):
do_something(v1, v2, ...)

def do_something(*args, **kw):
# do stuff

e = MyEvent()
e()

Any enlightenment will be much appreciated.

Jerry

Michael Merickel

unread,
Dec 14, 2011, 6:45:02 AM12/14/11
to pylons-...@googlegroups.com
The point of any event system is that the subscribers are decoupled from the publishers. In your example it seems you're mangling the concept of an event to mean "publish" and it's heavily coupled to the "do_something" listener.

Anyway the point is that Pyramid has a pub/sub system within it that works via the ZCA. If you don't want to use it you're more than welcome to implement your own thing. Pyramid won't care one way or the other, it just depends on your needs.

Robert Forkel

unread,
Dec 14, 2011, 6:47:43 AM12/14/11
to pylons-...@googlegroups.com
If you know the list of subscribers for each event when coding the
event, your approach works. But if you want to allow plugins or other
packages to hook into the events, it breaks down.
I'm using events to allow for configurable notification emails. Some
configurations of the application will have many of these, others
none, etc.
regards
robert

Thomas G. Willis

unread,
Dec 14, 2011, 7:42:06 AM12/14/11
to pylons-...@googlegroups.com
The event system in pyramid is simple and kicks ass.
 
I use it to do the following....

1: notify interested users about interesting things via email or sms based on their profile preferences.

2: notify the js clients  running in the browser via pubnub(http://www.pubnub.com/) of interesting things that just happened on the system(user logged in, added new comment etc...)

3: schedule a map reduce job to calculate and aggregate statistics when certain things change in the data.

All of these have one thing in common

1: an event is raised somewhere in the code that a handler receives, serializes and posts it on one or more task queues. 

2: a process on the other side is consuming messages from the queue(s) and doing all the cool stuff. 

If you are on appengine, scheduled tasks consumed by back end instances are great for this. 

If you want to go enterprisey, there's rabbitmq and you can interface with it via celery or whatever.

if you want to go the low tech route you could just write another pyramid application or set of url/view to post to to actually do the work And communicate with it through a queuing system. and restrict access to the local IP. 

or if you think the work that needs to be done is not going to substantially effect the response time(or you just don't care) you can do it in your event handlers. 

The point is, the event system does exactly what it advertises, it allows you to publish events in your app and subscribe to them with handlers in your app. The heavy lifting is done by your handlers and is only limited by your imagination, not the event system. :)


Reply all
Reply to author
Forward
0 new messages