From 58a612eaa1ff56bef3aa66ffdc89b7383868ec07 Mon Sep 17 00:00:00 2001
From: Kevin Jahns <kevin.jahns@rwth-aachen.de>
Date: Sun, 15 Nov 2015 02:04:06 +0100
Subject: [PATCH] added option for servers that want to propagate applied
 operations (aka the websockets connector)

---
 src/Connector.js   | 12 ++++++++++++
 src/Database.js    |  2 ++
 src/Transaction.js | 19 ++++++++++++++++++-
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/src/Connector.js b/src/Connector.js
index 42119593..3fa4ad2a 100644
--- a/src/Connector.js
+++ b/src/Connector.js
@@ -20,6 +20,7 @@ module.exports = function (Y) {
       } else {
         throw new Error("Role must be either 'master' or 'slave'!")
       }
+      this.y.db.forwardAppliedOperations = opts.forwardAppliedOperations || false
       this.role = opts.role
       this.connections = {}
       this.isSynced = false
@@ -221,6 +222,17 @@ module.exports = function (Y) {
             this.send(client, m)
           }
         }
+        if (this.y.db.forwardAppliedOperations) {
+          var delops = m.ops.filter(function (o) {
+            return o.struct === 'Delete'
+          })
+          if (delops.length > 0) {
+            this.broadcast({
+              type: 'update',
+              ops: delops
+            })
+          }
+        }
         this.y.db.apply(m.ops)
       }
     }
diff --git a/src/Database.js b/src/Database.js
index 051a0148..46f8f253 100644
--- a/src/Database.js
+++ b/src/Database.js
@@ -16,6 +16,8 @@ module.exports = function (Y) {
   class AbstractDatabase {
     constructor (y, opts) {
       this.y = y
+      // whether to broadcast all applied operations (insert & delete hook)
+      this.forwardAppliedOperations = false
       // E.g. this.listenersById[id] : Array<Listener>
       this.listenersById = {}
       // Execute the next time a transaction is requested
diff --git a/src/Transaction.js b/src/Transaction.js
index c9d3d82e..19b91e4f 100644
--- a/src/Transaction.js
+++ b/src/Transaction.js
@@ -104,7 +104,8 @@ module.exports = function (Y) {
         yield* this.store.tryExecute.call(this, op)
         send.push(Y.Struct[op.struct].encode(op))
       }
-      if (!this.store.y.connector.isDisconnected()) {
+      if (!this.store.y.connector.isDisconnected()) { // TODO: && !this.store.forwardAppliedOperations (but then i don't send delete ops)
+        // is connected, and this is not going to be send in addOperation
         this.store.y.connector.broadcast({
           type: 'update',
           ops: send
@@ -483,6 +484,15 @@ module.exports = function (Y) {
           yield* this.garbageCollectOperation(id)
         }
       }
+      if (this.store.forwardAppliedOperations) {
+        var ops = deletions.map(function(d){
+          return {struct: 'Delete', target: [d[0], d[1]]}
+        })
+        this.store.y.connector.broadcast({
+          type: 'update',
+          ops: ops
+        })
+      }
     }
     * isGarbageCollected (id) {
       var n = yield* this.ds.findWithUpperBound(id)
@@ -517,6 +527,13 @@ module.exports = function (Y) {
     }
     * addOperation (op) {
       yield* this.os.put(op)
+      if (!this.store.y.connector.isDisconnected() && this.store.forwardAppliedOperations) {
+        // is connected, and this is not going to be send in addOperation
+        this.store.y.connector.broadcast({
+          type: 'update',
+          ops: [op]
+        })
+      }
     }
     * getOperation (id) {
       return yield* this.os.find(id)
-- 
GitLab