@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 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(16)
64
+ const array = new Uint8Array(8)
64
65
  getRandomValues(array)
65
- return array.map (b => b.toString (16).padStart (2, "0")).join ("")
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
- process.nextTick(() => {
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
- process.nextTick(() => this.opLogObservable.observe(this))
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
- //if(this.indexName == 'triggers_new') console.log("GOT NEXT KEYS")
334
+ //console.log("GOT NEXT KEYS")
340
335
  if(this.disposed) return
341
- //if(this.indexName == 'triggers_new') console.log("POSSIBLE NEXT KEYS", possibleNextKeys.map(({key, reader}) => [reader.prefix, key]))
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
- //if(this.indexName == 'triggers_new') console.log("NEXT KEY", next && next.reader && next.reader.prefix, next && next.key)
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
- //if(this.indexName == 'triggers_new') console.log("NEXT", !!next, "KEY", next && next.key, lastKey)
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
- //if(this.indexName == 'triggers_new')
362
- // console.log("OTHER READ NEXT", otherReaderNext && otherReaderNext.reader && otherReaderNext.reader.prefix,
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
- //if(this.indexName == 'triggers_new') console.log("CKN", this.currentKey, '=>', next.key)
370
+ //console.log("CKN", this.currentKey, '=>', next.key)
376
371
  this.currentKey = next.key
377
- //if(this.indexName == 'triggers_new') console.log("READ TO", readEnd)
372
+ //console.log("READ TO", readEnd)
378
373
  const readKey = await next.reader.readTo(readEnd)
379
- //if(this.indexName == 'triggers_new') console.log("READED")
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
- //if(this.indexName == 'triggers_new') console.log("CKR", this.currentKey, '=>', readKey)
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.run(this.code,`userCode:${this.database.name}/indexes/${this.name}`)
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
@@ -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
@@ -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.2",
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.2",
25
- "@live-change/db-store-lmdb": "^0.6.2",
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.14",
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": "9a1b104864c08f3e35b009f191889e3308e3eeb0"
38
+ "gitHead": "2b63a796522f2a5bf7c4e0311331640b4152ba77"
38
39
  }