Compare commits

...

4 Commits

Author SHA1 Message Date
Kevin Jahns
957d650f81 Deploy 12.1.2 2016-11-10 17:01:53 +01:00
Kevin Jahns
9769968c1c Deploy 12.1.1 2016-11-09 14:26:32 +01:00
Kevin Jahns
1e30a877e6 merge 2016-11-09 14:17:00 +01:00
Kevin Jahns
549ab76b42 Deploy 12.0.4 2016-10-12 15:52:00 +02:00
6 changed files with 104 additions and 57 deletions

View File

@@ -198,14 +198,20 @@ The promise returns an instance of Y. We denote it with a lower case `y`.
* Force to disconnect this instance from the other instances * Force to disconnect this instance from the other instances
* y.connector.reconnect() * y.connector.reconnect()
* Try to reconnect to the other instances (needs to be supported by the connector) * Try to reconnect to the other instances (needs to be supported by the connector)
* Not supported by y-xmpp * Not supported by y-xmpp
* y.destroy() * y.close()
* Destroy this object. * Destroy this object.
* Destroys all types (they will throw weird errors if you still use them) * Destroys all types (they will throw weird errors if you still use them)
* Disconnects from the other instances (via connector) * Disconnects from the other instances (via connector)
* Returns a promise
* y.destroy()
* calls y.close()
* Removes all data from the database * Removes all data from the database
* Returns a promise
* y.db.stopGarbageCollector() * y.db.stopGarbageCollector()
* Stop the garbage collector. Call y.db.garbageCollect() to continue garbage collection * Stop the garbage collector. Call y.db.garbageCollect() to continue garbage collection
* y.db.gc :: Boolean
* Whether gc is turned on
* y.db.gcTimeout :: Number (defaults to 50000 ms) * y.db.gcTimeout :: Number (defaults to 50000 ms)
* Time interval between two garbage collect cycles * Time interval between two garbage collect cycles
* It is required that all instances exchanged all messages after two garbage collect cycles (after 100000 ms per default) * It is required that all instances exchanged all messages after two garbage collect cycles (after 100000 ms per default)

View File

