@muze-nl/simplystore 0.5.2 → 0.5.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/package.json +1 -1
- package/src/command-worker-module.mjs +25 -22
- package/src/command-worker.mjs +2 -6
- package/src/fastParse.mjs +40 -51
- package/src/server.mjs +44 -33
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import JSONTag from '@muze-nl/jsontag'
|
|
2
|
-
import {source} from './symbols.mjs'
|
|
2
|
+
import {source, isChanged} from './symbols.mjs'
|
|
3
3
|
import fastParse from './fastParse.mjs'
|
|
4
4
|
import {stringToSAB,resultSetStringify} from './fastStringify.mjs'
|
|
5
5
|
import writeFileAtomic from 'write-file-atomic'
|
|
@@ -25,7 +25,7 @@ export const metaIdProxy = {
|
|
|
25
25
|
})
|
|
26
26
|
},
|
|
27
27
|
set: (id,ref) => {
|
|
28
|
-
//
|
|
28
|
+
//FIXME: is this correct?
|
|
29
29
|
meta.index.id.set(id, resultSet.length-1)
|
|
30
30
|
},
|
|
31
31
|
get: (id) => {
|
|
@@ -46,7 +46,10 @@ export const metaIdProxy = {
|
|
|
46
46
|
export const FastJSONTag = {
|
|
47
47
|
getType: (obj) => JSONTag.getType(obj[source]),
|
|
48
48
|
getAttribute: (obj, attr) => JSONTag.getAttribute(obj[source],attr),
|
|
49
|
-
setAttribute: (obj, attr, value) =>
|
|
49
|
+
setAttribute: (obj, attr, value) => {
|
|
50
|
+
obj[isChanged] = true
|
|
51
|
+
return JSONTag.setAttribute(obj[source], attr, value)
|
|
52
|
+
},
|
|
50
53
|
getAttributes: (obj) => JSONTag.getAttributes(obj[source]),
|
|
51
54
|
getAttributeString: (obj) => JSONTag.getAttributesString(obj[source]),
|
|
52
55
|
getTypeString: (obj) => JSONTag.getTypeString(obj[source])
|
|
@@ -59,6 +62,7 @@ export async function initialize(task) {
|
|
|
59
62
|
metaProxy.index.id = metaIdProxy
|
|
60
63
|
datafile = task.datafile
|
|
61
64
|
commands = await import(task.commandsFile).then(mod => {
|
|
65
|
+
console.log('commands loaded:',Object.keys(mod.default))
|
|
62
66
|
return mod.default
|
|
63
67
|
})
|
|
64
68
|
}
|
|
@@ -71,29 +75,28 @@ export default async function runCommand(commandStr, request) {
|
|
|
71
75
|
jsontag: true
|
|
72
76
|
}
|
|
73
77
|
if (commands[task.name]) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
let time = Date.now()
|
|
79
|
+
commands[task.name](dataspace, task, request, metaProxy)
|
|
80
|
+
FastJSONTag.setAttribute(dataspace, 'command', task.id)
|
|
77
81
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
82
|
+
const strData = resultSetStringify(resultSet)
|
|
83
|
+
const uint8sab = stringToSAB(strData)
|
|
84
|
+
response.data = uint8sab
|
|
85
|
+
response.meta = {
|
|
86
|
+
index: {
|
|
87
|
+
id: meta.index.id
|
|
85
88
|
}
|
|
86
|
-
|
|
87
|
-
await writeFileAtomic(datafile, uint8sab)
|
|
88
|
-
} catch(err) {
|
|
89
|
-
console.error('error',err)
|
|
90
|
-
response.code = 422;
|
|
91
|
-
response.body = '<object class="Error">{"message":'+JSON.stringify(''+err)+',"code":422}'
|
|
92
89
|
}
|
|
90
|
+
|
|
91
|
+
await writeFileAtomic(datafile, uint8sab)
|
|
92
|
+
let end = Date.now()
|
|
93
|
+
console.log('task time',end-time)
|
|
93
94
|
} else {
|
|
94
|
-
console.error('Command not found', task.name
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
console.error('Command not found', task.name)
|
|
96
|
+
throw {
|
|
97
|
+
code: 404,
|
|
98
|
+
message: "Command "+task.name+" not found"
|
|
99
|
+
}
|
|
97
100
|
}
|
|
98
101
|
return response
|
|
99
102
|
}
|
package/src/command-worker.mjs
CHANGED
|
@@ -3,11 +3,7 @@ import runCommand, { initialize } from '../src/command-worker-module.mjs'
|
|
|
3
3
|
|
|
4
4
|
parentPort.on('message', async data => {
|
|
5
5
|
let result
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
result = await runCommand(data.command)
|
|
9
|
-
} catch(err) {
|
|
10
|
-
result = { error: err.message }
|
|
11
|
-
}
|
|
6
|
+
await initialize(data)
|
|
7
|
+
result = await runCommand(data.command)
|
|
12
8
|
parentPort.postMessage(result)
|
|
13
9
|
})
|
package/src/fastParse.mjs
CHANGED
|
@@ -567,9 +567,9 @@ export default function parse(input, meta, immutable=true)
|
|
|
567
567
|
error("Input stopped early")
|
|
568
568
|
}
|
|
569
569
|
|
|
570
|
-
let object = function()
|
|
570
|
+
let object = function(object={})
|
|
571
571
|
{
|
|
572
|
-
let key, val
|
|
572
|
+
let key, val
|
|
573
573
|
if (ch !== '{') {
|
|
574
574
|
error("Syntax Error")
|
|
575
575
|
}
|
|
@@ -638,10 +638,10 @@ export default function parse(input, meta, immutable=true)
|
|
|
638
638
|
return parseInt(numString)
|
|
639
639
|
}
|
|
640
640
|
|
|
641
|
-
let parseValue = function(position) {
|
|
641
|
+
let parseValue = function(position, ob={}) {
|
|
642
642
|
at = position.start
|
|
643
643
|
next()
|
|
644
|
-
return value()
|
|
644
|
+
return value(ob)
|
|
645
645
|
}
|
|
646
646
|
|
|
647
647
|
const makeChildProxies = function(parent) {
|
|
@@ -704,7 +704,7 @@ export default function parse(input, meta, immutable=true)
|
|
|
704
704
|
if (i != index) {
|
|
705
705
|
return encoder.encode('~'+index)
|
|
706
706
|
}
|
|
707
|
-
// return newly stringified contents of
|
|
707
|
+
// return newly stringified contents of target
|
|
708
708
|
return encoder.encode(fastStringify(target, meta, true, i))
|
|
709
709
|
}
|
|
710
710
|
break
|
|
@@ -726,7 +726,7 @@ export default function parse(input, meta, immutable=true)
|
|
|
726
726
|
if (JSONTag.getType(value)==='object' && !value[isProxy]) {
|
|
727
727
|
value = getNewValueProxy(value)
|
|
728
728
|
}
|
|
729
|
-
|
|
729
|
+
target[prop] = val
|
|
730
730
|
return true
|
|
731
731
|
}
|
|
732
732
|
}
|
|
@@ -749,6 +749,12 @@ export default function parse(input, meta, immutable=true)
|
|
|
749
749
|
let parsed = false
|
|
750
750
|
at += length
|
|
751
751
|
next()
|
|
752
|
+
let firstParse = function() {
|
|
753
|
+
if (!parsed) {
|
|
754
|
+
parseValue(position, cache)
|
|
755
|
+
parsed = true
|
|
756
|
+
}
|
|
757
|
+
}
|
|
752
758
|
// newValueHandler makes sure that value[getBuffer] runs stringify
|
|
753
759
|
// arrayHandler makes sure that changes in the array set targetIsChanged to true
|
|
754
760
|
let arrayHandler = {
|
|
@@ -794,13 +800,10 @@ export default function parse(input, meta, immutable=true)
|
|
|
794
800
|
}
|
|
795
801
|
let handler = {
|
|
796
802
|
get(target, prop, receiver) {
|
|
797
|
-
|
|
798
|
-
cache = parseValue(position)
|
|
799
|
-
parsed = true
|
|
800
|
-
}
|
|
803
|
+
firstParse()
|
|
801
804
|
switch(prop) {
|
|
802
805
|
case source:
|
|
803
|
-
return
|
|
806
|
+
return target
|
|
804
807
|
break
|
|
805
808
|
case isProxy:
|
|
806
809
|
return true
|
|
@@ -812,8 +815,8 @@ export default function parse(input, meta, immutable=true)
|
|
|
812
815
|
}
|
|
813
816
|
if (targetIsChanged) {
|
|
814
817
|
// return newly stringified contents of cache
|
|
815
|
-
let temp = fastStringify(
|
|
816
|
-
return encoder.encode(fastStringify(
|
|
818
|
+
let temp = fastStringify(target, null, true)
|
|
819
|
+
return encoder.encode(fastStringify(target, null, true))
|
|
817
820
|
}
|
|
818
821
|
return input.slice(position.start,position.end)
|
|
819
822
|
}
|
|
@@ -825,57 +828,43 @@ export default function parse(input, meta, immutable=true)
|
|
|
825
828
|
return targetIsChanged
|
|
826
829
|
break
|
|
827
830
|
default:
|
|
828
|
-
if (!immutable && Array.isArray(
|
|
829
|
-
return new Proxy(
|
|
831
|
+
if (!immutable && Array.isArray(target[prop])) {
|
|
832
|
+
return new Proxy(target[prop], arrayHandler)
|
|
830
833
|
}
|
|
831
|
-
return
|
|
834
|
+
return target[prop] // FIXME: make arrays immutable as well
|
|
832
835
|
break
|
|
833
836
|
}
|
|
834
837
|
},
|
|
835
|
-
|
|
836
|
-
if (!
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
if (!parsed) {
|
|
844
|
-
cache = parseValue(position)
|
|
845
|
-
parsed = true
|
|
846
|
-
}
|
|
847
|
-
return Reflect.ownKeys(cache)
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
if (!immutable) {
|
|
851
|
-
Object.assign(handler, {
|
|
852
|
-
set: (target, prop, val) => {
|
|
853
|
-
if (!parsed) {
|
|
854
|
-
cache = parseValue(position)
|
|
855
|
-
parsed = true
|
|
856
|
-
}
|
|
857
|
-
if (JSONTag.getType(val)==='object' && !val[isProxy]) {
|
|
858
|
-
val = getNewValueProxy(val)
|
|
838
|
+
set(target, prop, value) {
|
|
839
|
+
if (!immutable) {
|
|
840
|
+
firstParse()
|
|
841
|
+
if (prop!==isChanged) {
|
|
842
|
+
if (JSONTag.getType(value)==='object' && !value[isProxy]) {
|
|
843
|
+
value = getNewValueProxy(value)
|
|
844
|
+
}
|
|
845
|
+
target[prop] = value
|
|
859
846
|
}
|
|
860
|
-
cache[prop] = val
|
|
861
847
|
targetIsChanged = true
|
|
862
848
|
return true
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
delete cache[prop]
|
|
849
|
+
}
|
|
850
|
+
},
|
|
851
|
+
deleteProperty: (target, prop) => {
|
|
852
|
+
if (!immutable) {
|
|
853
|
+
firstParse()
|
|
854
|
+
delete target[prop]
|
|
870
855
|
targetIsChanged = true
|
|
871
856
|
return true
|
|
872
857
|
}
|
|
873
|
-
}
|
|
858
|
+
},
|
|
859
|
+
'ownKeys': (target) => {
|
|
860
|
+
firstParse()
|
|
861
|
+
return Reflect.ownKeys(target)
|
|
862
|
+
}
|
|
874
863
|
}
|
|
875
864
|
return new Proxy(cache, handler)
|
|
876
865
|
}
|
|
877
866
|
|
|
878
|
-
value = function()
|
|
867
|
+
value = function(ob={})
|
|
879
868
|
{
|
|
880
869
|
let tagOb, result, tagName;
|
|
881
870
|
whitespace()
|
|
@@ -893,7 +882,7 @@ export default function parse(input, meta, immutable=true)
|
|
|
893
882
|
if (tagName && tagName!=='object') {
|
|
894
883
|
isTypeError(tagName, ch)
|
|
895
884
|
}
|
|
896
|
-
result = object()
|
|
885
|
+
result = object(ob)
|
|
897
886
|
break
|
|
898
887
|
case '[':
|
|
899
888
|
if (tagName && tagName!=='array') {
|
package/src/server.mjs
CHANGED
|
@@ -153,7 +153,7 @@ async function main(options) {
|
|
|
153
153
|
let lines = file.split("\n").filter(Boolean) //filter clears empty lines
|
|
154
154
|
for(let line of lines) {
|
|
155
155
|
let command = JSONTag.parse(line)
|
|
156
|
-
status.set(command.id, command
|
|
156
|
+
status.set(command.id, command)
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
}
|
|
@@ -208,31 +208,38 @@ async function main(options) {
|
|
|
208
208
|
start(
|
|
209
209
|
// resolve()
|
|
210
210
|
(data) => {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
211
|
+
let s
|
|
212
|
+
if (!data || (data.code>=300 && data.code<=499)) {
|
|
213
|
+
console.error('ERROR: SimplyStore cannot run command ', command.id, data)
|
|
214
|
+
if (!data?.code) {
|
|
215
|
+
s = {code: 500, status: "failed"}
|
|
216
216
|
} else {
|
|
217
|
-
status.
|
|
218
|
-
|
|
217
|
+
s = {code: data.code, status: "failed", message: data.message, details: data.details}
|
|
218
|
+
}
|
|
219
|
+
status.set(command.id, s)
|
|
220
|
+
} else {
|
|
221
|
+
s = {code: 200, status: "done"}
|
|
222
|
+
status.set(command.id, s)
|
|
223
|
+
if (data.data) { // data has changed, commands may do other things instead of changing data
|
|
224
|
+
jsontagBuffer = data.data
|
|
225
|
+
meta = data.meta
|
|
226
|
+
// restart query workers with new data
|
|
227
|
+
let oldPool = queryWorkerPool
|
|
228
|
+
queryWorkerPool = new WorkerPool(maxWorkers, queryWorker, queryWorkerInitTask())
|
|
229
|
+
setTimeout(() => {
|
|
230
|
+
oldPool.close()
|
|
231
|
+
}, 2000)
|
|
219
232
|
}
|
|
220
233
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
appendFile(commandStatus, JSONTag.stringify({command:command.id, status: 'done'}))
|
|
225
|
-
// restart query workers with new data
|
|
226
|
-
let oldPool = queryWorkerPool
|
|
227
|
-
queryWorkerPool = new WorkerPool(maxWorkers, queryWorker, queryWorkerInitTask())
|
|
228
|
-
setTimeout(() => {
|
|
229
|
-
oldPool.close()
|
|
230
|
-
}, 2000)
|
|
234
|
+
let l = Object.assign({command:command.id}, s)
|
|
235
|
+
console.log('appending status ',l,s)
|
|
236
|
+
appendFile(commandStatus, JSONTag.stringify(Object.assign({command:command.id}, s)))
|
|
231
237
|
},
|
|
232
238
|
//reject()
|
|
233
239
|
(error) => {
|
|
234
|
-
status.
|
|
235
|
-
|
|
240
|
+
let s = {status: "failed", code: error.code, message: error.message, details: error.details}
|
|
241
|
+
status.set(command.id, s)
|
|
242
|
+
appendFile(commandStatus, JSONTag.stringify(Object.assign({command:command.id}, s)))
|
|
236
243
|
}
|
|
237
244
|
)
|
|
238
245
|
} else {
|
|
@@ -270,8 +277,9 @@ async function main(options) {
|
|
|
270
277
|
|
|
271
278
|
runNextCommand()
|
|
272
279
|
} catch(err) {
|
|
273
|
-
|
|
274
|
-
status.set(commandId,
|
|
280
|
+
let s = {code:err.code||500, status:'failed', message:err.message, details:err.details}
|
|
281
|
+
status.set(commandId, s)
|
|
282
|
+
appendFile(commandStatus, JSONTag.stringify(Object.assign({command:commandId}, s)))
|
|
275
283
|
console.error('ERROR: SimplyStore cannot run command ', commandId, err)
|
|
276
284
|
}
|
|
277
285
|
})
|
|
@@ -279,32 +287,35 @@ async function main(options) {
|
|
|
279
287
|
function checkCommand(req, res) {
|
|
280
288
|
let commandStr = req.body.toString() // raw body through express.raw()
|
|
281
289
|
let command = JSONTag.parse(commandStr)
|
|
290
|
+
let commandOK = {
|
|
291
|
+
command: command?.id,
|
|
292
|
+
code: 202,
|
|
293
|
+
status: 'accepted'
|
|
294
|
+
}
|
|
282
295
|
if (!command || !command.id) {
|
|
283
296
|
error = {
|
|
284
297
|
code: 422,
|
|
285
|
-
message: "Command has no id"
|
|
298
|
+
message: "Command has no id",
|
|
299
|
+
details: command
|
|
286
300
|
}
|
|
287
301
|
sendResponse({code: 422, body: JSON.stringify(error)}, res)
|
|
288
302
|
return false
|
|
289
303
|
} else if (status.has(command.id)) {
|
|
290
|
-
|
|
291
|
-
sendResponse({body: JSON.stringify(result)}, res)
|
|
304
|
+
sendResponse({body: JSON.stringify(s)}, res)
|
|
292
305
|
return false
|
|
293
306
|
} else if (!command.name) {
|
|
294
307
|
error = {
|
|
295
308
|
code: 422,
|
|
296
|
-
message: "Command has no name"
|
|
309
|
+
message: "Command has no name",
|
|
310
|
+
details: command
|
|
297
311
|
}
|
|
298
312
|
sendResponse({code:422, body: JSON.stringify(error)}, res)
|
|
299
313
|
return false
|
|
300
314
|
}
|
|
301
315
|
appendFile(commandLog, JSONTag.stringify(command))
|
|
302
|
-
appendFile(commandStatus, JSONTag.stringify(
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}))
|
|
306
|
-
status.set(command.id, 'accepted')
|
|
307
|
-
sendResponse({code: 202, body: '"Accepted"'}, res)
|
|
316
|
+
appendFile(commandStatus, JSONTag.stringify(commandOK))
|
|
317
|
+
status.set(command.id, commandOK)
|
|
318
|
+
sendResponse({code: 202, body: JSON.stringify(commandOK)}, res)
|
|
308
319
|
return command.id
|
|
309
320
|
}
|
|
310
321
|
|
|
@@ -319,7 +330,7 @@ async function main(options) {
|
|
|
319
330
|
sendResponse({
|
|
320
331
|
code: 404,
|
|
321
332
|
jsontag: false,
|
|
322
|
-
body: JSON.stringify({code: 404, message: "Command not found"})
|
|
333
|
+
body: JSON.stringify({code: 404, message: "Command not found", details: req.params.id})
|
|
323
334
|
}, res)
|
|
324
335
|
}
|
|
325
336
|
})
|