diff --git a/lib/models.py b/lib/models.py index d391be1..239f404 100644 --- a/lib/models.py +++ b/lib/models.py @@ -108,7 +108,9 @@ class Subject(db.Model): subject = cls.get_by_key_name(name) if subject: return subject - return cls(key_name=name).put() + subject = cls(key_name=name) + subject.put() + return subject @db.transactional() def GetRecentMessages(self, num_messages): diff --git a/static/cosmopolite.js b/static/cosmopolite.js index a86f20d..6109d85 100644 --- a/static/cosmopolite.js +++ b/static/cosmopolite.js @@ -38,6 +38,8 @@ Cosmopolite = function(callbacks, urlPrefix, namespace) { this.urlPrefix_ = urlPrefix || '/cosmopolite'; this.namespace_ = namespace || 'cosmopolite'; + this.shutdown_ = false; + this.subscriptions_ = {}; var scriptUrls = [ @@ -53,6 +55,18 @@ Cosmopolite = function(callbacks, urlPrefix, namespace) { }, this); }; +Cosmopolite.prototype.shutdown = function() { + this.shutdown_ = true; + if (this.socket_) { + var socket = this.socket_; + this.socket_ = null; + socket.close(); + } + if (this.$) { + this.$('window').off('message'); + } +}; + /** * Subscribe to a subject. * @@ -141,8 +155,15 @@ Cosmopolite.prototype.onLoad_ = function() { return; } this.$ = jQuery.noConflict(true); + if (this.shutdown_) { + // Shutdown during startup + return; + } this.registerMessageHandlers_(); this.createChannel_(); + if ('onReady' in this.callbacks_) { + this.callbacks_['onReady'](); + }; }; /** @@ -153,13 +174,13 @@ Cosmopolite.prototype.onLoad_ = function() { Cosmopolite.prototype.onReceiveMessage_ = function(data) { switch (data) { case 'login_complete': - this.socket.close(); + this.socket_.close(); break; case 'logout_complete': localStorage.removeItem(this.namespace_ + ':client_id'); localStorage.removeItem(this.namespace_ + ':google_user_id'); this.$('#google_user').empty(); - this.socket.close(); + this.socket_.close(); break; default: console.log('Unknown event type:', data); @@ -311,9 +332,12 @@ Cosmopolite.prototype.createChannel_ = function() { * @param {!Object} data Server response including channel token */ Cosmopolite.prototype.onCreateChannel_ = function(data) { + if (this.shutdown_) { + return; + } var channel = new goog.appengine.Channel(data['token']); console.log('Opening channel...'); - this.socket = channel.open({ + this.socket_ = channel.open({ onopen: this.$.proxy(this.onSocketOpen_, this), onclose: this.$.proxy(this.onSocketClose_, this), onmessage: this.$.proxy(this.onSocketMessage_, this), @@ -332,11 +356,11 @@ Cosmopolite.prototype.onSocketOpen_ = function() { * Callback from channel library for closure; reopen. */ Cosmopolite.prototype.onSocketClose_ = function() { - if (!this.socket) { + if (!this.socket_) { return; } console.log('Channel closed'); - this.socket = null; + this.socket_ = null; this.createChannel_(); }; @@ -405,7 +429,7 @@ Cosmopolite.prototype.onServerEvent_ = function(e) { */ Cosmopolite.prototype.onSocketError_ = function(msg) { console.log('Socket error:', msg); - this.socket.close(); + this.socket_.close(); }; /* Exported values */ diff --git a/static/debug.html b/static/debug.html index 743efb2..ddd5f9f 100644 --- a/static/debug.html +++ b/static/debug.html @@ -1,6 +1,6 @@
- +