@@ -1,6 +1,6 @@
{ {
"name": "yjs", "name": "yjs",
"version": "12.1.0", "version": "12.1.2",
"homepage": "y-js.org", "homepage": "y-js.org",
"authors": [ "authors": [
"Kevin Jahns <kevin.jahns@rwth-aachen.de>" "Kevin Jahns <kevin.jahns@rwth-aachen.de>"

139
y.es6
View File

@@ -145,13 +145,8 @@ module.exports = function (Y/* :any */) {
this.whenSyncedListeners.push(f) this.whenSyncedListeners.push(f)
} }
} }
/*
returns false, if there is no sync target
true otherwise
*/
findNextSyncTarget () { findNextSyncTarget () {
if (this.currentSyncTarget != null || this.isSynced) { if (this.currentSyncTarget != null) {
return // "The current sync has not finished!" return // "The current sync has not finished!"
} }
@@ -177,16 +172,20 @@ module.exports = function (Y/* :any */) {
}) })
}) })
} else { } else {
this.y.db.requestTransaction(function *() { if (!conn.isSynced) {
// it is crucial that isSynced is set at the time garbageCollectAfterSync is called this.y.db.requestTransaction(function *() {
conn.isSynced = true if (!conn.isSynced) {
yield* this.garbageCollectAfterSync() // it is crucial that isSynced is set at the time garbageCollectAfterSync is called
// call whensynced listeners conn.isSynced = true
for (var f of conn.whenSyncedListeners) { yield* this.garbageCollectAfterSync()
f() // call whensynced listeners
} for (var f of conn.whenSyncedListeners) {
conn.whenSyncedListeners = [] f()
}) }
conn.whenSyncedListeners = []
}
})
}
} }
} }
send (uid, message) { send (uid, message) {
@@ -714,12 +713,18 @@ module.exports = function (Y /* :any */) {
} }
this.gc1 = [] // first stage this.gc1 = [] // first stage
this.gc2 = [] // second stage -> after that, remove the op this.gc2 = [] // second stage -> after that, remove the op
this.gcTimeout = !opts.gcTimeout ? 50000 : opts.gcTimeouts this.gc = opts.gc == null || opts.gc
if (this.gc) {
this.gcTimeout = !opts.gcTimeout ? 50000 : opts.gcTimeout
} else {
this.gcTimeout = -1
}
function garbageCollect () { function garbageCollect () {
return os.whenTransactionsFinished().then(function () { return os.whenTransactionsFinished().then(function () {
if (os.gc1.length > 0 || os.gc2.length > 0) { if (os.gc1.length > 0 || os.gc2.length > 0) {
if (!os.y.isConnected()) { if (!os.y.connector.isSynced) {
console.warn('gc should be empty when disconnected!') console.warn('gc should be empty when not synced!')
} }
return new Promise((resolve) => { return new Promise((resolve) => {
os.requestTransaction(function * () { os.requestTransaction(function * () {
@@ -788,7 +793,7 @@ module.exports = function (Y /* :any */) {
clearInterval(this.repairCheckIntervalHandler) clearInterval(this.repairCheckIntervalHandler)
} }
queueGarbageCollector (id) { queueGarbageCollector (id) {
if (this.y.isConnected()) { if (this.y.connector.isSynced && this.gc) {
this.gc1.push(id) this.gc1.push(id)
} }
} }
@@ -843,7 +848,7 @@ module.exports = function (Y /* :any */) {
TODO: rename this function TODO: rename this function
Rulez: Rulez:
* Only gc if this user is online * Only gc if this user is online & gc turned on
* The most left element in a list must not be gc'd. * The most left element in a list must not be gc'd.
=> There is at least one element in the list => There is at least one element in the list
@@ -852,7 +857,9 @@ module.exports = function (Y /* :any */) {
* addToGarbageCollector (op, left) { * addToGarbageCollector (op, left) {
if ( if (
op.gc == null && op.gc == null &&
op.deleted === true op.deleted === true &&
this.store.gc &&
this.store.y.connector.isSynced
) { ) {
var gc = false var gc = false
if (left != null && left.deleted === true) { if (left != null && left.deleted === true) {
@@ -878,10 +885,7 @@ module.exports = function (Y /* :any */) {
this.gc2 = this.gc2.filter(filter) this.gc2 = this.gc2.filter(filter)
delete op.gc delete op.gc
} }
* destroy () { destroyTypes () {
clearInterval(this.gcInterval)
this.gcInterval = null
this.stopRepairCheck()
for (var key in this.initializedTypes) { for (var key in this.initializedTypes) {
var type = this.initializedTypes[key] var type = this.initializedTypes[key]
if (type._destroy != null) { if (type._destroy != null) {
@@ -891,6 +895,11 @@ module.exports = function (Y /* :any */) {
} }
} }
} }
* destroy () {
clearInterval(this.gcInterval)
this.gcInterval = null
this.stopRepairCheck()
}
setUserId (userId) { setUserId (userId) {
if (!this.userIdPromise.inProgress) { if (!this.userIdPromise.inProgress) {
this.userIdPromise.inProgress = true this.userIdPromise.inProgress = true
@@ -1073,8 +1082,7 @@ module.exports = function (Y /* :any */) {
*/ */
* operationAdded (transaction, op) { * operationAdded (transaction, op) {
if (op.struct === 'Delete') { if (op.struct === 'Delete') {
var target = yield* transaction.getInsertion(op.target) var type = this.initializedTypes[JSON.stringify(op.targetParent)]
var type = this.initializedTypes[JSON.stringify(target.parent)]
if (type != null) { if (type != null) {
yield* type._changed(transaction, op) yield* type._changed(transaction, op)
} }
@@ -1142,10 +1150,8 @@ module.exports = function (Y /* :any */) {
resolve: resolve, resolve: resolve,
promise: promise promise: promise
} }
return promise
} else {
return this.transactionsFinished.promise
} }
return this.transactionsFinished.promise
} else { } else {
return Promise.resolve() return Promise.resolve()
} }
@@ -1261,7 +1267,11 @@ module.exports = function (Y/* :any */) {
*/ */
Delete: { Delete: {
encode: function (op) { encode: function (op) {
return op return {
target: op.target,
length: op.length || 0,
struct: 'Delete'
}
}, },
requiredOps: function (op) { requiredOps: function (op) {
return [] // [op.target] return [] // [op.target]
@@ -1739,7 +1749,7 @@ module.exports = function (Y/* :any */) {
send.push(Y.Struct[op.struct].encode(op)) send.push(Y.Struct[op.struct].encode(op))
} }
} }
if (!this.store.y.connector.isDisconnected() && send.length > 0) { // TODO: && !this.store.forwardAppliedOperations (but then i don't send delete ops) if (this.store.y.connector.isSynced && send.length > 0) { // TODO: && !this.store.forwardAppliedOperations (but then i don't send delete ops)
// is connected, and this is not going to be send in addOperation // is connected, and this is not going to be send in addOperation
this.store.y.connector.broadcastOps(send) this.store.y.connector.broadcastOps(send)
} }
@@ -1849,7 +1859,8 @@ module.exports = function (Y/* :any */) {
yield* this.store.operationAdded(this, { yield* this.store.operationAdded(this, {
struct: 'Delete', struct: 'Delete',
target: target.id, target: target.id,
length: targetLength length: targetLength,
targetParent: target.parent
}) })
} }
// need to gc in the end! // need to gc in the end!
@@ -2356,7 +2367,7 @@ module.exports = function (Y/* :any */) {
} }
* addOperation (op) { * addOperation (op) {
yield* this.os.put(op) yield* this.os.put(op)
if (!this.store.y.connector.isDisconnected() && this.store.forwardAppliedOperations && typeof op.id[1] !== 'string') { if (this.store.y.connector.isSynced && this.store.forwardAppliedOperations && typeof op.id[1] !== 'string') {
// is connected, and this is not going to be send in addOperation // is connected, and this is not going to be send in addOperation
this.store.y.connector.broadcastOps([op]) this.store.y.connector.broadcastOps([op])
} }
@@ -2771,7 +2782,6 @@ module.exports = function (Y /* : any*/) {
destroy () { destroy () {
super.destroy() super.destroy()
this.waiting = null this.waiting = null
this.awaiting = null
this.onevent = null this.onevent = null
} }
/* /*
@@ -3485,7 +3495,12 @@ Y.extend = function (name, value) {
Y.requestModules = requestModules Y.requestModules = requestModules
function requestModules (modules) { function requestModules (modules) {
var sourceDir = Y.sourceDir || '/bower_components' var sourceDir
if (Y.sourceDir === null) {
sourceDir = null
} else {
sourceDir = Y.sourceDir || '/bower_components'
}
// determine if this module was compiled for es5 or es6 (y.js vs. y.es6) // determine if this module was compiled for es5 or es6 (y.js vs. y.es6)
// if Insert.execute is a Function, then it isnt a generator.. // if Insert.execute is a Function, then it isnt a generator..
// then load the es5(.js) files.. // then load the es5(.js) files..
@@ -3498,10 +3513,11 @@ function requestModules (modules) {
if (requiringModules[module] == null) { if (requiringModules[module] == null) {
// module does not exist // module does not exist
if (typeof window !== 'undefined' && window.Y !== 'undefined') { if (typeof window !== 'undefined' && window.Y !== 'undefined') {
var imported = document.createElement('script') if (sourceDir != null) {
imported.src = sourceDir + '/' + modulename + '/' + modulename + extention var imported = document.createElement('script')
document.head.appendChild(imported) imported.src = sourceDir + '/' + modulename + '/' + modulename + extention
document.head.appendChild(imported)
}
let requireModule = {} let requireModule = {}
requiringModules[module] = requireModule requiringModules[module] = requireModule
requireModule.promise = new Promise(function (resolve) { requireModule.promise = new Promise(function (resolve) {
@@ -3550,7 +3566,7 @@ type YOptions = {
*/ */
function Y (opts/* :YOptions */) /* :Promise<YConfig> */ { function Y (opts/* :YOptions */) /* :Promise<YConfig> */ {
if (opts.sourceDir != null) { if (opts.hasOwnProperty('sourceDir')) {
Y.sourceDir = opts.sourceDir Y.sourceDir = opts.sourceDir
} }
opts.types = opts.types != null ? opts.types : [] opts.types = opts.types != null ? opts.types : []
@@ -3595,6 +3611,7 @@ class YConfig {
this.options = opts this.options = opts
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)
this.connected = true
} }
init (callback) { init (callback) {
var opts = this.options var opts = this.options
@@ -3631,22 +3648,46 @@ class YConfig {
return this.connector.isSynced return this.connector.isSynced
} }
disconnect () { disconnect () {
return this.connector.disconnect() if (this.connected) {
this.connected = false
return this.connector.disconnect()
} else {
return Promise.resolve()
}
} }
reconnect () { reconnect () {
return this.connector.reconnect() if (!this.connected) {
this.connected = true
return this.connector.reconnect()
} else {
return Promise.resolve()
}
} }
destroy () { destroy () {
var self = this
return this.close().then(function () {
if (self.db.deleteDB != null) {
return self.db.deleteDB()
} else {
return Promise.resolve()
}
})
}
close () {
var self = this
this.share = null
if (this.connector.destroy != null) { if (this.connector.destroy != null) {
this.connector.destroy() this.connector.destroy()
} else { } else {
this.connector.disconnect() this.connector.disconnect()
} }
var self = this return this.db.whenTransactionsFinished(function () {
this.db.requestTransaction(function * () { this.db.destroyTypes()
yield* self.db.destroy() // make sure to wait for all transactions before destroying the db
self.connector = null this.db.requestTransaction(function * () {
self.db = null yield* self.db.destroy()
})
return this.db.whenTransactionsFinished()
}) })
} }
} }

File diff suppressed because one or more lines are too long

6
y.js

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long