[Twisted-Python] Event dispatcher example and deferreds

Qvx 3000 qvx3000 at gmail.com
Mon Apr 18 16:11:59 MDT 2005


Consider the following twisted example::

class Event:
    def _parse ...
    def __str__ ...

class EventChannel(basic.Int32StringReceiver):
    def connectionMade(self):
        self.factory.eventConnectionMade(self)
    def connectionLost(self, reason):
        self.factory.eventConnectionLost(self, reason)
    def stringReceived(self, recd):
        event = Event._parse(recd)
        self.factory.eventReceived(self, event)
    def sendEvent(self, devent):
        devent.addCallback(lambda e: self.sendString(str(e)))

class EventService(service.Service):

    def __init__ (self):
        self.registry = {}
        self.clients = {}
        self.funcs = dict(bind=self._bind, unbind=self._unbind)

    def getEventFactory(self):
        f = protocol.ServerFactory()
        f.protocol = EventChannel
        f.eventConnectionMade = self.eventConnectionMade
        f.eventReceived       = self.eventReceived
        f.eventConnectionLost = self.eventConnectionLost
        return f

    def eventConnectionMade(self, proto):
        self.clients[id(proto)] = proto

    def eventReceived(self, proto, event):
        func = self.funcs.get(event.name, self._notify)
        func(event)

    def eventConnectionLost(self, proto, reason):
        # remove from list of clients
        if self.clients[id(proto)] == proto:
            del self.clients[id(proto)]
        # remove from registry
        for event_name, protos in self.registry.items():
            if proto in protos:
                protos.remove(proto)

    def _bind (self, event, proto):
        current = self.registry.setdefault(event.event_name, [])
        if proto not in current:
            current.append(proto)

    def _unbind (self, event, proto):
        protos = self.registry.get(event.event_name, [])
        if proto in protos:
            protos.remove(proto)

    def _notify (self, event):
        current = self.registry.get(event.name, [])
        for proto in current:
            #if proto connected:
            proto.sendEvent(defer.succeed(event))


This is a simple event dispatching service. 

It receives connections from clients (channels). Upon receiving new connection
service remembers the connection. Each connection can bind to specific event(s).
This is achieved by sending <bind> event. After the client binds to event, it
will receive event notifications whenever a dispatcher receives such events 
from any client.
It is similar to GUI messaging systems.


I have a few questions:

1. Do I have to use deferreds? And more importantly - HOW? 
I am worried that one slow connection could have impact on other connections.
I definitely want to avoid this.
(service is only dispatching events - there are no DB or filesystem operations)

2. What if I try to send event to recently closed channel of which I am 
not aware yet (connectionLost could be inside a long queue perhaps 
- am I talking any sense?).

3. How can I assign some kind of ID to automagically created EventChannel? 
I guess id(obj) is not good enough.

4. I'm curious: is there any limit to the number of open connections? 
Could twisted on Windows handle 10,000 or even 100,000 concurrent connections?
(I will test this, but maybe somebody has some kind of real life example)

Thanks,
Qvx




More information about the Twisted-Python mailing list