@muze-nl/simplystore 0.9.3 → 0.10.1
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/package.json +6 -7
- package/scripts/convert.mjs +41 -9
- package/scripts/index.id.json +1 -0
- package/scripts/index.offset.json +1 -0
- package/src/command-worker-module.mjs +11 -1
- package/src/index.id.mjs +45 -0
- package/src/index.mjs +19 -0
- package/src/index.offset.mjs +39 -0
- package/src/load-worker.mjs +16 -2
- package/src/query-worker-module.mjs +15 -21
- package/src/server.mjs +55 -13
- package/www/home.html +21 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@muze-nl/simplystore",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"main": "src/server.mjs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -16,14 +16,13 @@
|
|
|
16
16
|
"bugs": "https://github.com/simplyedit/simplystore/issues",
|
|
17
17
|
"homepage": "https://github.com/simplyedit/simplystore#readme",
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@muze-nl/jaqt": "^0.10.
|
|
19
|
+
"@muze-nl/jaqt": "^0.10.6",
|
|
20
20
|
"@muze-nl/jsontag": "^0.10.4",
|
|
21
|
-
"@muze-nl/od-jsontag": "^0.4.
|
|
21
|
+
"@muze-nl/od-jsontag": "^0.4.6",
|
|
22
22
|
"codemirror": "^6.0.1",
|
|
23
|
-
"express": "^
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"write-file-atomic": "^5.0.1"
|
|
23
|
+
"express": "^5.2.1",
|
|
24
|
+
"vm2": "^3.10.5",
|
|
25
|
+
"write-file-atomic": "^7.0.1"
|
|
27
26
|
},
|
|
28
27
|
"devDependencies": {
|
|
29
28
|
"@eslint/js": "^9.36.0",
|
package/scripts/convert.mjs
CHANGED
|
@@ -1,25 +1,57 @@
|
|
|
1
1
|
import JSONTag from '@muze-nl/jsontag'
|
|
2
2
|
import serialize, { stringify } from '@muze-nl/od-jsontag/src/serialize.mjs'
|
|
3
|
+
import Parser from '@muze-nl/od-jsontag'
|
|
3
4
|
import fs from 'node:fs'
|
|
5
|
+
import path from 'node:path'
|
|
6
|
+
|
|
7
|
+
const __dirname = import.meta.dirname;
|
|
4
8
|
|
|
5
9
|
if (process.argv.length<=3) {
|
|
6
|
-
console.log('usage: node ./convert.mjs {inputfile} {outputfile}')
|
|
10
|
+
console.log('usage: node ./convert.mjs {inputfile} {outputfile} {indexlib?}')
|
|
7
11
|
process.exit()
|
|
8
12
|
}
|
|
9
13
|
|
|
10
14
|
// parse command line
|
|
11
15
|
let inputFile = process.argv[2]
|
|
12
16
|
let outputFile = process.argv[3]
|
|
17
|
+
let indexFile = process.argv[4] || __dirname+'/../src/index.mjs'
|
|
18
|
+
|
|
19
|
+
async function main() {
|
|
20
|
+
// load file
|
|
21
|
+
let input = fs.readFileSync(inputFile, 'utf-8')
|
|
22
|
+
|
|
23
|
+
// parse jsontag
|
|
24
|
+
let data = JSONTag.parse(input)
|
|
13
25
|
|
|
14
|
-
//
|
|
15
|
-
let
|
|
26
|
+
// write resultset to output
|
|
27
|
+
let strData = stringify(serialize(data))
|
|
28
|
+
fs.writeFileSync(outputFile, strData)
|
|
29
|
+
console.log('Converted data written to ',outputFile)
|
|
16
30
|
|
|
17
|
-
//
|
|
18
|
-
|
|
31
|
+
// now create indexes
|
|
32
|
+
console.log('Using index library:', indexFile)
|
|
33
|
+
const index = await import(indexFile).then(mod => {
|
|
34
|
+
return mod.default
|
|
35
|
+
})
|
|
19
36
|
|
|
20
|
-
//
|
|
21
|
-
|
|
37
|
+
// indexes need the position data which is only available after
|
|
38
|
+
// parsing the od-jsontag data
|
|
39
|
+
const parser = new Parser()
|
|
40
|
+
const odData = parser.parse(strData)
|
|
22
41
|
|
|
23
|
-
|
|
42
|
+
let meta = {
|
|
43
|
+
index: {
|
|
44
|
+
id: new Map()
|
|
45
|
+
},
|
|
46
|
+
resultArray: parser.meta.resultArray,
|
|
47
|
+
data: path.dirname(outputFile)
|
|
48
|
+
}
|
|
49
|
+
for (const ob of meta.resultArray) {
|
|
50
|
+
meta.index.id.set(JSONTag.getAttribute(ob, 'id'), ob)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
index.create(odData, meta)
|
|
54
|
+
console.log('Indexes created')
|
|
55
|
+
}
|
|
24
56
|
|
|
25
|
-
|
|
57
|
+
main()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import JSONTag from '@muze-nl/jsontag'
|
|
2
|
-
import {getIndex, resultSet} from '@muze-nl/od-jsontag/src/symbols.mjs'
|
|
2
|
+
import {getIndex, resultSet, isChanged} from '@muze-nl/od-jsontag/src/symbols.mjs'
|
|
3
3
|
import Parser from '@muze-nl/od-jsontag/src/parse.mjs'
|
|
4
4
|
import serialize from '@muze-nl/od-jsontag/src/serialize.mjs'
|
|
5
5
|
import writeFileAtomic from 'write-file-atomic'
|
|
6
6
|
|
|
7
7
|
let commands = {}
|
|
8
|
+
let index = {}
|
|
8
9
|
let resultArr = []
|
|
9
10
|
let dataspace
|
|
10
11
|
let datafile, basefile, extension
|
|
@@ -79,6 +80,9 @@ export async function initialize(task) {
|
|
|
79
80
|
commands = await import(task.commandsFile).then(mod => {
|
|
80
81
|
return mod.default
|
|
81
82
|
})
|
|
83
|
+
index = await import(task.indexFile).then(mod => {
|
|
84
|
+
return mod.default
|
|
85
|
+
})
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
export default async function runCommand(commandStr, request) {
|
|
@@ -94,6 +98,12 @@ export default async function runCommand(commandStr, request) {
|
|
|
94
98
|
commands[task.name](dataspace, task, request, metaProxy)
|
|
95
99
|
//TODO: if command/task makes no changes, skip updating data.jsontag and writing it, skip response.data
|
|
96
100
|
|
|
101
|
+
const changes = meta.resultArray.filter(e => e[isChanged])
|
|
102
|
+
//FIXME: new entities should also report isChanged = true
|
|
103
|
+
if (changes.length) {
|
|
104
|
+
changes.uuid = task.id
|
|
105
|
+
index.update(dataspace, meta, changes)
|
|
106
|
+
}
|
|
97
107
|
const uint8sab = serialize(dataspace, {meta, changes: true}) // serialize only changes
|
|
98
108
|
response.data = uint8sab
|
|
99
109
|
response.meta = {
|
package/src/index.id.mjs
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import JSONTag from '@muze-nl/jsontag'
|
|
3
|
+
import { getIndex } from '@muze-nl/od-jsontag/src/symbols.mjs'
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
create(data, meta) {
|
|
7
|
+
console.log('creating '+meta.data+'/index.id.json')
|
|
8
|
+
// jsontag parse automatically fills meta.index.id, so no need to create anything
|
|
9
|
+
// just store meta.index.id in index.id.json
|
|
10
|
+
const index = {}
|
|
11
|
+
for (const key of meta.index.id.keys()) {
|
|
12
|
+
if (!key) {
|
|
13
|
+
continue
|
|
14
|
+
}
|
|
15
|
+
const entity = meta.index.id.get(key)
|
|
16
|
+
if (!entity) {
|
|
17
|
+
continue
|
|
18
|
+
}
|
|
19
|
+
index[key] = entity[getIndex]
|
|
20
|
+
}
|
|
21
|
+
fs.writeFileSync(meta.data+'/index.id.json', JSON.stringify(index))
|
|
22
|
+
},
|
|
23
|
+
update(data, meta, changes) {
|
|
24
|
+
if (!changes.length) {
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
const index = {}
|
|
28
|
+
for (const entry of changes) {
|
|
29
|
+
const id = JSONTag.getAttribute(entry, 'id')
|
|
30
|
+
if (id) {
|
|
31
|
+
index[id] = entry[getIndex]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
fs.writeFileSync(meta.data+'/index.id.'+changes.uuid+'.json', JSON.stringify(index))
|
|
35
|
+
},
|
|
36
|
+
load(uuid=null) {
|
|
37
|
+
let filename
|
|
38
|
+
if (!uuid) {
|
|
39
|
+
filename = 'index.id.json'
|
|
40
|
+
} else {
|
|
41
|
+
filename = 'index.id.'+filename+'.json'
|
|
42
|
+
}
|
|
43
|
+
return JSON.parse(fs.readFileSync(meta.data+filename))
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/index.mjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import idIndex from './index.id.mjs'
|
|
2
|
+
import offsetIndex from './index.offset.mjs'
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
create(data, meta) {
|
|
6
|
+
idIndex.create(data, meta)
|
|
7
|
+
offsetIndex.create(data, meta)
|
|
8
|
+
},
|
|
9
|
+
update(data, meta, changes) {
|
|
10
|
+
idIndex.update(data, meta, changes)
|
|
11
|
+
offsetIndex.update(data, meta, changes)
|
|
12
|
+
},
|
|
13
|
+
load(meta, uuid=null) {
|
|
14
|
+
return {
|
|
15
|
+
id: idIndex.load(uuid),
|
|
16
|
+
offset: offsetIndex.load(uuid)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import JSONTag from '@muze-nl/jsontag'
|
|
3
|
+
import { getIndex, position } from '@muze-nl/od-jsontag/src/symbols.mjs'
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
create(data, meta) {
|
|
7
|
+
console.log('creating '+meta.data+'/index.offset.json')
|
|
8
|
+
// jsontag parse automatically fills meta.index.offset, so no need to create anything
|
|
9
|
+
const index = {}
|
|
10
|
+
const max = meta.resultArray.length
|
|
11
|
+
for (let i=0;i<max;i++) {
|
|
12
|
+
const entity = meta.resultArray[i]
|
|
13
|
+
index[i] = [ entity[position].start, entity[position].end ]
|
|
14
|
+
}
|
|
15
|
+
fs.writeFileSync(meta.data+'/index.offset.json', JSON.stringify(index))
|
|
16
|
+
},
|
|
17
|
+
update(data, meta, changes) {
|
|
18
|
+
if (!changes.length) {
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
const index = {}
|
|
22
|
+
for (const entry of changes) {
|
|
23
|
+
let pos = entry[position]
|
|
24
|
+
if (pos) {
|
|
25
|
+
index[entry[getIndex]] = [ pos.start, pos.end ]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
fs.writeFileSync(meta.data+'/index.offset.'+changes.uuid+'.json', JSON.stringify(index))
|
|
29
|
+
},
|
|
30
|
+
load(uuid=null) {
|
|
31
|
+
let filename
|
|
32
|
+
if (!uuid) {
|
|
33
|
+
filename = 'index.offset.json'
|
|
34
|
+
} else {
|
|
35
|
+
filename = 'index.offset.'+filename+'.json'
|
|
36
|
+
}
|
|
37
|
+
return JSON.parse(fs.readFileSync(meta.data+filename))
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/load-worker.mjs
CHANGED
|
@@ -2,25 +2,39 @@ import { parentPort } from 'node:worker_threads'
|
|
|
2
2
|
import JSONTag from '@muze-nl/jsontag'
|
|
3
3
|
import Parser from '@muze-nl/od-jsontag/src/parse.mjs'
|
|
4
4
|
import fs from 'fs'
|
|
5
|
+
import path from 'path'
|
|
5
6
|
import serialize from '@muze-nl/od-jsontag/src/serialize.mjs'
|
|
6
7
|
|
|
7
8
|
const parser = new Parser()
|
|
8
|
-
|
|
9
|
+
let index = {}
|
|
10
|
+
|
|
11
|
+
parentPort.on('message', async (files) => {
|
|
9
12
|
let meta = {
|
|
10
13
|
index: {
|
|
11
14
|
id: new Map()
|
|
12
15
|
}
|
|
13
16
|
}
|
|
14
17
|
|
|
18
|
+
index = await import(files.indexFile).then(mod => {
|
|
19
|
+
return mod.default
|
|
20
|
+
})
|
|
15
21
|
const extension = files.dataFile.split('.').pop()
|
|
16
22
|
const basefile = files.dataFile.substring(0, files.dataFile.length - (extension.length + 1)) //+1 for . character
|
|
17
|
-
|
|
23
|
+
meta.data = path.dirname(basefile)
|
|
18
24
|
let count = 0
|
|
19
25
|
let data
|
|
20
26
|
let jsontag
|
|
21
27
|
let datafile = files.dataFile
|
|
22
28
|
let commands = files.commands
|
|
23
29
|
commands.push('done')
|
|
30
|
+
// TODO
|
|
31
|
+
// - only load index files
|
|
32
|
+
// - for each command id
|
|
33
|
+
// - load files as raw bytes
|
|
34
|
+
// - index.id.*.jsontag and index.offset.*.jsontag to create proxies that will get the correct offset on access
|
|
35
|
+
// - do the same for resultSet[0] - the dataspace root entity
|
|
36
|
+
// don't parse entire files with od-jsontag
|
|
37
|
+
// add version info in proxies with a symbol to get that information
|
|
24
38
|
do {
|
|
25
39
|
if (fs.existsSync(datafile)) {
|
|
26
40
|
jsontag = fs.readFileSync(datafile)
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import pointer from 'json-pointer'
|
|
2
1
|
import {VM} from 'vm2'
|
|
3
2
|
import { memoryUsage } from 'node:process'
|
|
4
3
|
import JSONTag from '@muze-nl/jsontag'
|
|
5
4
|
import {source} from '@muze-nl/od-jsontag/src/symbols.mjs'
|
|
6
5
|
import Parser from '@muze-nl/od-jsontag/src/parse.mjs'
|
|
7
|
-
import {_,from,not,anyOf,allOf,asc,desc,sum,count,avg,max,min,many,one,distinct} from '@muze-nl/jaqt'
|
|
6
|
+
import {_,from,not,anyOf,allOf,asc,desc,sum,count,avg,max,min,many,one,first,distinct} from '@muze-nl/jaqt'
|
|
8
7
|
import process from 'node:process'
|
|
9
8
|
|
|
10
9
|
let dataspace
|
|
@@ -56,7 +55,7 @@ const tasks = {
|
|
|
56
55
|
return true
|
|
57
56
|
},
|
|
58
57
|
query: async (task) => {
|
|
59
|
-
return runQuery(task.req.path, task.req, task.req.body)
|
|
58
|
+
return runQuery(task.req.path, task.req, task.req.body, task.timeout)
|
|
60
59
|
},
|
|
61
60
|
memoryUsage: async () => {
|
|
62
61
|
let result = memoryUsage()
|
|
@@ -67,7 +66,7 @@ const tasks = {
|
|
|
67
66
|
|
|
68
67
|
export default tasks
|
|
69
68
|
|
|
70
|
-
export function runQuery(pointer, request, query) {
|
|
69
|
+
export function runQuery(pointer, request, query, timeout=1000) {
|
|
71
70
|
if (!pointer) { throw new Error('missing pointer parameter')}
|
|
72
71
|
if (!request) { throw new Error('missing request parameter')}
|
|
73
72
|
let response = {
|
|
@@ -79,7 +78,7 @@ export function runQuery(pointer, request, query) {
|
|
|
79
78
|
// @todo add text search: https://github.com/nextapps-de/flexsearch
|
|
80
79
|
// @todo replace VM with V8 isolate
|
|
81
80
|
const vm = new VM({
|
|
82
|
-
timeout:
|
|
81
|
+
timeout: timeout,
|
|
83
82
|
allowAsync: false,
|
|
84
83
|
sandbox: {
|
|
85
84
|
root: dataspace, //@TODO: if we don't pass the root, we can later shard
|
|
@@ -99,6 +98,7 @@ export function runQuery(pointer, request, query) {
|
|
|
99
98
|
min,
|
|
100
99
|
many,
|
|
101
100
|
one,
|
|
101
|
+
first,
|
|
102
102
|
distinct,
|
|
103
103
|
// console: connectConsole(res),
|
|
104
104
|
JSONTag,
|
|
@@ -171,24 +171,18 @@ function parseAllObjects(o, reset=true) {
|
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
export function getDataSpace(path, dataspace) {
|
|
174
|
-
if (path.substring(path.length-1)
|
|
175
|
-
//jsonpointer doesn't allow a trailing '/'
|
|
174
|
+
if (path.substring(path.length-1)=='/') {
|
|
176
175
|
path = path.substring(0, path.length-1)
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
result = pointer.get(dataspace, path)
|
|
184
|
-
} else {
|
|
185
|
-
result = JSONTag.parse('<object class="Error">{"message":"Not found", "code":404}')
|
|
186
|
-
}
|
|
187
|
-
} catch(err) {
|
|
188
|
-
result = JSONTag.parse('<object class="Error">{"message":'+JSON.stringify(err.message)+', "code":500}')
|
|
176
|
+
}
|
|
177
|
+
const pointer = path.split('/')
|
|
178
|
+
let result = dataspace
|
|
179
|
+
for (const part of pointer) {
|
|
180
|
+
if (part && result) {
|
|
181
|
+
result = result[part]
|
|
189
182
|
}
|
|
190
|
-
}
|
|
191
|
-
|
|
183
|
+
}
|
|
184
|
+
if (result===undefined) {
|
|
185
|
+
result = JSONTag.parse(`<object class="Error">{"message":"Path Not found", "code":404, "path":"${path}"}`)
|
|
192
186
|
}
|
|
193
187
|
return [result,path]
|
|
194
188
|
}
|
package/src/server.mjs
CHANGED
|
@@ -27,11 +27,14 @@ async function main(options) {
|
|
|
27
27
|
const loadWorker = options.loadWorker || __dirname+'/src/load-worker.mjs'
|
|
28
28
|
const commandWorker = options.commandWorker || __dirname+'/src/command-worker.mjs'
|
|
29
29
|
const commandsFile = options.commandsFile || __dirname+'/src/commands.mjs'
|
|
30
|
+
const indexFile = options.indexFile || __dirname+'/src/index.mjs'
|
|
30
31
|
const commandLog = options.commandLog || './command-log.jsontag'
|
|
31
32
|
const commandStatus = options.commandStatus || './command-status.jsontag'
|
|
32
33
|
const access = options.access || null
|
|
34
|
+
const timeout = options.timeout || 1000
|
|
35
|
+
const slowTimeout = options.slowTimeout || 10000
|
|
33
36
|
|
|
34
|
-
server.
|
|
37
|
+
server.get('/', serveHomepage)
|
|
35
38
|
|
|
36
39
|
// allow access to raw body, used to parse a query send as post body
|
|
37
40
|
server.use(express.raw({
|
|
@@ -59,17 +62,33 @@ async function main(options) {
|
|
|
59
62
|
body: jsontagBuffers,
|
|
60
63
|
meta,
|
|
61
64
|
access
|
|
62
|
-
}
|
|
65
|
+
},
|
|
66
|
+
timeout
|
|
63
67
|
}
|
|
64
68
|
}
|
|
65
69
|
|
|
70
|
+
const slowQueryWorkerInitTask = () => {
|
|
71
|
+
let result = queryWorkerInitTask()
|
|
72
|
+
result.timeout = slowTimeout
|
|
73
|
+
return result
|
|
74
|
+
}
|
|
75
|
+
|
|
66
76
|
let queryWorkerPool = new WorkerPool(maxWorkers, queryWorker, queryWorkerInitTask())
|
|
77
|
+
let slowQueryWorkerPool = new WorkerPool(1, queryWorker, slowQueryWorkerInitTask())
|
|
67
78
|
let commandWorkerInstance
|
|
68
79
|
|
|
69
|
-
server.get('/query
|
|
70
|
-
server.
|
|
71
|
-
server.
|
|
72
|
-
server.get('/
|
|
80
|
+
server.get('/query/', (req,next) => handleGetQuery(req,next))
|
|
81
|
+
server.get('/query/*remainder', (req,next) => handleGetQuery(req,next))
|
|
82
|
+
server.get('/slowquery/', (req,next) => handleSlowGetQuery(req,next))
|
|
83
|
+
server.get('/slowquery/*remainder', (req,next) => handleSlowGetQuery(req,next))
|
|
84
|
+
server.post('/query/', (req,next) => handlePostQuery(req,next))
|
|
85
|
+
server.post('/query/*remainder', (req,next) => handlePostQuery(req,next))
|
|
86
|
+
server.post('/slowquery/', (req,next) => handleSlowPostQuery(req,next))
|
|
87
|
+
server.post('/slowquery/*remainder', (req,next) => handleSlowPostQuery(req,next))
|
|
88
|
+
server.post('/command', (req,next) => handlePostCommand(req,next))
|
|
89
|
+
server.get('/command/:id', (req,next) => handleGetCommand(req,next))
|
|
90
|
+
|
|
91
|
+
server.use(express.static(wwwroot))
|
|
73
92
|
|
|
74
93
|
try {
|
|
75
94
|
await fetch(`http://localhost:${port}`, {
|
|
@@ -95,6 +114,11 @@ async function main(options) {
|
|
|
95
114
|
|
|
96
115
|
/* ------ */
|
|
97
116
|
|
|
117
|
+
function serveHomepage(req, res) {
|
|
118
|
+
res.setHeader('content-type', 'text/html');
|
|
119
|
+
res.send(fs.readFileSync(wwwroot+'/home.html'))
|
|
120
|
+
}
|
|
121
|
+
|
|
98
122
|
function loadCommandStatus(commandStatusFile) {
|
|
99
123
|
let status = new Map()
|
|
100
124
|
if (fs.existsSync(commandStatusFile)) {
|
|
@@ -134,6 +158,7 @@ async function main(options) {
|
|
|
134
158
|
meta,
|
|
135
159
|
data:jsontagBuffers,
|
|
136
160
|
commandsFile,
|
|
161
|
+
indexFile,
|
|
137
162
|
datafile
|
|
138
163
|
})
|
|
139
164
|
break;
|
|
@@ -158,12 +183,17 @@ async function main(options) {
|
|
|
158
183
|
reject(error)
|
|
159
184
|
worker.terminate()
|
|
160
185
|
})
|
|
161
|
-
worker.postMessage({dataFile:datafile,schemaFile,commands})
|
|
186
|
+
worker.postMessage({dataFile:datafile,indexFile,schemaFile,commands})
|
|
162
187
|
})
|
|
163
188
|
}
|
|
164
189
|
|
|
165
|
-
async function handleGetQuery(req, res) {
|
|
190
|
+
async function handleGetQuery(req, res, pool=null) {
|
|
166
191
|
let start = Date.now()
|
|
192
|
+
if (!pool) {
|
|
193
|
+
pool = queryWorkerPool
|
|
194
|
+
} else {
|
|
195
|
+
console.log(pool)
|
|
196
|
+
}
|
|
167
197
|
if ( !accept(req,res,
|
|
168
198
|
['application/jsontag','application/json','text/html','text/javascript','image/*'],
|
|
169
199
|
function(req, res, accept) {
|
|
@@ -182,7 +212,7 @@ async function main(options) {
|
|
|
182
212
|
// done
|
|
183
213
|
return
|
|
184
214
|
}
|
|
185
|
-
let path = req.
|
|
215
|
+
let path = req.params.remainder?.join('/') || '/'
|
|
186
216
|
console.log('query',path)
|
|
187
217
|
let request = {
|
|
188
218
|
method: req.method,
|
|
@@ -194,7 +224,7 @@ async function main(options) {
|
|
|
194
224
|
request.jsontag = true
|
|
195
225
|
}
|
|
196
226
|
try {
|
|
197
|
-
let result = await
|
|
227
|
+
let result = await pool.run('query', request)
|
|
198
228
|
sendResponse(result, res)
|
|
199
229
|
} catch(error) {
|
|
200
230
|
sendError(error, res)
|
|
@@ -203,7 +233,14 @@ async function main(options) {
|
|
|
203
233
|
console.log(path, (end-start), process.memoryUsage())
|
|
204
234
|
}
|
|
205
235
|
|
|
206
|
-
async function
|
|
236
|
+
async function handleSlowGetQuery(req, res) {
|
|
237
|
+
return handleGetQuery(req, res, slowQueryWorkerPool)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async function handlePostQuery(req,res,pool=null) {
|
|
241
|
+
if (!pool) {
|
|
242
|
+
pool = queryWorkerPool
|
|
243
|
+
}
|
|
207
244
|
let start = Date.now()
|
|
208
245
|
if ( !accept(req,res,
|
|
209
246
|
['application/jsontag','application/json'])
|
|
@@ -211,7 +248,7 @@ async function main(options) {
|
|
|
211
248
|
sendError({code:406, message:'Not Acceptable',accept:['application/json','application/jsontag']},res)
|
|
212
249
|
return
|
|
213
250
|
}
|
|
214
|
-
let path = req.
|
|
251
|
+
let path = req.params.remainder?.join('/') || '/'
|
|
215
252
|
let request = {
|
|
216
253
|
method: req.method,
|
|
217
254
|
url: req.originalUrl,
|
|
@@ -223,7 +260,7 @@ async function main(options) {
|
|
|
223
260
|
request.jsontag = true
|
|
224
261
|
}
|
|
225
262
|
try {
|
|
226
|
-
let result = await
|
|
263
|
+
let result = await pool.run('query', request)
|
|
227
264
|
sendResponse(result, res)
|
|
228
265
|
} catch(error) {
|
|
229
266
|
sendError(error, res)
|
|
@@ -233,6 +270,10 @@ async function main(options) {
|
|
|
233
270
|
// queryWorkerPool.memoryUsage()
|
|
234
271
|
}
|
|
235
272
|
|
|
273
|
+
async function handleSlowPostQuery(req, res) {
|
|
274
|
+
return handlePostQuery(req, res, slowQueryWorkerPool)
|
|
275
|
+
}
|
|
276
|
+
|
|
236
277
|
async function handlePostCommand(req, res) {
|
|
237
278
|
let commandId = checkCommand(req, res)
|
|
238
279
|
if (!commandId) {
|
|
@@ -253,6 +294,7 @@ async function main(options) {
|
|
|
253
294
|
meta,
|
|
254
295
|
data:jsontagBuffers,
|
|
255
296
|
commandsFile,
|
|
297
|
+
indexFile,
|
|
256
298
|
datafile
|
|
257
299
|
})
|
|
258
300
|
let result
|
package/www/home.html
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<meta charset="utf-8">
|
|
3
|
+
<link rel="stylesheet" href="/assets/css/style.css">
|
|
4
|
+
<title>SimplyStore</title>
|
|
5
|
+
<body>
|
|
6
|
+
<h1>SimplyStore</h1>
|
|
7
|
+
<h2>In memory database and API</h2>
|
|
8
|
+
<p>This is a placeholder page. To run queries go to <a href="query/">the <code>/query</code> endpoint</a></p>
|
|
9
|
+
<p>You can override this placeholder page by adding this to your SimplyStore server code:</p>
|
|
10
|
+
<pre>
|
|
11
|
+
import SimplyStore from '@muze-nl/simplystore'
|
|
12
|
+
|
|
13
|
+
SimplyStore.get('/', function(req, res) {
|
|
14
|
+
res.setHeader('Content-Type', 'text/html')
|
|
15
|
+
res.send('Your homepage content')
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
SimplyStore.run()
|
|
19
|
+
</pre>
|
|
20
|
+
</body>
|
|
21
|
+
|