added support to use existing user ids! Fixes #23
This commit is contained in:
parent
a9c2ec6ba0
commit
dc3c6a5d42
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -154,7 +154,7 @@ module.exports = {
|
||||
this.send(user, {
|
||||
sync_step: "getHB",
|
||||
send_again: "true",
|
||||
data: []
|
||||
data: this.getStateVector()
|
||||
});
|
||||
if (!this.sent_hb_to_all_users) {
|
||||
this.sent_hb_to_all_users = true;
|
||||
@ -184,7 +184,7 @@ module.exports = {
|
||||
this.send(user, {
|
||||
sync_step: "getHB",
|
||||
send_again: "true",
|
||||
data: []
|
||||
data: this.getStateVector()
|
||||
});
|
||||
hb = this.getHB([]).hb;
|
||||
_hb = [];
|
||||
@ -221,8 +221,14 @@ module.exports = {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
whenReceivedStateVector: function(f) {
|
||||
if (this.when_received_state_vector_listeners == null) {
|
||||
this.when_received_state_vector_listeners = [];
|
||||
}
|
||||
return this.when_received_state_vector_listeners.push(f);
|
||||
},
|
||||
receiveMessage: function(sender, res) {
|
||||
var _hb, data, f, hb, i, j, len, len1, o, ref, results, sendApplyHB, send_again;
|
||||
var _hb, data, f, hb, i, j, k, len, len1, len2, o, ref, ref1, results, sendApplyHB, send_again;
|
||||
if (res.sync_step == null) {
|
||||
ref = this.receive_handlers;
|
||||
results = [];
|
||||
@ -236,6 +242,14 @@ module.exports = {
|
||||
return;
|
||||
}
|
||||
if (res.sync_step === "getHB") {
|
||||
if (this.when_received_state_vector_listeners != null) {
|
||||
ref1 = this.when_received_state_vector_listeners;
|
||||
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
||||
f = ref1[j];
|
||||
f.call(this, res.data);
|
||||
}
|
||||
}
|
||||
delete this.when_received_state_vector_listeners;
|
||||
data = this.getHB(res.data);
|
||||
hb = data.hb;
|
||||
_hb = [];
|
||||
@ -252,8 +266,8 @@ module.exports = {
|
||||
};
|
||||
})(this);
|
||||
}
|
||||
for (j = 0, len1 = hb.length; j < len1; j++) {
|
||||
o = hb[j];
|
||||
for (k = 0, len2 = hb.length; k < len2; k++) {
|
||||
o = hb[k];
|
||||
_hb.push(o);
|
||||
if (_hb.length > 10) {
|
||||
sendApplyHB({
|
||||
@ -271,10 +285,10 @@ module.exports = {
|
||||
send_again = (function(_this) {
|
||||
return function(sv) {
|
||||
return function() {
|
||||
var k, len2;
|
||||
var l, len3;
|
||||
hb = _this.getHB(sv).hb;
|
||||
for (k = 0, len2 = hb.length; k < len2; k++) {
|
||||
o = hb[k];
|
||||
for (l = 0, len3 = hb.length; l < len3; l++) {
|
||||
o = hb[l];
|
||||
_hb.push(o);
|
||||
if (_hb.length > 10) {
|
||||
_this.send(sender, {
|
||||
|
@ -16,30 +16,26 @@ HistoryBuffer = (function() {
|
||||
setTimeout(this.emptyGarbage, this.garbageCollectTimeout);
|
||||
}
|
||||
|
||||
HistoryBuffer.prototype.resetUserId = function(id) {
|
||||
var o, o_name, own;
|
||||
own = this.buffer[this.user_id];
|
||||
if (own != null) {
|
||||
for (o_name in own) {
|
||||
o = own[o_name];
|
||||
if (o.uid.creator != null) {
|
||||
o.uid.creator = id;
|
||||
}
|
||||
if (o.uid.alt != null) {
|
||||
o.uid.alt.creator = id;
|
||||
}
|
||||
}
|
||||
if (this.buffer[id] != null) {
|
||||
throw new Error("You are re-assigning an old user id - this is not (yet) possible!");
|
||||
}
|
||||
this.buffer[id] = own;
|
||||
delete this.buffer[this.user_id];
|
||||
HistoryBuffer.prototype.setUserId = function(user_id1, state_vector) {
|
||||
var base, buff, counter_diff, name, o, o_name, ref;
|
||||
this.user_id = user_id1;
|
||||
if ((base = this.buffer)[name = this.user_id] == null) {
|
||||
base[name] = [];
|
||||
}
|
||||
if (this.operation_counter[this.user_id] != null) {
|
||||
this.operation_counter[id] = this.operation_counter[this.user_id];
|
||||
delete this.operation_counter[this.user_id];
|
||||
buff = this.buffer[this.user_id];
|
||||
counter_diff = state_vector[this.user_id] || 0;
|
||||
if (this.buffer._temp != null) {
|
||||
ref = this.buffer._temp;
|
||||
for (o_name in ref) {
|
||||
o = ref[o_name];
|
||||
o.uid.creator = this.user_id;
|
||||
o.uid.op_number += counter_diff;
|
||||
buff[o.uid.op_number] = o;
|
||||
}
|
||||
}
|
||||
return this.user_id = id;
|
||||
this.operation_counter[this.user_id] = (this.operation_counter._temp || 0) + counter_diff;
|
||||
delete this.operation_counter._temp;
|
||||
return delete this.buffer._temp;
|
||||
};
|
||||
|
||||
HistoryBuffer.prototype.emptyGarbage = function() {
|
||||
@ -243,15 +239,13 @@ HistoryBuffer = (function() {
|
||||
if ((base = this.operation_counter)[name = o.uid.creator] == null) {
|
||||
base[name] = 0;
|
||||
}
|
||||
if (o.uid.creator !== this.getUserId()) {
|
||||
if (o.uid.op_number === this.operation_counter[o.uid.creator]) {
|
||||
this.operation_counter[o.uid.creator]++;
|
||||
}
|
||||
while (this.buffer[o.uid.creator][this.operation_counter[o.uid.creator]] != null) {
|
||||
this.operation_counter[o.uid.creator]++;
|
||||
}
|
||||
return void 0;
|
||||
if (o.uid.op_number === this.operation_counter[o.uid.creator]) {
|
||||
this.operation_counter[o.uid.creator]++;
|
||||
}
|
||||
while (this.buffer[o.uid.creator][this.operation_counter[o.uid.creator]] != null) {
|
||||
this.operation_counter[o.uid.creator]++;
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
return HistoryBuffer;
|
||||
|
@ -10,15 +10,15 @@ adaptConnector = require("./ConnectorAdapter");
|
||||
|
||||
createY = function(connector) {
|
||||
var HB, ct, engine, model, ops, ops_manager, user_id;
|
||||
user_id = null;
|
||||
if (connector.user_id != null) {
|
||||
user_id = connector.user_id;
|
||||
} else {
|
||||
user_id = "_temp";
|
||||
connector.on_user_id_set = function(id) {
|
||||
user_id = id;
|
||||
return HB.resetUserId(id);
|
||||
};
|
||||
connector.when_received_state_vector_listeners = [
|
||||
function(state_vector) {
|
||||
return HB.setUserId(this.user_id, state_vector);
|
||||
}
|
||||
];
|
||||
}
|
||||
HB = new HistoryBuffer(user_id);
|
||||
ops_manager = structured_ops_uninitialized(HB, this.constructor);
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
20152
build/test/selections-test.js
Normal file
20152
build/test/selections-test.js
Normal file
File diff suppressed because one or more lines are too long
18741
build/test/text-test.js
Normal file
18741
build/test/text-test.js
Normal file
File diff suppressed because one or more lines are too long
@ -102,7 +102,7 @@ module.exports =
|
||||
|
||||
#
|
||||
# Execute a function _when_ we are connected. If not connected, wait until connected.
|
||||
# @param f {Function} Will be executed on the PeerJs-Connector context.
|
||||
# @param f {Function} Will be executed on the Connector context.
|
||||
#
|
||||
whenSynced: (args)->
|
||||
if args.constructor is Function
|
||||
@ -143,7 +143,7 @@ module.exports =
|
||||
@send user,
|
||||
sync_step: "getHB"
|
||||
send_again: "true"
|
||||
data: [] # @getStateVector()
|
||||
data: @getStateVector()
|
||||
if not @sent_hb_to_all_users
|
||||
@sent_hb_to_all_users = true
|
||||
|
||||
@ -171,7 +171,7 @@ module.exports =
|
||||
@send user,
|
||||
sync_step: "getHB"
|
||||
send_again: "true"
|
||||
data: []
|
||||
data: @getStateVector()
|
||||
hb = @getHB([]).hb
|
||||
_hb = []
|
||||
for o in hb
|
||||
@ -199,6 +199,12 @@ module.exports =
|
||||
delete @compute_when_synced
|
||||
null
|
||||
|
||||
# executed when the a state_vector is received. listener will be called only once!
|
||||
whenReceivedStateVector: (f)->
|
||||
@when_received_state_vector_listeners ?= []
|
||||
@when_received_state_vector_listeners.push f
|
||||
|
||||
|
||||
#
|
||||
# You received a raw message, and you know that it is intended for to Yjs. Then call this function.
|
||||
#
|
||||
@ -210,6 +216,12 @@ module.exports =
|
||||
if sender is @user_id
|
||||
return
|
||||
if res.sync_step is "getHB"
|
||||
# call listeners
|
||||
if @when_received_state_vector_listeners?
|
||||
for f in @when_received_state_vector_listeners
|
||||
f.call this, res.data
|
||||
delete @when_received_state_vector_listeners
|
||||
|
||||
data = @getHB(res.data)
|
||||
hb = data.hb
|
||||
_hb = []
|
||||
|
@ -22,22 +22,32 @@ class HistoryBuffer
|
||||
@reserved_identifier_counter = 0
|
||||
setTimeout @emptyGarbage, @garbageCollectTimeout
|
||||
|
||||
resetUserId: (id)->
|
||||
own = @buffer[@user_id]
|
||||
if own?
|
||||
for o_name,o of own
|
||||
if o.uid.creator?
|
||||
o.uid.creator = id
|
||||
if o.uid.alt?
|
||||
o.uid.alt.creator = id
|
||||
if @buffer[id]?
|
||||
throw new Error "You are re-assigning an old user id - this is not (yet) possible!"
|
||||
@buffer[id] = own
|
||||
delete @buffer[@user_id]
|
||||
if @operation_counter[@user_id]?
|
||||
@operation_counter[id] = @operation_counter[@user_id]
|
||||
delete @operation_counter[@user_id]
|
||||
@user_id = id
|
||||
# At the beginning (when the user id was not assigned yet),
|
||||
# the operations are added to buffer._temp. When you finally get your user id,
|
||||
# the operations are copies from buffer._temp to buffer[id]. Furthermore, when buffer[id] does already contain operations
|
||||
# (because of a previous session), the uid.op_numbers of the operations have to be reassigned.
|
||||
# This is what this function does. It adds them to buffer[id],
|
||||
# and assigns them the correct uid.op_number and uid.creator
|
||||
setUserId: (@user_id, state_vector)->
|
||||
@buffer[@user_id] ?= []
|
||||
buff = @buffer[@user_id]
|
||||
|
||||
# we assumed that we started with counter = 0.
|
||||
# when we receive tha state_vector, and actually have
|
||||
# counter = 10. Then we have to add 10 to every op_counter
|
||||
counter_diff = state_vector[@user_id] or 0
|
||||
|
||||
if @buffer._temp?
|
||||
for o_name,o of @buffer._temp
|
||||
o.uid.creator = @user_id
|
||||
o.uid.op_number += counter_diff
|
||||
buff[o.uid.op_number] = o
|
||||
|
||||
@operation_counter[@user_id] = (@operation_counter._temp or 0) + counter_diff
|
||||
|
||||
delete @operation_counter._temp
|
||||
delete @buffer._temp
|
||||
|
||||
|
||||
emptyGarbage: ()=>
|
||||
for o in @garbage
|
||||
@ -207,17 +217,11 @@ class HistoryBuffer
|
||||
#
|
||||
addToCounter: (o)->
|
||||
@operation_counter[o.uid.creator] ?= 0
|
||||
if o.uid.creator isnt @getUserId()
|
||||
# TODO: check if operations are send in order
|
||||
if o.uid.op_number is @operation_counter[o.uid.creator]
|
||||
@operation_counter[o.uid.creator]++
|
||||
while @buffer[o.uid.creator][@operation_counter[o.uid.creator]]?
|
||||
@operation_counter[o.uid.creator]++
|
||||
undefined
|
||||
|
||||
#if @operation_counter[o.uid.creator] isnt (o.uid.op_number + 1)
|
||||
#console.log (@operation_counter[o.uid.creator] - (o.uid.op_number + 1))
|
||||
#console.log o
|
||||
#throw new Error "You don't receive operations in the proper order. Try counting like this 0,1,2,3,4,.. ;)"
|
||||
# TODO: check if operations are send in order
|
||||
if o.uid.op_number is @operation_counter[o.uid.creator]
|
||||
@operation_counter[o.uid.creator]++
|
||||
while @buffer[o.uid.creator][@operation_counter[o.uid.creator]]?
|
||||
@operation_counter[o.uid.creator]++
|
||||
undefined
|
||||
|
||||
module.exports = HistoryBuffer
|
||||
|
@ -6,14 +6,13 @@ Engine = require "./Engine"
|
||||
adaptConnector = require "./ConnectorAdapter"
|
||||
|
||||
createY = (connector)->
|
||||
user_id = null
|
||||
if connector.user_id?
|
||||
user_id = connector.user_id # TODO: change to getUniqueId()
|
||||
else
|
||||
user_id = "_temp"
|
||||
connector.on_user_id_set = (id)->
|
||||
user_id = id
|
||||
HB.resetUserId id
|
||||
connector.when_received_state_vector_listeners = [(state_vector)->
|
||||
HB.setUserId this.user_id, state_vector
|
||||
]
|
||||
HB = new HistoryBuffer user_id
|
||||
ops_manager = structured_ops_uninitialized HB, this.constructor
|
||||
ops = ops_manager.operations
|
||||
|
Loading…
x
Reference in New Issue
Block a user