diff --git a/lib/AppForServer.js b/lib/AppForServer.js index 7d5211c3..2910bd4a 100644 --- a/lib/AppForServer.js +++ b/lib/AppForServer.js @@ -340,15 +340,37 @@ AppForServer.prototype._updateScriptViews = function() { }; AppForServer.prototype._autoRefresh = function(backend) { - var agents = this.agents = {}; + this.agents = {}; var app = this; + // Auto-refresh is implemented on top of ShareDB's messaging layer. + // + // However, ShareDB wasn't originally designed to support custom message types, so ShareDB's + // Agent class will log out "Invalid or unknown message" warnings if it encounters a message + // it doesn't recognize. + // + // A workaround is to register a "receive" middleware, which fires when a ShareDB server + // receives a message from a client. If the message is Derby-related, the middleware will + // "exit" the middleware chain early by not calling `next()`. That way, the custom message never + // gets to the ShareDB Agent and won't result in warnings. + // + // However, multiple Derby apps can run together on the same ShareDB backend, each adding a + // "receive" middleware, and they all need to be notified of incoming Derby messages. This + // solution combines the exit-early approach with a custom event to accomplish that. backend.use('receive', function(request, next) { var data = request.data; if (data.derby) { - app._handleMessage(request.agent, data.derby, data); + // Derby-related message, emit custom event and "exit" middleware chain early. + backend.emit('derby:_messageReceived', request.agent, data.derby, data); + return; + } else { + // Not a Derby-related message, pass to next middleware. + next(); } - next(); + }); + + backend.on('derby:_messageReceived', function(agent, action, message) { + app._handleMessage(agent, action, message); }); };