@live-change/db 0.6.2 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Database.js +4 -3
- package/lib/Index.js +16 -21
- package/lib/ScriptContext.js +15 -0
- package/lib/WebScriptContext.js +15 -0
- package/package.json +6 -5
package/lib/Database.js
CHANGED
|
@@ -4,6 +4,7 @@ const Log = require('./Log.js')
|
|
|
4
4
|
const queryGet = require('./queryGet.js')
|
|
5
5
|
const queryObservable = require('./queryObservable.js')
|
|
6
6
|
const getRandomValues = require('get-random-values')
|
|
7
|
+
const nextTick = require('next-tick')
|
|
7
8
|
|
|
8
9
|
const ReactiveDao = require("@live-change/dao")
|
|
9
10
|
|
|
@@ -60,9 +61,9 @@ class Database {
|
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
generateUid() {
|
|
63
|
-
const array = new Uint8Array(
|
|
64
|
+
const array = new Uint8Array(8)
|
|
64
65
|
getRandomValues(array)
|
|
65
|
-
return array.map (b => b.toString
|
|
66
|
+
return [...array].map (b => b.toString(16).padStart (2, "0")).join ("")
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
store(name, config) {
|
|
@@ -280,7 +281,7 @@ class Database {
|
|
|
280
281
|
const config = this.config.indexes[name]
|
|
281
282
|
console.error("INDEX", name, "unhandledRejection", reason, "CODE:\n", config?.code)
|
|
282
283
|
console.error("DELETING INDEX", name)
|
|
283
|
-
|
|
284
|
+
nextTick(() => {
|
|
284
285
|
if(!config) {
|
|
285
286
|
console.error("INDEX", name, "IS ALREADY DELETED")
|
|
286
287
|
console.trace("ALREADY DELETED")
|
package/lib/Index.js
CHANGED
|
@@ -3,6 +3,7 @@ const ReactiveDao = require("@live-change/dao")
|
|
|
3
3
|
const Table = require('./Table.js')
|
|
4
4
|
const queryGet = require('./queryGet.js')
|
|
5
5
|
const profileLog = require('./profileLog.js')
|
|
6
|
+
const nextTick = require('next-tick')
|
|
6
7
|
const queryObservable = require('./queryObservable.js')
|
|
7
8
|
const { ChangeStream } = require('./ChangeStream.js')
|
|
8
9
|
|
|
@@ -183,12 +184,11 @@ class TableReader extends ChangeStream {
|
|
|
183
184
|
//console.log("READ OP LOG", this.prefix, "RANGE", JSON.stringify(this.opLogObservableRange))
|
|
184
185
|
this.opLogObservable = this.opLog.rangeObservable(this.opLogObservableRange)
|
|
185
186
|
/// NEXT TICK BECAUSE IT CAN FINISH BEFORE EVENT START xD
|
|
186
|
-
|
|
187
|
+
nextTick(() => this.opLogObservable.observe(this))
|
|
187
188
|
})
|
|
188
189
|
return this.opLogPromise
|
|
189
190
|
}
|
|
190
191
|
set(value) {
|
|
191
|
-
//if(this.prefix == 'table_triggers') console.log("TABLE", this.prefix, "READER SET", value)
|
|
192
192
|
if(!value) return
|
|
193
193
|
this.opLogBuffer = value.slice()
|
|
194
194
|
//console.log("PROMISE", this.opLogPromise)
|
|
@@ -209,7 +209,6 @@ class TableReader extends ChangeStream {
|
|
|
209
209
|
this.opLogReader.handleSignal()
|
|
210
210
|
}
|
|
211
211
|
push(object) {
|
|
212
|
-
//if(this.prefix == 'table_triggers') console.log("TABLE", this.prefix, " READER PUSH", object)
|
|
213
212
|
if(this.disposed) return
|
|
214
213
|
this.opLogBuffer.push(object)
|
|
215
214
|
this.opLogReader.handleSignal()
|
|
@@ -240,7 +239,6 @@ class TableReader extends ChangeStream {
|
|
|
240
239
|
}
|
|
241
240
|
}
|
|
242
241
|
async readTo(endKey) {
|
|
243
|
-
//if(this.prefix == 'table_triggers') console.log("RT", endKey, "IN", this.opLogBuffer)
|
|
244
242
|
let lastKey = null
|
|
245
243
|
while(this.opLogBuffer[0] && this.opLogBuffer[0].id <= endKey) {
|
|
246
244
|
const next = this.opLogBuffer.shift()
|
|
@@ -249,7 +247,6 @@ class TableReader extends ChangeStream {
|
|
|
249
247
|
await this.change(next, null, next.id, next.id)
|
|
250
248
|
} else {
|
|
251
249
|
const op = next.operation
|
|
252
|
-
//if(this.prefix == 'table_triggers') console.log("HANDLE OP LOG OPERATION", next)
|
|
253
250
|
if(op) {
|
|
254
251
|
if(op.type == 'put') {
|
|
255
252
|
await this.change(op.object, op.oldObject, op.object.id, next.id)
|
|
@@ -267,7 +264,6 @@ class TableReader extends ChangeStream {
|
|
|
267
264
|
await this.readOpLog(this.opLogObservable.list[this.opLogObservable.list.length - 1].id)
|
|
268
265
|
//console.log("READ TO RESULT, OP LOG PROMISE:", this.opLogPromise)
|
|
269
266
|
}
|
|
270
|
-
//console.log("RT", endKey, "IN", this.opLogBuffer)
|
|
271
267
|
}
|
|
272
268
|
return lastKey
|
|
273
269
|
}
|
|
@@ -326,7 +322,6 @@ class OpLogReader {
|
|
|
326
322
|
}
|
|
327
323
|
async readMore() {
|
|
328
324
|
this.readingMore = true
|
|
329
|
-
//if(this.indexName == 'triggers_new') console.log("READING TRIGGERS STARTED!")
|
|
330
325
|
do {
|
|
331
326
|
while(true) {
|
|
332
327
|
this.gotSignals = false
|
|
@@ -336,9 +331,9 @@ class OpLogReader {
|
|
|
336
331
|
let possibleNextKeys = await Promise.all(
|
|
337
332
|
this.tableReaders.map(async tr => ({ reader: tr, key: await tr.nextKey() }))
|
|
338
333
|
)
|
|
339
|
-
//
|
|
334
|
+
//console.log("GOT NEXT KEYS")
|
|
340
335
|
if(this.disposed) return
|
|
341
|
-
//
|
|
336
|
+
//console.log("POSSIBLE NEXT KEYS", possibleNextKeys.map(({key, reader}) => [reader.prefix, key]))
|
|
342
337
|
if(possibleNextKeys.length == 0) { /// It could happen when oplog is cleared
|
|
343
338
|
return
|
|
344
339
|
}
|
|
@@ -348,9 +343,10 @@ class OpLogReader {
|
|
|
348
343
|
next = possibleKey
|
|
349
344
|
}
|
|
350
345
|
}
|
|
351
|
-
//
|
|
346
|
+
//console.log("NEXT", next)
|
|
347
|
+
//console.log("NEXT KEY", next && next.reader && next.reader.prefix, next && next.key)
|
|
352
348
|
const lastKey = '\xFF\xFF\xFF\xFF'
|
|
353
|
-
//
|
|
349
|
+
//console.log("NEXT", !!next, "KEY", next && next.key, lastKey)
|
|
354
350
|
if(!next || next.key == lastKey) break // nothing to read
|
|
355
351
|
let otherReaderNext = null
|
|
356
352
|
for(const possibleKey of possibleNextKeys) {
|
|
@@ -358,13 +354,12 @@ class OpLogReader {
|
|
|
358
354
|
&& (!otherReaderNext || possibleKey.key < otherReaderNext.key))
|
|
359
355
|
otherReaderNext = possibleKey
|
|
360
356
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
// otherReaderNext && otherReaderNext.key)
|
|
357
|
+
/*console.log("OTHER READ NEXT", otherReaderNext && otherReaderNext.reader && otherReaderNext.reader.prefix,
|
|
358
|
+
otherReaderNext && otherReaderNext.key)*/
|
|
364
359
|
let readEnd = (otherReaderNext && otherReaderNext.key) // Read to next other reader key
|
|
365
360
|
|| (((''+(now - 1))).padStart(16, '0'))+':' // or to current timestamp
|
|
366
361
|
if(readEnd < next) {
|
|
367
|
-
readEnd = next+'\xff'
|
|
362
|
+
readEnd = next.key+'\xff'
|
|
368
363
|
}
|
|
369
364
|
|
|
370
365
|
if((next.key||'') < this.currentKey) {
|
|
@@ -372,24 +367,23 @@ class OpLogReader {
|
|
|
372
367
|
console.error("time travel", next.key, this.currentKey)
|
|
373
368
|
//process.exit(1) /// TODO: do something about it!
|
|
374
369
|
}
|
|
375
|
-
//
|
|
370
|
+
//console.log("CKN", this.currentKey, '=>', next.key)
|
|
376
371
|
this.currentKey = next.key
|
|
377
|
-
//
|
|
372
|
+
//console.log("READ TO", readEnd)
|
|
378
373
|
const readKey = await next.reader.readTo(readEnd)
|
|
379
|
-
//
|
|
374
|
+
//console.log("READED")
|
|
380
375
|
if(readKey) {
|
|
381
376
|
if((readKey||'') < this.currentKey) {
|
|
382
377
|
//debugger
|
|
383
378
|
console.error("time travel", readKey, this.currentKey)
|
|
384
379
|
//process.exit(1) /// TODO: do something about it!
|
|
385
380
|
}
|
|
386
|
-
//
|
|
381
|
+
//console.log("CKR", this.currentKey, '=>', readKey)
|
|
387
382
|
this.currentKey = readKey
|
|
388
383
|
}
|
|
389
384
|
}
|
|
390
385
|
} while(this.gotSignals)
|
|
391
386
|
this.readingMore = false
|
|
392
|
-
//if(this.indexName == 'triggers_new') console.log("READING TRIGGERS FINISHED!")
|
|
393
387
|
}
|
|
394
388
|
dispose() {
|
|
395
389
|
this.disposed = true
|
|
@@ -466,7 +460,8 @@ class Index extends Table {
|
|
|
466
460
|
this.scriptContext = this.database.createScriptContext({
|
|
467
461
|
/// TODO: script available routines
|
|
468
462
|
})
|
|
469
|
-
const queryFunction = this.scriptContext.
|
|
463
|
+
const queryFunction = this.scriptContext.getOrCreateFunction(this.code,
|
|
464
|
+
`userCode:${this.database.name}/indexes/${this.name}`)
|
|
470
465
|
this.codeFunction = (input, output) => queryFunction(input, output, this.params)
|
|
471
466
|
this.writer = new IndexWriter(this)
|
|
472
467
|
this.reader = null
|
package/lib/ScriptContext.js
CHANGED
|
@@ -86,6 +86,21 @@ class ScriptContext {
|
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
|
+
|
|
90
|
+
getOrCreateFunction(code, filename) {
|
|
91
|
+
const cleanCode = code.replace(/\n +/g, "\n")
|
|
92
|
+
//console.log("COMPILED FUNCTIONS", `\n[\n ${Object.keys(globalThis.compiledFunctions).join(',\n ')},\n]`)
|
|
93
|
+
if(!(globalThis.compiledFunctions = globalThis.compiledFunctions || {})[cleanCode]) {
|
|
94
|
+
console.log("############# compiled function not found: ", code)
|
|
95
|
+
for(const key of Object.keys(globalThis.compiledFunctions)) {
|
|
96
|
+
console.log(`compiled func |${cleanCode}| == |${key}| => ${cleanCode == key}`)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const queryFunction = (globalThis.compiledFunctions = globalThis.compiledFunctions || {})[cleanCode]
|
|
100
|
+
?? this.run(code, filename)
|
|
101
|
+
;(globalThis.compiledFunctions = globalThis.compiledFunctions || {})[cleanCode] = queryFunction
|
|
102
|
+
return queryFunction
|
|
103
|
+
}
|
|
89
104
|
}
|
|
90
105
|
|
|
91
106
|
module.exports = ScriptContext
|
package/lib/WebScriptContext.js
CHANGED
|
@@ -42,6 +42,21 @@ class WebScriptContext {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
+
|
|
46
|
+
getOrCreateFunction(code, filename) {
|
|
47
|
+
const cleanCode = code.replace(/\n +/g, "\n")
|
|
48
|
+
//console.log("COMPILED FUNCTIONS", `\n[\n ${Object.keys(globalThis.compiledFunctions).join(',\n ')},\n]`)
|
|
49
|
+
if(!(globalThis.compiledFunctions = globalThis.compiledFunctions || {})[cleanCode]) {
|
|
50
|
+
console.log("############# compiled function not found: ", code)
|
|
51
|
+
for(const key of Object.keys(globalThis.compiledFunctions)) {
|
|
52
|
+
console.log(`compiled func |${cleanCode}| == |${key}| => ${cleanCode == key}`)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const queryFunction = (globalThis.compiledFunctions = globalThis.compiledFunctions || {})[cleanCode]
|
|
56
|
+
?? this.run(code, filename)
|
|
57
|
+
;(globalThis.compiledFunctions = globalThis.compiledFunctions || {})[cleanCode] = queryFunction
|
|
58
|
+
return queryFunction
|
|
59
|
+
}
|
|
45
60
|
}
|
|
46
61
|
|
|
47
62
|
module.exports = WebScriptContext
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@live-change/db",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"description": "Database with observable data for live queries",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -21,18 +21,19 @@
|
|
|
21
21
|
},
|
|
22
22
|
"homepage": "https://github.com/live-change/live-change-db",
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@live-change/db-store-level": "^0.6.
|
|
25
|
-
"@live-change/db-store-lmdb": "^0.6.
|
|
24
|
+
"@live-change/db-store-level": "^0.6.4",
|
|
25
|
+
"@live-change/db-store-lmdb": "^0.6.4",
|
|
26
26
|
"minimist": ">=1.2.3",
|
|
27
|
+
"next-tick": "^1.1.0",
|
|
27
28
|
"rimraf": "^3.0.2",
|
|
28
29
|
"sockjs": "^0.3.24",
|
|
29
30
|
"tape": "^5.3.2",
|
|
30
31
|
"websocket-extensions": ">=0.1.4"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
|
-
"@live-change/dao": "0.5.
|
|
34
|
+
"@live-change/dao": "0.5.15",
|
|
34
35
|
"get-random-values": "^1.2.2",
|
|
35
36
|
"node-interval-tree": "^1.3.3"
|
|
36
37
|
},
|
|
37
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "2b63a796522f2a5bf7c4e0311331640b4152ba77"
|
|
38
39
|
}
|