added eventhandler
This commit is contained in:
		
							parent
							
								
									8e9e62b3d0
								
							
						
					
					
						commit
						8cc374cabb
					
				@ -8,7 +8,7 @@
 | 
				
			|||||||
    "no-underscore-dangle": 0,
 | 
					    "no-underscore-dangle": 0,
 | 
				
			||||||
    "no-constant-condition": 0,
 | 
					    "no-constant-condition": 0,
 | 
				
			||||||
    "no-empty": 0,
 | 
					    "no-empty": 0,
 | 
				
			||||||
    "new-cap": [2, { "capIsNewExceptions": ["List"] }],
 | 
					    "new-cap": [2, { "capIsNewExceptions": ["List", "Y"] }],
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "parser": "babel-eslint",
 | 
					  "parser": "babel-eslint",
 | 
				
			||||||
  "globals": {
 | 
					  "globals": {
 | 
				
			||||||
@ -27,6 +27,7 @@
 | 
				
			|||||||
    "setInterval": true,
 | 
					    "setInterval": true,
 | 
				
			||||||
    "Operation": true,
 | 
					    "Operation": true,
 | 
				
			||||||
    "getRandom": true,
 | 
					    "getRandom": true,
 | 
				
			||||||
    "RBTree": true
 | 
					    "RBTree": true,
 | 
				
			||||||
 | 
					    "compareIds": true
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -9,15 +9,15 @@ class AbstractTransaction { //eslint-disable-line no-unused-vars
 | 
				
			|||||||
    if (t == null) {
 | 
					    if (t == null) {
 | 
				
			||||||
      var op = yield* this.getOperation(id);
 | 
					      var op = yield* this.getOperation(id);
 | 
				
			||||||
      if (op != null) {
 | 
					      if (op != null) {
 | 
				
			||||||
        t = new Y[op.type].Create(op.id);
 | 
					        t = yield* Y[op.type].create(this.store, op.id);
 | 
				
			||||||
        this.store.initializedTypes[sid] = t;
 | 
					        this.store.initializedTypes[sid] = t;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return t;
 | 
					    return t;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  createType (model) {
 | 
					  *createType (model) {
 | 
				
			||||||
    var sid = JSON.stringify(model.id);
 | 
					    var sid = JSON.stringify(model.id);
 | 
				
			||||||
    var t = new Y[model.type].Create(model.id);
 | 
					    var t = yield* Y[model.type].create(this.store, model);
 | 
				
			||||||
    this.store.initializedTypes[sid] = t;
 | 
					    this.store.initializedTypes[sid] = t;
 | 
				
			||||||
    return t;
 | 
					    return t;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -40,9 +40,8 @@ var Struct = {
 | 
				
			|||||||
      var user = this.store.y.connector.userId;
 | 
					      var user = this.store.y.connector.userId;
 | 
				
			||||||
      var state = yield* this.getState(user);
 | 
					      var state = yield* this.getState(user);
 | 
				
			||||||
      op.id = [user, state.clock];
 | 
					      op.id = [user, state.clock];
 | 
				
			||||||
      if ((yield* this.addOperation(op)) === false) {
 | 
					      yield* Struct[op.struct].execute.call(this, op);
 | 
				
			||||||
        throw new Error("This is highly unexpected :(");
 | 
					
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      this.store.y.connector.broadcast({
 | 
					      this.store.y.connector.broadcast({
 | 
				
			||||||
        type: "update",
 | 
					        type: "update",
 | 
				
			||||||
        ops: [Struct[op.struct].encode(op)]
 | 
					        ops: [Struct[op.struct].encode(op)]
 | 
				
			||||||
@ -56,11 +55,7 @@ var Struct = {
 | 
				
			|||||||
        throw new Error("You must define a delete target!");
 | 
					        throw new Error("You must define a delete target!");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      op.struct = "Delete";
 | 
					      op.struct = "Delete";
 | 
				
			||||||
      yield* Struct.Operation.create.call(this, op);
 | 
					      return yield* Struct.Operation.create.call(this, op);
 | 
				
			||||||
 | 
					 | 
				
			||||||
      var target = yield* this.getOperation(op.target);
 | 
					 | 
				
			||||||
      target.deleted = true;
 | 
					 | 
				
			||||||
      yield* this.setOperation(target);
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    encode: function (op) {
 | 
					    encode: function (op) {
 | 
				
			||||||
      return op;
 | 
					      return op;
 | 
				
			||||||
@ -86,7 +81,7 @@ var Struct = {
 | 
				
			|||||||
        parentSub: string (optional)
 | 
					        parentSub: string (optional)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
    create: function*( op: Op ) : Insert {
 | 
					    create: function* ( op: Op ) : Insert {
 | 
				
			||||||
      if ( op.left === undefined
 | 
					      if ( op.left === undefined
 | 
				
			||||||
        || op.right === undefined
 | 
					        || op.right === undefined
 | 
				
			||||||
        || op.parent === undefined ) {
 | 
					        || op.parent === undefined ) {
 | 
				
			||||||
@ -94,7 +89,7 @@ var Struct = {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      op.origin = op.left;
 | 
					      op.origin = op.left;
 | 
				
			||||||
      op.struct = "Insert";
 | 
					      op.struct = "Insert";
 | 
				
			||||||
      return op;
 | 
					      return yield* Struct.Operation.create.call(this, op);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    encode: function(op){
 | 
					    encode: function(op){
 | 
				
			||||||
      /*var e = {
 | 
					      /*var e = {
 | 
				
			||||||
@ -253,11 +248,11 @@ var Struct = {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  List: {
 | 
					  List: {
 | 
				
			||||||
    create: function( op : Op){
 | 
					    create: function* ( op : Op){
 | 
				
			||||||
      op.start = null;
 | 
					      op.start = null;
 | 
				
			||||||
      op.end = null;
 | 
					      op.end = null;
 | 
				
			||||||
      op.struct = "List";
 | 
					      op.struct = "List";
 | 
				
			||||||
      return Struct.Operation.create(op);
 | 
					      return yield* Struct.Operation.create.call(this, op);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    encode: function(op){
 | 
					    encode: function(op){
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
@ -358,7 +353,7 @@ var Struct = {
 | 
				
			|||||||
        // empty
 | 
					        // empty
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
    create: function*( op : Op ){
 | 
					    create: function* ( op : Op ){
 | 
				
			||||||
      op.map = {};
 | 
					      op.map = {};
 | 
				
			||||||
      op.struct = "Map";
 | 
					      op.struct = "Map";
 | 
				
			||||||
      return yield* Struct.Operation.create.call(this, op);
 | 
					      return yield* Struct.Operation.create.call(this, op);
 | 
				
			||||||
@ -393,22 +388,6 @@ var Struct = {
 | 
				
			|||||||
                  ? res.content : yield* this.getType(res.opContent));
 | 
					                  ? res.content : yield* this.getType(res.opContent));
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    set: function* (op, name, value) {
 | 
					 | 
				
			||||||
      var right = op.map[name] || null;
 | 
					 | 
				
			||||||
      var insert = {
 | 
					 | 
				
			||||||
        left: null,
 | 
					 | 
				
			||||||
        right: right,
 | 
					 | 
				
			||||||
        parent: op.id,
 | 
					 | 
				
			||||||
        parentSub: name
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
      if ( value != null && value._model != null
 | 
					 | 
				
			||||||
           && value._model.length === 2) {
 | 
					 | 
				
			||||||
        insert.opContent = value._model;
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        insert.content = value;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      yield* Struct.Insert.create.call(this, insert);
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    delete: function* (op, name) {
 | 
					    delete: function* (op, name) {
 | 
				
			||||||
      var v = op.map[name] || null;
 | 
					      var v = op.map[name] || null;
 | 
				
			||||||
      if (v != null) {
 | 
					      if (v != null) {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										146
									
								
								src/Types/Map.js
									
									
									
									
									
								
							
							
						
						
									
										146
									
								
								src/Types/Map.js
									
									
									
									
									
								
							@ -1,36 +1,117 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					var GeneratorFunction = (function*(){}).constructor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class EventHandler {
 | 
				
			||||||
 | 
					  constructor (onevent) {
 | 
				
			||||||
 | 
					    this.waiting = [];
 | 
				
			||||||
 | 
					    this.awaiting = 0;
 | 
				
			||||||
 | 
					    this.onevent = onevent;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  receivedOp (op) {
 | 
				
			||||||
 | 
					    if (this.awaiting <= 0) {
 | 
				
			||||||
 | 
					      this.onevent([op]);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      this.waiting.push(copyObject(op));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  awaitAndPrematurelyCall (op) {
 | 
				
			||||||
 | 
					    this.awaiting++;
 | 
				
			||||||
 | 
					    this.onevent([op]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  awaitedLastOp () {
 | 
				
			||||||
 | 
					    var op = this.waiting.pop();
 | 
				
			||||||
 | 
					    for (var i = this.waiting.length - 1; i >= 0; i--) {
 | 
				
			||||||
 | 
					      var w = this.waiting[i];
 | 
				
			||||||
 | 
					      if (compareIds(op.left, w.id)) {
 | 
				
			||||||
 | 
					        // include the effect of op in w
 | 
				
			||||||
 | 
					        w.right = op.id;
 | 
				
			||||||
 | 
					        // exclude the effect of w in op
 | 
				
			||||||
 | 
					        op.left = w.left;
 | 
				
			||||||
 | 
					      } else if (compareIds(op.right, w.id)) {
 | 
				
			||||||
 | 
					        // similar..
 | 
				
			||||||
 | 
					        w.left = op.id;
 | 
				
			||||||
 | 
					        op.right = w.right;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    this.awaiting--;
 | 
				
			||||||
 | 
					    if (this.awaiting <= 0) {
 | 
				
			||||||
 | 
					      var events = this.waiting;
 | 
				
			||||||
 | 
					      this.waiting = [];
 | 
				
			||||||
 | 
					      this.onevent(events);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function(){
 | 
					(function(){
 | 
				
			||||||
  class Map {
 | 
					  class Map {
 | 
				
			||||||
    constructor (os, _model) {
 | 
					    constructor (os, model) {
 | 
				
			||||||
      this._model = _model;
 | 
					      this._model = model.id;
 | 
				
			||||||
      this.os = os;
 | 
					      this.os = os;
 | 
				
			||||||
    }
 | 
					      this.map = model.map;
 | 
				
			||||||
    val () {
 | 
					      this.contents = {};
 | 
				
			||||||
      if (arguments.length === 1) {
 | 
					      this.opContents = {};
 | 
				
			||||||
        if (this.opContents[arguments[0]] == null) {
 | 
					      this.eventHandler = new EventHandler( ops =>{
 | 
				
			||||||
          return this.contents[arguments[0]];
 | 
					        for (var i in ops) {
 | 
				
			||||||
        } else {
 | 
					          var op = ops[i];
 | 
				
			||||||
          let def = Promise.defer();
 | 
					          if (op.left === null) {
 | 
				
			||||||
          var oid = this.opContents[arguments[0]];
 | 
					            if (op.opContent != null) {
 | 
				
			||||||
          this.os.requestTransaction(function*(){
 | 
					              this.opContents[op.parentSub] = op.opContent;
 | 
				
			||||||
            def.resolve(yield* this.getType(oid));
 | 
					            } else {
 | 
				
			||||||
          });
 | 
					              this.contents[op.parentSub] = op.content;
 | 
				
			||||||
          return def.promise;
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } else if (arguments.length === 2) {
 | 
					      });
 | 
				
			||||||
        var key = arguments[0];
 | 
					    }
 | 
				
			||||||
        var value = arguments[1];
 | 
					    get (key) {
 | 
				
			||||||
 | 
					      // return property.
 | 
				
			||||||
 | 
					      // if property does not exist, return null
 | 
				
			||||||
 | 
					      // if property is a type, return a promise
 | 
				
			||||||
 | 
					      if (this.opContents[key] == null) {
 | 
				
			||||||
 | 
					        return this.contents[key];
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
        let def = Promise.defer();
 | 
					        let def = Promise.defer();
 | 
				
			||||||
        var _model = this._model;
 | 
					        var oid = this.opContents[key];
 | 
				
			||||||
        this.os.requestTransaction(function*(){
 | 
					        this.os.requestTransaction(function*(){
 | 
				
			||||||
          var model = yield* this.getOperation(_model);
 | 
					          def.resolve(yield* this.getType(oid));
 | 
				
			||||||
          def.resolve(yield* Y.Struct.Map.set.call(this, model, key, value));
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        return def.promise;
 | 
					        return def.promise;
 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        throw new Error("Implement this case!");
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    set (key, value) {
 | 
				
			||||||
 | 
					      // set property.
 | 
				
			||||||
 | 
					      // if property is a type, return a promise
 | 
				
			||||||
 | 
					      // if not, apply immediately on this type an call event
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var right = this.map[key] || null;
 | 
				
			||||||
 | 
					      var insert = {
 | 
				
			||||||
 | 
					        left: null,
 | 
				
			||||||
 | 
					        right: right,
 | 
				
			||||||
 | 
					        parent: this._model,
 | 
				
			||||||
 | 
					        parentSub: key
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      var def = Promise.defer();
 | 
				
			||||||
 | 
					      if ( value != null && value.constructor === GeneratorFunction) {
 | 
				
			||||||
 | 
					        // construct a new type
 | 
				
			||||||
 | 
					        this.os.requestTransaction(function*(){
 | 
				
			||||||
 | 
					          var type = yield* value.call(this);
 | 
				
			||||||
 | 
					          insert.opContent = type._model;
 | 
				
			||||||
 | 
					          yield* Struct.Insert.create.call(this, insert);
 | 
				
			||||||
 | 
					          def.resolve(type);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        insert.content = value;
 | 
				
			||||||
 | 
					        var eventHandler = this.eventHandler;
 | 
				
			||||||
 | 
					        eventHandler.awaitAndPrematurelyCall(insert);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.os.requestTransaction(function*(){
 | 
				
			||||||
 | 
					          yield* Struct.Insert.create.call(this, insert);
 | 
				
			||||||
 | 
					          eventHandler.awaitedLastOp();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        def.resolve(value);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return def.promise;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
    *delete (key) {
 | 
					    *delete (key) {
 | 
				
			||||||
      var t = yield "transaction";
 | 
					      var t = yield "transaction";
 | 
				
			||||||
@ -38,24 +119,15 @@
 | 
				
			|||||||
      yield* Y.Struct.Map.delete.call(t, model, key);
 | 
					      yield* Y.Struct.Map.delete.call(t, model, key);
 | 
				
			||||||
    }*/
 | 
					    }*/
 | 
				
			||||||
    _changed (op) {
 | 
					    _changed (op) {
 | 
				
			||||||
      if (op.left === null) {
 | 
					      this.eventHandler.receivedOp(op);
 | 
				
			||||||
        if (op.opContent != null) {
 | 
					 | 
				
			||||||
          this.opContents[op.parentSub] = op.opContent;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          this.contents[op.parentSub] = op.opContent;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Y.Map = function* YMap(){
 | 
					  Y.Map = function* YMap(){
 | 
				
			||||||
    var t = yield "transaction";
 | 
					    var model = yield* Y.Struct.Map.create.call(this, {type: "Map"});
 | 
				
			||||||
    if (this instanceof Y.AbstractOperationStore) {
 | 
					    return yield* this.createType(model);
 | 
				
			||||||
      var model = yield* Y.Struct.map.create.call(t, {type: "Map"});
 | 
					  };
 | 
				
			||||||
      return t.createType(model);
 | 
					  Y.Map.create = function* YMapCreate(os, model){
 | 
				
			||||||
    } else {
 | 
					    return new Map(os, model);
 | 
				
			||||||
      throw new Error("Don't use `new` to create this type!");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  Y.Map.Create = Map;
 | 
					 | 
				
			||||||
})();
 | 
					})();
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										23
									
								
								src/y.js
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								src/y.js
									
									
									
									
									
								
							@ -1,11 +1,18 @@
 | 
				
			|||||||
/* @flow */
 | 
					/* @flow */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const GeneratorFunction = (function*(){}).constructor;
 | 
					function Y (opts) {
 | 
				
			||||||
 | 
					  var def = Promise.defer();
 | 
				
			||||||
 | 
					  new YConfig(opts, function(config){ //eslint-disable-line
 | 
				
			||||||
 | 
					    def.resolve(config);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  return def.promise;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Y { //eslint-disable-line no-unused-vars
 | 
					class YConfig { //eslint-disable-line no-unused-vars
 | 
				
			||||||
  constructor (opts) {
 | 
					  constructor (opts, callback) {
 | 
				
			||||||
    this.db = new Y[opts.db.name](this, opts.db);
 | 
					    this.db = new Y[opts.db.name](this, opts.db);
 | 
				
			||||||
    this.connector = new Y[opts.connector.name](this, opts.connector);
 | 
					    this.connector = new Y[opts.connector.name](this, opts.connector);
 | 
				
			||||||
 | 
					    var yconfig = this;
 | 
				
			||||||
    this.db.requestTransaction(function*(){
 | 
					    this.db.requestTransaction(function*(){
 | 
				
			||||||
      // create initial Map type
 | 
					      // create initial Map type
 | 
				
			||||||
      var model = {
 | 
					      var model = {
 | 
				
			||||||
@ -15,15 +22,11 @@ class Y { //eslint-disable-line no-unused-vars
 | 
				
			|||||||
        map: {}
 | 
					        map: {}
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      yield* this.addOperation(model);
 | 
					      yield* this.addOperation(model);
 | 
				
			||||||
      this.createType(model);
 | 
					      var root = yield* this.createType(model);
 | 
				
			||||||
 | 
					      this.store.y.root = root;
 | 
				
			||||||
 | 
					      callback(yconfig);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  transact (generator) {
 | 
					 | 
				
			||||||
    if (generator.constructor !== GeneratorFunction) {
 | 
					 | 
				
			||||||
      throw new Error("y.transact requires a Generator function! E.g. function*(){/*..*/}");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    this.db.requestTransaction(generator);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  destroy () {
 | 
					  destroy () {
 | 
				
			||||||
    this.connector.disconnect();
 | 
					    this.connector.disconnect();
 | 
				
			||||||
    this.db.removeDatabase();
 | 
					    this.db.removeDatabase();
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										279
									
								
								src/y.spec.js
									
									
									
									
									
								
							
							
						
						
									
										279
									
								
								src/y.spec.js
									
									
									
									
									
								
							@ -24,9 +24,9 @@ function getRandomNumber(n) {
 | 
				
			|||||||
var numberOfYMapTests = 30;
 | 
					var numberOfYMapTests = 30;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function applyRandomTransactions (users, transactions, numberOfTransactions) {
 | 
					function applyRandomTransactions (users, transactions, numberOfTransactions) {
 | 
				
			||||||
  function* randomTransaction (root) {
 | 
					  function randomTransaction (root) {
 | 
				
			||||||
    var f = getRandom(transactions);
 | 
					    var f = getRandom(transactions);
 | 
				
			||||||
    yield* f(root);
 | 
					    f(root);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  for(var i = 0; i < numberOfTransactions; i++) {
 | 
					  for(var i = 0; i < numberOfTransactions; i++) {
 | 
				
			||||||
    var r = Math.random();
 | 
					    var r = Math.random();
 | 
				
			||||||
@ -34,7 +34,7 @@ function applyRandomTransactions (users, transactions, numberOfTransactions) {
 | 
				
			|||||||
      // 10% chance to flush
 | 
					      // 10% chance to flush
 | 
				
			||||||
      users[0].connector.flushOne();
 | 
					      users[0].connector.flushOne();
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      getRandom(users).transact(randomTransaction);
 | 
					      randomTransaction(getRandom(users).root);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -51,8 +51,8 @@ function compareAllUsers(users){
 | 
				
			|||||||
  for (var uid = 0; uid + 1 < users.length; uid++) {
 | 
					  for (var uid = 0; uid + 1 < users.length; uid++) {
 | 
				
			||||||
    var u1 = users[uid];
 | 
					    var u1 = users[uid];
 | 
				
			||||||
    var u2 = users[uid + 1];
 | 
					    var u2 = users[uid + 1];
 | 
				
			||||||
    u1.transact(t1);
 | 
					    u1.db.requestTransaction(t1);
 | 
				
			||||||
    u2.transact(t2);
 | 
					    u2.db.requestTransaction(t2);
 | 
				
			||||||
    expect(s1).toEqual(s2);
 | 
					    expect(s1).toEqual(s2);
 | 
				
			||||||
    var db1 = [];
 | 
					    var db1 = [];
 | 
				
			||||||
    var db2 = [];
 | 
					    var db2 = [];
 | 
				
			||||||
@ -71,10 +71,17 @@ function compareAllUsers(users){
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
describe("Yjs", function(){
 | 
					describe("Yjs", function(){
 | 
				
			||||||
  jasmine.DEFAULT_TIMEOUT_INTERVAL = 500;
 | 
					  jasmine.DEFAULT_TIMEOUT_INTERVAL = 500;
 | 
				
			||||||
  beforeEach(function(){
 | 
					  beforeEach(function(done){
 | 
				
			||||||
 | 
					    if (this.users != null) {
 | 
				
			||||||
 | 
					      for (var y of this.users) {
 | 
				
			||||||
 | 
					        y.destroy();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    this.users = [];
 | 
					    this.users = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var promises = [];
 | 
				
			||||||
    for (var i = 0; i < 5; i++) {
 | 
					    for (var i = 0; i < 5; i++) {
 | 
				
			||||||
      this.users.push(new Y({
 | 
					      promises.push(Y({
 | 
				
			||||||
        db: {
 | 
					        db: {
 | 
				
			||||||
          name: "Memory"
 | 
					          name: "Memory"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
@ -84,205 +91,142 @@ describe("Yjs", function(){
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }));
 | 
					      }));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  });
 | 
					    Promise.all(promises).then( users => {
 | 
				
			||||||
  afterEach(function(){
 | 
					      this.users = users;
 | 
				
			||||||
    for (var y of this.users) {
 | 
					      done();
 | 
				
			||||||
      y.destroy();
 | 
					    });
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    this.users = [];
 | 
					 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe("Basic tests", function(){
 | 
					  describe("Basic tests", function(){
 | 
				
			||||||
    it("There is an initial Map type & it is created only once", function(){
 | 
					 | 
				
			||||||
      var y = this.users[0];
 | 
					 | 
				
			||||||
      var root1;
 | 
					 | 
				
			||||||
      y.transact(function*(root){
 | 
					 | 
				
			||||||
        expect(root).not.toBeUndefined();
 | 
					 | 
				
			||||||
        root1 = root;
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      y.transact(function*(root2){
 | 
					 | 
				
			||||||
        expect(root1).toBe(root2);
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    it("Custom Types are created only once", function(){
 | 
					 | 
				
			||||||
      var y = this.users[0];
 | 
					 | 
				
			||||||
      var l1;
 | 
					 | 
				
			||||||
      y.transact(function*(root){
 | 
					 | 
				
			||||||
        var l = yield* Y.List();
 | 
					 | 
				
			||||||
        yield* root.val("list", l);
 | 
					 | 
				
			||||||
        l1 = l;
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      y.transact(function*(root){
 | 
					 | 
				
			||||||
        expect(l1).toBe(yield* root.val("list"));
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    it("Basic get&set of Map property (converge via sync)", function(){
 | 
					    it("Basic get&set of Map property (converge via sync)", function(){
 | 
				
			||||||
      var y = this.users[0];
 | 
					      var y = this.users[0].root;
 | 
				
			||||||
      y.transact(function*(root){
 | 
					      y.set("stuff", "stuffy");
 | 
				
			||||||
        yield* root.val("stuff", "stuffy");
 | 
					      expect(y.get("stuff")).toEqual("stuffy");
 | 
				
			||||||
        expect(yield* root.val("stuff")).toEqual("stuffy");
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      y.connector.flushAll();
 | 
					      this.users[0].connector.flushAll();
 | 
				
			||||||
 | 
					 | 
				
			||||||
      var transaction = function*(root){
 | 
					 | 
				
			||||||
        expect(yield* root.val("stuff")).toEqual("stuffy");
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
      for (var key in this.users) {
 | 
					 | 
				
			||||||
        var u = this.users[key];
 | 
					 | 
				
			||||||
        u.transact(transaction);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    it("Basic get&set of Map property (converge via update)", function(){
 | 
					 | 
				
			||||||
      var y = this.users[0];
 | 
					 | 
				
			||||||
      y.connector.flushAll();
 | 
					 | 
				
			||||||
      y.transact(function*(root){
 | 
					 | 
				
			||||||
        yield* root.val("stuff", "stuffy");
 | 
					 | 
				
			||||||
        expect(yield* root.val("stuff")).toEqual("stuffy");
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      var transaction = function*(root){
 | 
					 | 
				
			||||||
        expect(yield* root.val("stuff")).toEqual("stuffy");
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
      y.connector.flushAll();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      for (var key in this.users) {
 | 
					      for (var key in this.users) {
 | 
				
			||||||
        var u = this.users[key];
 | 
					        var u = this.users[key].root;
 | 
				
			||||||
        u.transact(transaction);
 | 
					        expect(u.get("stuff")).toEqual("stuffy");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      compareAllUsers(this.users);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it("Basic get&set of Map property (handle conflict)", function(){
 | 
					    it("Map can set custom types (Map)", function(done){
 | 
				
			||||||
 | 
					      var y = this.users[0].root;
 | 
				
			||||||
 | 
					      y.set("Map", Y.Map).then(function(map) {
 | 
				
			||||||
 | 
					        map.set("one", 1);
 | 
				
			||||||
 | 
					        return y.get("Map");
 | 
				
			||||||
 | 
					      }).then(function(map){
 | 
				
			||||||
 | 
					        expect(map.get("one")).toEqual(1);
 | 
				
			||||||
 | 
					        done();
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    it("Basic get&set of Map property (converge via update)", function(done){
 | 
				
			||||||
 | 
					      var u = this.users[0];
 | 
				
			||||||
 | 
					      u.connector.flushAll();
 | 
				
			||||||
 | 
					      var y = u.root;
 | 
				
			||||||
 | 
					      y.set("stuff", "stuffy");
 | 
				
			||||||
 | 
					      expect(y.get("stuff")).toEqual("stuffy");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      u.connector.flushAll();
 | 
				
			||||||
 | 
					      setTimeout(() => {
 | 
				
			||||||
 | 
					        for (var key in this.users) {
 | 
				
			||||||
 | 
					          var r = this.users[key].root;
 | 
				
			||||||
 | 
					          expect(r.get("stuff")).toEqual("stuffy");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        done();
 | 
				
			||||||
 | 
					      }, 50);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    it("Basic get&set of Map property (handle conflict)", function(done){
 | 
				
			||||||
      var y = this.users[0];
 | 
					      var y = this.users[0];
 | 
				
			||||||
      y.connector.flushAll();
 | 
					      y.connector.flushAll();
 | 
				
			||||||
      this.users[0].transact(function*(root){
 | 
					      y.root.set("stuff", "c0");
 | 
				
			||||||
        yield* root.val("stuff", "c0");
 | 
					
 | 
				
			||||||
      });
 | 
					      this.users[1].root.set("stuff", "c1");
 | 
				
			||||||
      this.users[1].transact(function*(root){
 | 
					 | 
				
			||||||
        yield* root.val("stuff", "c1");
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      var transaction = function*(root){
 | 
					 | 
				
			||||||
        expect(yield* root.val("stuff")).toEqual("c0");
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
      y.connector.flushAll();
 | 
					      y.connector.flushAll();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      for (var key in this.users) {
 | 
					      setTimeout( () => {
 | 
				
			||||||
        var u = this.users[key];
 | 
					        for (var key in this.users) {
 | 
				
			||||||
        u.transact(transaction);
 | 
					          var u = this.users[key];
 | 
				
			||||||
      }
 | 
					          expect(u.root.get("stuff")).toEqual("c0");
 | 
				
			||||||
 | 
					          compareAllUsers(this.users);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        done();
 | 
				
			||||||
 | 
					      }, 50);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it("Basic get&set of Map property (handle three conflicts)", function(){
 | 
					    it("Basic get&set of Map property (handle three conflicts)", function(done){
 | 
				
			||||||
      var y = this.users[0];
 | 
					      var y = this.users[0];
 | 
				
			||||||
 | 
					      this.users[0].root.set("stuff", "c0");
 | 
				
			||||||
 | 
					      this.users[1].root.set("stuff", "c1");
 | 
				
			||||||
 | 
					      this.users[2].root.set("stuff", "c2");
 | 
				
			||||||
 | 
					      this.users[3].root.set("stuff", "c3");
 | 
				
			||||||
      y.connector.flushAll();
 | 
					      y.connector.flushAll();
 | 
				
			||||||
      this.users[0].transact(function*(root){
 | 
					 | 
				
			||||||
        yield* root.val("stuff", "c0");
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      this.users[1].transact(function*(root){
 | 
					 | 
				
			||||||
        yield* root.val("stuff", "c1");
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      this.users[2].transact(function*(root){
 | 
					 | 
				
			||||||
        yield* root.val("stuff", "c2");
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      this.users[3].transact(function*(root){
 | 
					 | 
				
			||||||
        yield* root.val("stuff", "c3");
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      y.connector.flushAll();
 | 
					 | 
				
			||||||
      var transaction = function*(root){
 | 
					 | 
				
			||||||
        expect(yield* root.val("stuff")).toEqual("c0");
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      for (var key in this.users) {
 | 
					      setTimeout( () => {
 | 
				
			||||||
        var u = this.users[key];
 | 
					        for (var key in this.users) {
 | 
				
			||||||
        u.transact(transaction);
 | 
					          var u = this.users[key];
 | 
				
			||||||
      }
 | 
					          expect(u.root.get("stuff")).toEqual("c0");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        compareAllUsers(this.users);
 | 
				
			||||||
 | 
					        done();
 | 
				
			||||||
 | 
					      }, 50);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  it("Basic get&set&delete with Map property", function(){
 | 
					 | 
				
			||||||
    var y = this.users[0];
 | 
					 | 
				
			||||||
    y.connector.flushAll();
 | 
					 | 
				
			||||||
    this.users[0].transact(function*(root){
 | 
					 | 
				
			||||||
      yield* root.val("stuff", "c0");
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    this.users[0].transact(function*(root){
 | 
					 | 
				
			||||||
      yield* root.val("stuff", "c1");
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    this.users[0].transact(function*(root){
 | 
					 | 
				
			||||||
      yield* root.delete("stuff");
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    y.connector.flushAll();
 | 
					 | 
				
			||||||
    var transaction = function*(root){
 | 
					 | 
				
			||||||
      expect(yield* root.val("stuff")).toBeUndefined();
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (var key in this.users) {
 | 
					 | 
				
			||||||
      var u = this.users[key];
 | 
					 | 
				
			||||||
      u.transact(transaction);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  it("List type: can create, insert, and delete elements", function(){
 | 
					 | 
				
			||||||
    var y = this.users[0];
 | 
					 | 
				
			||||||
    y.transact(function*(root){
 | 
					 | 
				
			||||||
      var list = yield* Y.List();
 | 
					 | 
				
			||||||
      yield* root.val("list", list);
 | 
					 | 
				
			||||||
      yield* list.insert(0, [1, 2, 3, 4]);
 | 
					 | 
				
			||||||
      yield* list.delete(1);
 | 
					 | 
				
			||||||
      expect(yield* root.val("list")).not.toBeUndefined();
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    y.connector.flushAll();
 | 
					 | 
				
			||||||
    function* transaction (root) {
 | 
					 | 
				
			||||||
      var list = yield* root.val("list");
 | 
					 | 
				
			||||||
      expect(yield* list.val()).toEqual([1, 3, 4]);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    for (var u of this.users) {
 | 
					 | 
				
			||||||
      u.transact(transaction);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
  describe("Map random tests", function(){
 | 
					  describe("Map random tests", function(){
 | 
				
			||||||
    var randomMapTransactions = [
 | 
					    var randomMapTransactions = [
 | 
				
			||||||
      function* set (map) {
 | 
					      function set (map) {
 | 
				
			||||||
        yield* map.val("somekey", getRandomNumber());
 | 
					        map.set("somekey", getRandomNumber());
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      function* delete_ (map) {
 | 
					      function* delete_ (map) {
 | 
				
			||||||
        yield* map.delete("somekey");
 | 
					        map.delete("somekey");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
    it(`succeed after ${numberOfYMapTests} actions with flush before transactions`, function(){
 | 
					    function compareMapValues(users){
 | 
				
			||||||
 | 
					      var firstMap;
 | 
				
			||||||
 | 
					      for (var u of users) {
 | 
				
			||||||
 | 
					        var val = u.root.get();
 | 
				
			||||||
 | 
					        if (firstMap == null) {
 | 
				
			||||||
 | 
					          firstMap = val;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          expect(val).toEqual(firstMap);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    it(`succeed after ${numberOfYMapTests} actions with flush before transactions`, function(done){
 | 
				
			||||||
      this.users[0].connector.flushAll();
 | 
					      this.users[0].connector.flushAll();
 | 
				
			||||||
      applyRandomTransactions(this.users, randomMapTransactions, numberOfYMapTests);
 | 
					      applyRandomTransactions(this.users, randomMapTransactions, numberOfYMapTests);
 | 
				
			||||||
      compareAllUsers(this.users);
 | 
					      setTimeout(()=>{
 | 
				
			||||||
      var firstMap;
 | 
					        compareAllUsers(this.users);
 | 
				
			||||||
      for (var u of this.users) {
 | 
					        compareMapValues(this.users);
 | 
				
			||||||
        u.transact(function*(root){//eslint-disable-line
 | 
					        done();
 | 
				
			||||||
          var val = yield* root.val();
 | 
					      }, 500);
 | 
				
			||||||
          if (firstMap == null) {
 | 
					 | 
				
			||||||
            firstMap = val;
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            expect(val).toEqual(firstMap);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it(`succeed after ${numberOfYMapTests} actions without flush before transactions`, function(){
 | 
					    it(`succeed after ${numberOfYMapTests} actions without flush before transactions`, function(done){
 | 
				
			||||||
      applyRandomTransactions(this.users, randomMapTransactions, numberOfYMapTests);
 | 
					      applyRandomTransactions(this.users, randomMapTransactions, numberOfYMapTests);
 | 
				
			||||||
      compareAllUsers(this.users);
 | 
					      setTimeout(()=>{
 | 
				
			||||||
 | 
					        compareAllUsers(this.users);
 | 
				
			||||||
 | 
					        compareMapValues(this.users);
 | 
				
			||||||
 | 
					        done();
 | 
				
			||||||
 | 
					      }, 500);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  var numberOfYListTests = 100;
 | 
					  var numberOfYListTests = 100;
 | 
				
			||||||
  describe("List random tests", function(){
 | 
					  describe("List random tests", function(){
 | 
				
			||||||
    var randomListTests = [function* insert (root) {
 | 
					    var randomListTests = [function* insert (root) {
 | 
				
			||||||
      var list = yield* root.val("list");
 | 
					      var list = yield* root.get("list");
 | 
				
			||||||
      yield* list.insert(Math.floor(Math.random() * 10), [getRandomNumber()]);
 | 
					      yield* list.insert(Math.floor(Math.random() * 10), [getRandomNumber()]);
 | 
				
			||||||
    }, function* delete_(root) {
 | 
					    }, function* delete_(root) {
 | 
				
			||||||
      var list = yield* root.val("list");
 | 
					      var list = yield* root.get("list");
 | 
				
			||||||
      yield* list.delete(Math.floor(Math.random() * 10));
 | 
					      yield* list.delete(Math.floor(Math.random() * 10));
 | 
				
			||||||
    }];
 | 
					    }];
 | 
				
			||||||
    beforeEach(function(){
 | 
					    beforeEach(function(){
 | 
				
			||||||
      this.users[0].transact(function*(root){
 | 
					      this.users[0].transact(function*(root){
 | 
				
			||||||
        var list = yield* Y.List();
 | 
					        var list = yield* Y.List();
 | 
				
			||||||
        yield* root.val("list", list);
 | 
					        yield* root.set("list", list);
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      this.users[0].connector.flushAll();
 | 
					      this.users[0].connector.flushAll();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@ -292,11 +236,11 @@ describe("Yjs", function(){
 | 
				
			|||||||
      compareAllUsers(this.users);
 | 
					      compareAllUsers(this.users);
 | 
				
			||||||
      var userList;
 | 
					      var userList;
 | 
				
			||||||
      this.users[0].transact(function*(root){
 | 
					      this.users[0].transact(function*(root){
 | 
				
			||||||
        var list = yield* root.val("list");
 | 
					        var list = yield* root.get("list");
 | 
				
			||||||
        if (userList == null) {
 | 
					        if (userList == null) {
 | 
				
			||||||
          userList = yield* list.val();
 | 
					          userList = yield* list.get();
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          expect(userList).toEqual(yield* list.val());
 | 
					          expect(userList).toEqual(yield* list.get());
 | 
				
			||||||
          expect(userList.length > 0).toBeTruthy();
 | 
					          expect(userList.length > 0).toBeTruthy();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@ -323,4 +267,5 @@ describe("Yjs", function(){
 | 
				
			|||||||
      compareAllUsers(this.users);
 | 
					      compareAllUsers(this.users);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user