improved awaitOps
This commit is contained in:
parent
483d2c78aa
commit
14d59de2bd
@ -479,16 +479,11 @@ module.exports = function (Y /* :any */) {
|
|||||||
this.waitingTransactions.push(makeGen)
|
this.waitingTransactions.push(makeGen)
|
||||||
if (!this.transactionInProgress) {
|
if (!this.transactionInProgress) {
|
||||||
this.transactionInProgress = true
|
this.transactionInProgress = true
|
||||||
if (false || callImmediately) { // TODO: decide whether this is ok or not..
|
setTimeout(() => {
|
||||||
this.transact(this.getNextRequest())
|
this.transact(this.getNextRequest())
|
||||||
} else {
|
|
||||||
var self = this
|
|
||||||
setTimeout(function () {
|
|
||||||
self.transact(self.getNextRequest())
|
|
||||||
}, 0)
|
}, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Y.AbstractDatabase = AbstractDatabase
|
Y.AbstractDatabase = AbstractDatabase
|
||||||
}
|
}
|
||||||
|
@ -88,8 +88,21 @@ g.getRandomString = getRandomString
|
|||||||
function * applyTransactions (relAmount, numberOfTransactions, objects, users, transactions, noReconnect) {
|
function * applyTransactions (relAmount, numberOfTransactions, objects, users, transactions, noReconnect) {
|
||||||
for (var i = 0; i < numberOfTransactions * relAmount + 1; i++) {
|
for (var i = 0; i < numberOfTransactions * relAmount + 1; i++) {
|
||||||
var r = Math.random()
|
var r = Math.random()
|
||||||
if (r >= 0.5) {
|
if (r > 0.9) {
|
||||||
// 50% chance to flush
|
// 10% chance of toggling concurrent user interactions.
|
||||||
|
// There will be an artificial delay until ops can be executed by the type,
|
||||||
|
// therefore, operations of the database will be (pre)transformed until user operations arrive
|
||||||
|
yield (function simulateConcurrentUserInteractions (type) {
|
||||||
|
if (type.eventHandler.awaiting === 0 && type.eventHandler._debuggingAwaiting !== true) {
|
||||||
|
type.eventHandler.awaiting = 1
|
||||||
|
type.eventHandler._debuggingAwaiting = true
|
||||||
|
} else {
|
||||||
|
// fixAwaitingInType will handle _debuggingAwaiting
|
||||||
|
return fixAwaitingInType(type)
|
||||||
|
}
|
||||||
|
})(getRandom(objects))
|
||||||
|
} else if (r >= 0.5) {
|
||||||
|
// 40% chance to flush
|
||||||
yield Y.utils.globalRoom.flushOne() // flushes for some user.. (not necessarily 0)
|
yield Y.utils.globalRoom.flushOne() // flushes for some user.. (not necessarily 0)
|
||||||
} else if (noReconnect || r >= 0.05) {
|
} else if (noReconnect || r >= 0.05) {
|
||||||
// 45% chance to create operation
|
// 45% chance to create operation
|
||||||
@ -121,7 +134,7 @@ function fixAwaitingInType (type) {
|
|||||||
type.os.requestTransaction(function * () {
|
type.os.requestTransaction(function * () {
|
||||||
if (type.eventHandler.awaiting > 0 && type.eventHandler._debuggingAwaiting === true) {
|
if (type.eventHandler.awaiting > 0 && type.eventHandler._debuggingAwaiting === true) {
|
||||||
type.eventHandler._debuggingAwaiting = false
|
type.eventHandler._debuggingAwaiting = false
|
||||||
yield* type.eventHandler.awaitedOps(this, 0)
|
yield* type.eventHandler.awaitOps(this, function * () { /* mock function */ })
|
||||||
}
|
}
|
||||||
wait(50).then(type.os.whenTransactionsFinished()).then(wait(50)).then(resolve)
|
wait(50).then(type.os.whenTransactionsFinished()).then(wait(50)).then(resolve)
|
||||||
})
|
})
|
||||||
|
57
src/Utils.js
57
src/Utils.js
@ -105,9 +105,36 @@ module.exports = function (Y /* : any*/) {
|
|||||||
this.awaiting++
|
this.awaiting++
|
||||||
ops.map(Y.utils.copyOperation).forEach(this.onevent)
|
ops.map(Y.utils.copyOperation).forEach(this.onevent)
|
||||||
}
|
}
|
||||||
* awaitedOps (transaction, n) {
|
* awaitOps (transaction, f, args) {
|
||||||
// remove awaited ops
|
function notSoSmartSort (array) {
|
||||||
this.waiting.splice(this.waiting.length - n)
|
// this function sorts insertions in a executable order
|
||||||
|
var result = []
|
||||||
|
while (array.length > 0) {
|
||||||
|
for (var i = 0; i < array.length; i++) {
|
||||||
|
var independent = true
|
||||||
|
for (var j = 0; j < array.length; j++) {
|
||||||
|
if (Y.utils.matchesId(array[j], array[i].left)) {
|
||||||
|
// array[i] depends on array[j]
|
||||||
|
independent = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (independent) {
|
||||||
|
result.push(array.splice(i, 1)[0])
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
var before = this.waiting.length
|
||||||
|
// somehow create new operations
|
||||||
|
yield* f.apply(transaction, args)
|
||||||
|
// remove all appended ops / awaited ops
|
||||||
|
this.waiting.splice(before)
|
||||||
|
if (this.awaiting > 0) this.awaiting--
|
||||||
|
// if there are no awaited ops anymore, we can update all waiting ops, and send execute them (if there are still no awaited ops)
|
||||||
|
if (this.awaiting === 0 && this.waiting.length > 0) {
|
||||||
// update all waiting ops
|
// update all waiting ops
|
||||||
for (let i = 0; i < this.waiting.length; i++) {
|
for (let i = 0; i < this.waiting.length; i++) {
|
||||||
var o = this.waiting[i]
|
var o = this.waiting[i]
|
||||||
@ -133,7 +160,29 @@ module.exports = function (Y /* : any*/) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._tryCallEvents()
|
// the previous stuff was async, so we have to check again!
|
||||||
|
// We also pull changes from the bindings, if there exists such a method, this could increase awaiting too
|
||||||
|
if (this._pullChanges != null) {
|
||||||
|
this._pullChanges()
|
||||||
|
}
|
||||||
|
if (this.awaiting === 0) {
|
||||||
|
// sort by type, execute inserts first
|
||||||
|
var ins = []
|
||||||
|
var dels = []
|
||||||
|
this.waiting.forEach(function (o) {
|
||||||
|
if (o.struct === 'Delete') {
|
||||||
|
dels.push(o)
|
||||||
|
} else {
|
||||||
|
ins.push(o)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// put in executable order
|
||||||
|
ins = notSoSmartSort(ins)
|
||||||
|
ins.forEach(this.onevent)
|
||||||
|
dels.forEach(this.onevent)
|
||||||
|
this.waiting = []
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// TODO: Remove awaitedInserts and awaitedDeletes in favor of awaitedOps, as they are deprecated and do not always work
|
// TODO: Remove awaitedInserts and awaitedDeletes in favor of awaitedOps, as they are deprecated and do not always work
|
||||||
// Do this in one of the coming releases that are breaking anyway
|
// Do this in one of the coming releases that are breaking anyway
|
||||||
|
Loading…
x
Reference in New Issue
Block a user