implemented "preferUntransformed"
This commit is contained in:
parent
8e4efd9bba
commit
b242aab955
@ -170,6 +170,11 @@ soon, if possible.
|
|||||||
immediately going to be resolved, without waiting for any confirmation from
|
immediately going to be resolved, without waiting for any confirmation from
|
||||||
the server. Use with caution.
|
the server. Use with caution.
|
||||||
* Have a look at the used connector repository to see all available options.
|
* Have a look at the used connector repository to see all available options.
|
||||||
|
* *Only if you know what you are doing:* Set
|
||||||
|
`options.connector.preferUntransformed = true` in order receive the shared
|
||||||
|
data untransformed. This is very efficient as the database content is simply
|
||||||
|
copied to this client. This does only work if this client receives content
|
||||||
|
from only one client.
|
||||||
* options.sourceDir (browser only)
|
* options.sourceDir (browser only)
|
||||||
* Path where all y-* modules are stored
|
* Path where all y-* modules are stored
|
||||||
* Defaults to `/bower_components`
|
* Defaults to `/bower_components`
|
||||||
|
@ -17,7 +17,6 @@ module.exports = function (Y/* :any */) {
|
|||||||
syncingClients: Array<UserId>;
|
syncingClients: Array<UserId>;
|
||||||
forwardToSyncingClients: boolean;
|
forwardToSyncingClients: boolean;
|
||||||
debug: boolean;
|
debug: boolean;
|
||||||
broadcastedHB: boolean;
|
|
||||||
syncStep2: Promise;
|
syncStep2: Promise;
|
||||||
userId: UserId;
|
userId: UserId;
|
||||||
send: Function;
|
send: Function;
|
||||||
@ -36,6 +35,11 @@ module.exports = function (Y/* :any */) {
|
|||||||
if (opts == null) {
|
if (opts == null) {
|
||||||
opts = {}
|
opts = {}
|
||||||
}
|
}
|
||||||
|
// Prefer to receive untransformed operations. This does only work if
|
||||||
|
// this client receives operations from only one other client.
|
||||||
|
// In particular, this does not work with y-webrtc.
|
||||||
|
// It will work with y-websockets-client
|
||||||
|
this.preferUntransformed = opts.preferUntransformed || false
|
||||||
if (opts.role == null || opts.role === 'master') {
|
if (opts.role == null || opts.role === 'master') {
|
||||||
this.role = 'master'
|
this.role = 'master'
|
||||||
} else if (opts.role === 'slave') {
|
} else if (opts.role === 'slave') {
|
||||||
@ -55,7 +59,6 @@ module.exports = function (Y/* :any */) {
|
|||||||
this.syncingClients = []
|
this.syncingClients = []
|
||||||
this.forwardToSyncingClients = opts.forwardToSyncingClients !== false
|
this.forwardToSyncingClients = opts.forwardToSyncingClients !== false
|
||||||
this.debug = opts.debug === true
|
this.debug = opts.debug === true
|
||||||
this.broadcastedHB = false
|
|
||||||
this.syncStep2 = Promise.resolve()
|
this.syncStep2 = Promise.resolve()
|
||||||
this.broadcastOpBuffer = []
|
this.broadcastOpBuffer = []
|
||||||
this.protocolVersion = 11
|
this.protocolVersion = 11
|
||||||
@ -83,7 +86,6 @@ module.exports = function (Y/* :any */) {
|
|||||||
this.connections = {}
|
this.connections = {}
|
||||||
this.isSynced = false
|
this.isSynced = false
|
||||||
this.currentSyncTarget = null
|
this.currentSyncTarget = null
|
||||||
this.broadcastedHB = false
|
|
||||||
this.syncingClients = []
|
this.syncingClients = []
|
||||||
this.whenSyncedListeners = []
|
this.whenSyncedListeners = []
|
||||||
return this.y.db.stopGarbageCollector()
|
return this.y.db.stopGarbageCollector()
|
||||||
@ -95,7 +97,6 @@ module.exports = function (Y/* :any */) {
|
|||||||
}
|
}
|
||||||
this.isSynced = false
|
this.isSynced = false
|
||||||
this.currentSyncTarget = null
|
this.currentSyncTarget = null
|
||||||
this.broadcastedHB = false
|
|
||||||
this.findNextSyncTarget()
|
this.findNextSyncTarget()
|
||||||
}
|
}
|
||||||
setUserId (userId) {
|
setUserId (userId) {
|
||||||
@ -182,13 +183,17 @@ module.exports = function (Y/* :any */) {
|
|||||||
this.y.db.requestTransaction(function *() {
|
this.y.db.requestTransaction(function *() {
|
||||||
var stateSet = yield* this.getStateSet()
|
var stateSet = yield* this.getStateSet()
|
||||||
var deleteSet = yield* this.getDeleteSet()
|
var deleteSet = yield* this.getDeleteSet()
|
||||||
conn.send(syncUser, {
|
var answer = {
|
||||||
type: 'sync step 1',
|
type: 'sync step 1',
|
||||||
stateSet: stateSet,
|
stateSet: stateSet,
|
||||||
deleteSet: deleteSet,
|
deleteSet: deleteSet,
|
||||||
protocolVersion: conn.protocolVersion,
|
protocolVersion: conn.protocolVersion,
|
||||||
auth: conn.authInfo
|
auth: conn.authInfo
|
||||||
})
|
}
|
||||||
|
if (conn.preferUntransformed && Object.keys(stateSet).length === 0) {
|
||||||
|
answer.preferUntransformed = true
|
||||||
|
}
|
||||||
|
conn.send(syncUser, answer)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
if (!conn.isSynced) {
|
if (!conn.isSynced) {
|
||||||
@ -294,15 +299,19 @@ module.exports = function (Y/* :any */) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var ds = yield* this.getDeleteSet()
|
var ds = yield* this.getDeleteSet()
|
||||||
var ops = yield* this.getOperations(m.stateSet)
|
var answer = {
|
||||||
conn.send(sender, {
|
|
||||||
type: 'sync step 2',
|
type: 'sync step 2',
|
||||||
os: ops,
|
|
||||||
stateSet: currentStateSet,
|
stateSet: currentStateSet,
|
||||||
deleteSet: ds,
|
deleteSet: ds,
|
||||||
protocolVersion: this.protocolVersion,
|
protocolVersion: this.protocolVersion,
|
||||||
auth: this.authInfo
|
auth: this.authInfo
|
||||||
})
|
}
|
||||||
|
if (message.preferUntransformed === true && Object.keys(m.stateSet).length === 0) {
|
||||||
|
answer.osUntransformed = yield* this.getOperationsUntransformed()
|
||||||
|
} else {
|
||||||
|
answer.os = yield* this.getOperations(m.stateSet)
|
||||||
|
}
|
||||||
|
conn.send(sender, answer)
|
||||||
if (this.forwardToSyncingClients) {
|
if (this.forwardToSyncingClients) {
|
||||||
conn.syncingClients.push(sender)
|
conn.syncingClients.push(sender)
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
@ -321,8 +330,6 @@ module.exports = function (Y/* :any */) {
|
|||||||
})
|
})
|
||||||
} else if (message.type === 'sync step 2' && canWrite(auth)) {
|
} else if (message.type === 'sync step 2' && canWrite(auth)) {
|
||||||
let conn = this
|
let conn = this
|
||||||
var broadcastHB = !this.broadcastedHB
|
|
||||||
this.broadcastedHB = true
|
|
||||||
var db = this.y.db
|
var db = this.y.db
|
||||||
var defer = {}
|
var defer = {}
|
||||||
defer.promise = new Promise(function (resolve) {
|
defer.promise = new Promise(function (resolve) {
|
||||||
@ -332,7 +339,15 @@ module.exports = function (Y/* :any */) {
|
|||||||
let m /* :MessageSyncStep2 */ = message
|
let m /* :MessageSyncStep2 */ = message
|
||||||
db.requestTransaction(function * () {
|
db.requestTransaction(function * () {
|
||||||
yield* this.applyDeleteSet(m.deleteSet)
|
yield* this.applyDeleteSet(m.deleteSet)
|
||||||
this.store.apply(m.os)
|
if (m.osUntransformed != null) {
|
||||||
|
yield* this.applyOperationsUntransformed(m.osUntransformed, m.stateSet)
|
||||||
|
} else {
|
||||||
|
this.store.apply(m.os)
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* This just sends the complete hb after some time
|
||||||
|
* Mostly for debugging..
|
||||||
|
*
|
||||||
db.requestTransaction(function * () {
|
db.requestTransaction(function * () {
|
||||||
var ops = yield* this.getOperations(m.stateSet)
|
var ops = yield* this.getOperations(m.stateSet)
|
||||||
if (ops.length > 0) {
|
if (ops.length > 0) {
|
||||||
@ -346,8 +361,9 @@ module.exports = function (Y/* :any */) {
|
|||||||
conn.broadcastOps(ops)
|
conn.broadcastOps(ops)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defer.resolve()
|
|
||||||
})
|
})
|
||||||
|
*/
|
||||||
|
defer.resolve()
|
||||||
})
|
})
|
||||||
} else if (message.type === 'sync done') {
|
} else if (message.type === 'sync done') {
|
||||||
var self = this
|
var self = this
|
||||||
|
@ -111,7 +111,7 @@ module.exports = function (Y /* :any */) {
|
|||||||
}
|
}
|
||||||
this.garbageCollect = garbageCollect
|
this.garbageCollect = garbageCollect
|
||||||
this.startGarbageCollector()
|
this.startGarbageCollector()
|
||||||
|
|
||||||
this.repairCheckInterval = !opts.repairCheckInterval ? 6000 : opts.repairCheckInterval
|
this.repairCheckInterval = !opts.repairCheckInterval ? 6000 : opts.repairCheckInterval
|
||||||
this.opsReceivedTimestamp = new Date()
|
this.opsReceivedTimestamp = new Date()
|
||||||
this.startRepairCheck()
|
this.startRepairCheck()
|
||||||
|
@ -1013,6 +1013,56 @@ module.exports = function (Y/* :any */) {
|
|||||||
}
|
}
|
||||||
return send.reverse()
|
return send.reverse()
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Get the plain untransformed operations from the database.
|
||||||
|
* You can apply these operations using .applyOperationsUntransformed(ops)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
* getOperationsUntransformed () {
|
||||||
|
var ops = []
|
||||||
|
yield* this.os.iterate(this, null, null, function * (op) {
|
||||||
|
if (op.id[0] !== '_') {
|
||||||
|
ops.push(Y.Struct[op.struct].encode(op))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
untransformed: ops
|
||||||
|
}
|
||||||
|
}
|
||||||
|
* applyOperationsUntransformed (m, stateSet) {
|
||||||
|
var ops = m.untransformed
|
||||||
|
for (var i = 0; i < ops.length; i++) {
|
||||||
|
var op = ops[i]
|
||||||
|
// create, and modify parent, if it is created implicitly
|
||||||
|
if (op.parent != null && op.parent[0] === '_') {
|
||||||
|
if (op.struct === 'Insert') {
|
||||||
|
// update parents .map/start/end properties
|
||||||
|
if (op.parentSub != null && op.left == null) {
|
||||||
|
// op is child of Map
|
||||||
|
let parent = yield* this.getOperation(op.parent)
|
||||||
|
parent.map[op.parentSub] = op.id
|
||||||
|
yield* this.setOperation(parent)
|
||||||
|
} else if (op.right == null || op.left == null) {
|
||||||
|
let parent = yield* this.getOperation(op.parent)
|
||||||
|
if (op.right == null) {
|
||||||
|
parent.end = Y.utils.getLastId(op)
|
||||||
|
}
|
||||||
|
if (op.left == null) {
|
||||||
|
parent.start = op.id
|
||||||
|
}
|
||||||
|
yield* this.setOperation(parent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yield* this.os.put(op)
|
||||||
|
}
|
||||||
|
for (var user in stateSet) {
|
||||||
|
yield* this.ss.put({
|
||||||
|
id: [user],
|
||||||
|
clock: stateSet[user]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
/* this is what we used before.. use this as a reference..
|
/* this is what we used before.. use this as a reference..
|
||||||
* makeOperationReady (startSS, op) {
|
* makeOperationReady (startSS, op) {
|
||||||
op = Y.Struct[op.struct].encode(op)
|
op = Y.Struct[op.struct].encode(op)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user