diff --git a/services/real-time/app/coffee/DocumentUpdaterController.coffee b/services/real-time/app/coffee/DocumentUpdaterController.coffee index 3de0becfc9..e74b01259b 100644 --- a/services/real-time/app/coffee/DocumentUpdaterController.coffee +++ b/services/real-time/app/coffee/DocumentUpdaterController.coffee @@ -24,7 +24,7 @@ module.exports = DocumentUpdaterController = if client.id == update.meta.source logger.log doc_id: doc_id, version: update.v, source: update.meta?.source, "distributing update to sender" client.emit "otUpdateApplied", v: update.v, doc: update.doc - else + else if !update.dup # Duplicate ops should just be sent back to sending client for acknowledgement logger.log doc_id: doc_id, version: update.v, source: update.meta?.source, client_id: client.id, "distributing update to collaborator" client.emit "otUpdateApplied", update diff --git a/services/real-time/test/unit/coffee/DocumentUpdaterControllerTests.coffee b/services/real-time/test/unit/coffee/DocumentUpdaterControllerTests.coffee index 479231743c..186b493669 100644 --- a/services/real-time/test/unit/coffee/DocumentUpdaterControllerTests.coffee +++ b/services/real-time/test/unit/coffee/DocumentUpdaterControllerTests.coffee @@ -68,24 +68,43 @@ describe "DocumentUpdaterController", -> doc: @doc_id @io.sockets = clients: sinon.stub().returns([@sourceClient, @otherClients...]) - @EditorUpdatesController._applyUpdateFromDocumentUpdater @io, @doc_id, @update + + describe "normally", -> + beforeEach -> + @EditorUpdatesController._applyUpdateFromDocumentUpdater @io, @doc_id, @update - it "should send a version bump to the source client", -> - @sourceClient.emit - .calledWith("otUpdateApplied", v: @version, doc: @doc_id) - .should.equal true - - it "should get the clients connected to the document", -> - @io.sockets.clients - .calledWith(@doc_id) - .should.equal true - - it "should send the full update to the other clients", -> - for client in @otherClients - client.emit - .calledWith("otUpdateApplied", @update) + it "should send a version bump to the source client", -> + @sourceClient.emit + .calledWith("otUpdateApplied", v: @version, doc: @doc_id) .should.equal true + it "should get the clients connected to the document", -> + @io.sockets.clients + .calledWith(@doc_id) + .should.equal true + + it "should send the full update to the other clients", -> + for client in @otherClients + client.emit + .calledWith("otUpdateApplied", @update) + .should.equal true + + describe "with a duplicate op", -> + beforeEach -> + @update.dup = true + @EditorUpdatesController._applyUpdateFromDocumentUpdater @io, @doc_id, @update + + it "should send a version bump to the source client as usual", -> + @sourceClient.emit + .calledWith("otUpdateApplied", v: @version, doc: @doc_id) + .should.equal true + + it "should not send anything to the other clients (they've already had the op)", -> + for client in @otherClients + client.emit + .calledWith("otUpdateApplied") + .should.equal false + describe "_processErrorFromDocumentUpdater", -> beforeEach -> @clients = [new MockClient(), new MockClient()]