From 1d2a6f7f0ee703abd84da8a720eda222c5fc1aa2 Mon Sep 17 00:00:00 2001 From: Damien Churchill Date: Wed, 17 Feb 2010 01:50:05 +0000 Subject: [PATCH] implement a better remote events system --- deluge/ui/web/js/deluge-all/Deluge.Events.js | 30 ++++++++++++-------- deluge/ui/web/json_api.py | 24 +++++++++++++--- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/deluge/ui/web/js/deluge-all/Deluge.Events.js b/deluge/ui/web/js/deluge-all/Deluge.Events.js index 858778164..c5d7912bb 100644 --- a/deluge/ui/web/js/deluge-all/Deluge.Events.js +++ b/deluge/ui/web/js/deluge-all/Deluge.Events.js @@ -60,9 +60,10 @@ Copyright: Events.superclass.addListener.call(this, eventName, fn, scope, o); }, - poll: function() { + getEvents: function() { Deluge.Client.web.get_events({ - success: this.onPollSuccess, + success: this.onGetEventsSuccess, + failure: this.onGetEventsFailure, scope: this }); }, @@ -74,18 +75,15 @@ Copyright: Ext.each(this.toRegister, function(eventName) { Deluge.Client.web.register_event_listener(eventName); }); - this.poll = this.poll.createDelegate(this); - this.running = setInterval(this.poll, 2000); - this.poll(); + this.running = true; + this.getEvents(); }, /** * Stops the EventsManager checking for events. */ stop: function() { - if (this.running) { - clearInterval(this.running); - } + this.running = false; }, // private @@ -94,15 +92,22 @@ Copyright: this.on('PluginEnabledEvent', this.onPluginEnabled, this); this.on('PluginDisabledEvent', this.onPluginDisabled, this); }, - - // private - onPollSuccess: function(events) { + + onGetEventsSuccess: function(events) { if (!events) return; Ext.each(events, function(event) { var name = event[0], args = event[1]; args.splice(0, 0, name); this.fireEvent.apply(this, args); }, this); + if (this.running) this.getEvents(); + }, + + // private + onGetEventsFailure: function(events) { + // the request timed out so we just want to open up another + // one. + if (this.running) this.getEvents(); } }); @@ -113,7 +118,8 @@ Copyright: Events.prototype.on = Events.prototype.addListener /** - * Fires the specified event with the passed parameters (minus the event name). + * Fires the specified event with the passed parameters (minus the + * event name). * @method */ Events.prototype.fire = Events.prototype.fireEvent diff --git a/deluge/ui/web/json_api.py b/deluge/ui/web/json_api.py index 4b445f8ba..a8fbccbf6 100644 --- a/deluge/ui/web/json_api.py +++ b/deluge/ui/web/json_api.py @@ -42,6 +42,7 @@ import hashlib import tempfile from types import FunctionType +from twisted.internet import reactor from twisted.internet.defer import Deferred, DeferredList from twisted.web import http, resource, server @@ -328,6 +329,7 @@ class EventQueue(object): self.__events = {} self.__handlers = {} self.__queue = {} + self.__loopers = {} def add_listener(self, listener_id, event): """ @@ -337,7 +339,7 @@ class EventQueue(object): :type listener_id: string :param event: The event name :type event: string - """ + """ if event not in self.__events: def on_event(*args): @@ -358,12 +360,26 @@ class EventQueue(object): :param listener_id: A unique id for the listener :type listener_id: string - """ + """ + + # Check to see if we have anything to return immediately if listener_id in self.__queue: queue = self.__queue[listener_id] del self.__queue[listener_id] return queue - return None + + # Create a deferred to and check again in 100ms + d = Deferred() + reactor.callLater(0.5, self._get_events, listener_id, d) + return d + + def _get_events(self, listener_id, d): + if listener_id in self.__queue: + queue = self.__queue[listener_id] + del self.__queue[listener_id] + d.callback(queue) + else: + reactor.callLater(0.1, self._get_events, listener_id, d) def remove_listener(self, listener_id, event): """ @@ -373,7 +389,7 @@ class EventQueue(object): :type listener_id: string :param event: The event name :type event: string - """ + """ self.__events[event].remove(listener_id) if not self.__events[event]: client.deregister_event_handler(event, self.__handlers[event])