Example #1
0
class EventController:
    """ Uses simple Redis lists to build a broadcast event mechanism. 
        Since we're not using persistent connections, PubSub isn't an option. """
    
    def __init__(self, settings):
        self.redis = RedisClient(**settings.redis)
        self.client_timeout = 120
        self.event_timeout = 60
        random.seed()


    def add_client(self, client_id):
        self.redis.hset("dash:clients", client_id, time.time())
        # create a new initialization event
        self.redis.setex("event:%s" % client_id, self.event_timeout,
                         json.dumps({'event': 'client-id', 'data': client_id}))
        # ...and add a reference to it to a new client queue
        self.redis.rpush("client:%s" % client_id, client_id)


    def del_client(self, client_id):
        return self.redis.hdel("dash:clients", client_id)


    def client_alive(self, client_id):
        return self.redis.hexists("dash:clients", client_id)


    def expire_clients(self):
        clients = self.redis.hgetall("dash:clients")
        if not clients:
            return
        i = iter(clients)
        clients = dict(itertools.izip(i,i))
        now = time.time()
        for k in clients.keys():
            if float(clients[k]) < (now - self.client_timeout):
                self.redis.hdel("dash:clients", k)
                self.redis.delete("client:%s" % k)


    def add_event(self, event_name, event_data):
        clients = self.redis.hgetall("dash:clients")
        if not clients:
            return
        if not random.randint(0,3):
            self.expire_clients()
        event_id = str(uuid.uuid4())
        # store the event data
        self.redis.setex("event:%s" % event_id,
                         self.event_timeout,
                         json.dumps({
                             'event': event_name,
                             'data' : event_data
                         }))
        # propagate it to all clients
        clients = self.redis.hkeys("dash:clients")
        if clients:
            for client_id in clients:
                self.redis.rpush("client:%s" % client_id, event_id)


    def get_events_for_client(self, client_id):
        count = self.redis.llen("client:%s" % client_id)
        if not count:
            return

        for i in xrange(count):

            # pop each ID from the queue
            event_id = self.redis.lpop("client:%s" % client_id) 

            if not event_id:
                break

            # grab the corresponding data
            buf = self.redis.get("event:%s" % event_id)

            try:
                event = json.loads(buf)
                event.update({'id': event_id})
                yield event
            except Exception as e:
                log.warn("Could not parse '%s' as JSON" % buf)
                break
Example #2
0
class EventController:
    """ Uses simple Redis lists to build a broadcast event mechanism. 
        Since we're not using persistent connections, PubSub isn't an option. """

    def __init__(self, settings):
        self.redis = RedisClient(**settings.redis)
        self.client_timeout = 120
        self.event_timeout = 60
        random.seed()

    def add_client(self, client_id):
        self.redis.hset("dash:clients", client_id, time.time())
        # create a new initialization event
        self.redis.setex(
            "event:%s" % client_id, self.event_timeout, json.dumps({"event": "client-id", "data": client_id})
        )
        # ...and add a reference to it to a new client queue
        self.redis.rpush("client:%s" % client_id, client_id)

    def del_client(self, client_id):
        return self.redis.hdel("dash:clients", client_id)

    def client_alive(self, client_id):
        return self.redis.hexists("dash:clients", client_id)

    def expire_clients(self):
        clients = self.redis.hgetall("dash:clients")
        if not clients:
            return
        i = iter(clients)
        clients = dict(itertools.izip(i, i))
        now = time.time()
        for k in clients.keys():
            if float(clients[k]) < (now - self.client_timeout):
                self.redis.hdel("dash:clients", k)
                self.redis.delete("client:%s" % k)

    def add_event(self, event_name, event_data):
        clients = self.redis.hgetall("dash:clients")
        if not clients:
            return
        if not random.randint(0, 3):
            self.expire_clients()
        event_id = str(uuid.uuid4())
        # store the event data
        self.redis.setex(
            "event:%s" % event_id, self.event_timeout, json.dumps({"event": event_name, "data": event_data})
        )
        # propagate it to all clients
        clients = self.redis.hkeys("dash:clients")
        if clients:
            for client_id in clients:
                self.redis.rpush("client:%s" % client_id, event_id)

    def get_events_for_client(self, client_id):
        count = self.redis.llen("client:%s" % client_id)
        if not count:
            return

        for i in xrange(count):

            # pop each ID from the queue
            event_id = self.redis.lpop("client:%s" % client_id)

            if not event_id:
                break

            # grab the corresponding data
            buf = self.redis.get("event:%s" % event_id)

            try:
                event = json.loads(buf)
                event.update({"id": event_id})
                yield event
            except Exception as e:
                log.warn("Could not parse '%s' as JSON" % buf)
                break