Переглянути джерело

[bugfix] prevent Websocket from failing sending messages after being closed

B Thibault 8 роки тому
батько
коміт
ef2ca22528
1 змінених файлів з 46 додано та 5 видалено
  1. 46 5
      srv/src/slack.js

+ 46 - 5
srv/src/slack.js

@@ -78,6 +78,9 @@ function Slack(slackToken, manager) {
     this.pendingPing = false;
     this.connected = false;
     this.closing = false;
+
+    /** @type {array<String>} */
+    this.queuedMessages = [];
 }
 
 Slack.prototype.getId = function() {
@@ -90,6 +93,24 @@ Slack.prototype.onRequest = function() {
     }
 };
 
+Slack.prototype.sendUnsafe = function(msg) {
+    this.rtm.send(msg);
+};
+
+Slack.prototype.send = function(msg, priority) {
+    try {
+        this.sendUnsafe(msg);
+    } catch (e) {
+        this.connected = false;
+        console.error("[SLACK] send failed");
+        if (priority)
+            this.queuedMessages.push(msg);
+        this.connect();
+        return false;
+    }
+    return true;
+};
+
 Slack.prototype.connect = function(cb) {
     var _this = this;
 
@@ -98,11 +119,13 @@ Slack.prototype.connect = function(cb) {
         if (!body || !body.ok) {
             _this.error = "Slack API error";
             _this.connected = false;
+            _this.pendingPing = false;
             console.error("Slack api responded " +status +" with body " +JSON.stringify(body));
             cb && cb(_this);
         } else if (status !== 200) {
             _this.error = body.error;
             _this.connected = false;
+            _this.pendingPing = false;
             console.error("Slack api responded " +status);
             cb && cb(_this);
         } else {
@@ -110,11 +133,13 @@ Slack.prototype.connect = function(cb) {
                 if (!channels || !channels.ok) {
                     _this.error = "Slack API error";
                     _this.connected = false;
+                    _this.pendingPing = false;
                     console.error("Slack api responded " +status +" with body " +JSON.stringify(body));
                     cb && cb(_this);
                 } else if (status !== 200) {
                     _this.error = body.error;
                     _this.connected = false;
+                    _this.pendingPing = false;
                     console.error("Slack api responded " +status);
                     cb && cb(_this);
                 } else {
@@ -169,7 +194,7 @@ Slack.prototype.sendCommand = function(room, cmd, arg) {
 }
 
 Slack.prototype.sendTyping = function(room) {
-    this.rtm.send('{"id":' +this.rtmId++ +',"type":"typing","channel":"' +room.remoteId +'"}');
+    this.send('{"id":' +this.rtmId++ +',"type":"typing","channel":"' +room.remoteId +'"}');
 }
 
 Slack.prototype.getSlashCommands = function(cb) {
@@ -234,6 +259,13 @@ Slack.prototype.unstackPendingMessages = function() {
         this.onMessage(this.pendingMessages[0], Date.now());
         this.pendingMessages.shift();
     }
+    while (this.queuedMessages.length) {
+        if (this.send(this.queuedMessages[0])) {
+            this.queuedMessages.shift();
+        } else {
+            break;
+        }
+    }
 };
 
 Slack.prototype.resetVersions = function(v) {
@@ -348,6 +380,7 @@ Slack.prototype.connectRtm = function(url, cb) {
     });
     this.rtm.once("error", function(e) {
         _this.connected = false;
+        _this.pendingPing = false;
         console.error(e);
         _this.close();
     });
@@ -372,13 +405,21 @@ Slack.prototype.rtmPing = function() {
             // We could use reconect_url, but we could have missed something important,
             // so we restart all over again
             this.connected = false;
+            this.pendingPing = false;
             console.error("[SLACK] Ping timeout");
             this.connect();
         } else {
             var rtmId = this.rtmId++;
-            this.pendingRtm[rtmId] = { type: 'ping' };
-            this.pendingPing = rtmId;
-            this.rtm.send('{"id":' +rtmId +',"type":"ping"}');
+            try {
+                this.sendUnsafe('{"id":' +rtmId +',"type":"ping"}');
+                this.pendingRtm[rtmId] = { type: 'ping' };
+                this.pendingPing = rtmId;
+            } catch (e) {
+                this.connected = false;
+                this.pendingPing = false;
+                console.error("[SLACK] Ping timeout");
+                this.connect();
+            }
         }
     }
 };
@@ -723,7 +764,7 @@ Slack.prototype.sendMsg = function(channel, text, attachments) {
             user: this.data.self.remoteId,
             text: fullDecodedText
         };
-        this.rtm.send('{"id":' +this.rtmId++ +',"type":"message","channel":"' +channel.remoteId +'", "text":' +JSON.stringify(fullDecodedText) +'}');
+        this.send('{"id":' +this.rtmId++ +',"type":"message","channel":"' +channel.remoteId +'", "text":' +JSON.stringify(fullDecodedText) +'}', true);
         return fullDecodedText;
     }
 };