@muze-nl/simplystore 0.4.7 → 0.5.0
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 +12 -4
- package/scripts/convert.mjs +25 -0
- package/src/command-worker-module.mjs +100 -0
- package/src/command-worker.mjs +13 -0
- package/src/fastParse.mjs +1036 -0
- package/src/fastStringify.mjs +200 -0
- package/src/load-worker.mjs +33 -0
- package/src/{worker-query.mjs → query-worker-module.mjs} +138 -83
- package/src/query-worker.mjs +12 -0
- package/src/server.mjs +303 -218
- package/src/statusCodes.mjs +70 -0
- package/src/symbols.mjs +6 -0
- package/src/util.mjs +3 -3
- package/src/workerPool.mjs +99 -0
- package/data.jsontag +0 -20
- package/src/share.mjs +0 -142
- package/src/worker-query-init.mjs +0 -14
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const httpStatusCodes = {
|
|
2
|
+
'100': 'Continue',
|
|
3
|
+
'101': 'Switching Protocols',
|
|
4
|
+
'102': 'Processing',
|
|
5
|
+
'103': 'Early Hints',
|
|
6
|
+
'200': 'OK',
|
|
7
|
+
'201': 'Created',
|
|
8
|
+
'200': 'OK',
|
|
9
|
+
'201': 'Created',
|
|
10
|
+
'202': 'Accepted',
|
|
11
|
+
'203': 'Non-Authoritative Information',
|
|
12
|
+
'204': 'No Content',
|
|
13
|
+
'205': 'Reset Content',
|
|
14
|
+
'206': 'Partial Content',
|
|
15
|
+
'207': 'Multi-Status',
|
|
16
|
+
'208': 'Already Reported',
|
|
17
|
+
'226': 'IM Used',
|
|
18
|
+
'300': 'Multiple Choices',
|
|
19
|
+
'301': 'Moved Permanently',
|
|
20
|
+
'302': 'Found',
|
|
21
|
+
'303': 'See Other',
|
|
22
|
+
'304': 'Not Modified',
|
|
23
|
+
'305': 'Use Proxy',
|
|
24
|
+
'306': '(Unused)',
|
|
25
|
+
'307': 'Temporary Redirect',
|
|
26
|
+
'308': 'Permanent Redirect (experimental)',
|
|
27
|
+
'400': 'Bad Request',
|
|
28
|
+
'401': 'Unauthorized',
|
|
29
|
+
'402': 'Payment Required',
|
|
30
|
+
'403': 'Forbidden',
|
|
31
|
+
'404': 'Not Found',
|
|
32
|
+
'405': 'Method Not Allowed',
|
|
33
|
+
'406': 'Not Acceptable',
|
|
34
|
+
'407': 'Proxy Authentication Required',
|
|
35
|
+
'408': 'Request Timeout',
|
|
36
|
+
'409': 'Conflict',
|
|
37
|
+
'410': 'Gone',
|
|
38
|
+
'411': 'Length Required',
|
|
39
|
+
'412': 'Precondition Failed',
|
|
40
|
+
'413': 'Request Entity Too Large',
|
|
41
|
+
'414': 'Request-URI Too Long',
|
|
42
|
+
'415': 'Unsupported Media Type',
|
|
43
|
+
'416': 'Requested Range Not Satisfiable',
|
|
44
|
+
'417': 'Expectation Failed',
|
|
45
|
+
'418': 'I\'m a teapot (RFC 2324)',
|
|
46
|
+
'420': 'Enhance Your Calm (Twitter)',
|
|
47
|
+
'422': 'Unprocessable Entity (WebDAV)',
|
|
48
|
+
'423': 'Locked (WebDAV)',
|
|
49
|
+
'424': 'Failed Dependency (WebDAV)',
|
|
50
|
+
'425': 'Reserved for WebDAV',
|
|
51
|
+
'426': 'Upgrade Required',
|
|
52
|
+
'428': 'Precondition Required',
|
|
53
|
+
'429': 'Too Many Requests',
|
|
54
|
+
'431': 'Request Header Fields Too Large',
|
|
55
|
+
'451': 'Unavailable For Legal Reasons',
|
|
56
|
+
'500': 'Internal Server Error',
|
|
57
|
+
'501': 'Not Implemented',
|
|
58
|
+
'502': 'Bad Gateway',
|
|
59
|
+
'503': 'Service Unavailable',
|
|
60
|
+
'504': 'Gateway Timeout',
|
|
61
|
+
'505': 'HTTP Version Not Supported',
|
|
62
|
+
'506': 'Variant Also Negotiates (Experimental)',
|
|
63
|
+
'507': 'Insufficient Storage (WebDAV)',
|
|
64
|
+
'508': 'Loop Detected (WebDAV)',
|
|
65
|
+
'509': 'Bandwidth Limit Exceeded (Apache)',
|
|
66
|
+
'510': 'Not Extended',
|
|
67
|
+
'511': 'Network Authentication Required',
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export default httpStatusCodes
|
package/src/symbols.mjs
ADDED
package/src/util.mjs
CHANGED
|
@@ -33,14 +33,14 @@ export function joinArgs(args) {
|
|
|
33
33
|
* @return {void}
|
|
34
34
|
*/
|
|
35
35
|
export async function appendFile(filename, data) {
|
|
36
|
-
console.log('appending command')
|
|
37
36
|
let handle;
|
|
38
37
|
try {
|
|
39
|
-
handle = await fs.open(filename, 'a')
|
|
38
|
+
handle = await fs.open(filename, 'a+')
|
|
40
39
|
await handle.appendFile(data+"\n")
|
|
41
40
|
await handle.datasync()
|
|
42
41
|
return true
|
|
43
42
|
} finally {
|
|
44
43
|
await handle.close()
|
|
45
44
|
}
|
|
46
|
-
}
|
|
45
|
+
}
|
|
46
|
+
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { AsyncResource } from 'async_hooks'
|
|
2
|
+
import { EventEmitter } from 'events'
|
|
3
|
+
import path from 'path'
|
|
4
|
+
import { Worker } from 'worker_threads'
|
|
5
|
+
|
|
6
|
+
const kTaskInfo = Symbol('kTaskInfo');
|
|
7
|
+
const kWorkerFreedEvent = Symbol('kWorkerFreedEvent');
|
|
8
|
+
|
|
9
|
+
class WorkerPoolTaskInfo extends AsyncResource {
|
|
10
|
+
constructor(callback) {
|
|
11
|
+
super('WorkerPoolTaskInfo');
|
|
12
|
+
this.callback = callback;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
done(err, result) {
|
|
16
|
+
this.runInAsyncScope(this.callback, null, err, result);
|
|
17
|
+
this.emitDestroy(); // `TaskInfo`s are used only once.
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//@TODO: only create new workers when needed, not immediately
|
|
22
|
+
//@TODO: allow initialization of newly created workers
|
|
23
|
+
|
|
24
|
+
export default class WorkerPool extends EventEmitter {
|
|
25
|
+
constructor(numThreads, workerFile, initTask) {
|
|
26
|
+
super()
|
|
27
|
+
this.numThreads = numThreads
|
|
28
|
+
this.workerFile = workerFile
|
|
29
|
+
this.initTask = initTask
|
|
30
|
+
this.workers = []
|
|
31
|
+
this.freeWorkers = []
|
|
32
|
+
|
|
33
|
+
for (let i = 0; i < numThreads; i++)
|
|
34
|
+
this.addNewWorker();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
addNewWorker() {
|
|
38
|
+
const worker = new Worker(path.resolve(this.workerFile));
|
|
39
|
+
worker.on('message', (result) => {
|
|
40
|
+
// In case of success: Call the callback that was passed to `runTask`,
|
|
41
|
+
// remove the `TaskInfo` associated with the Worker, and mark it as free
|
|
42
|
+
// again.
|
|
43
|
+
if (worker[kTaskInfo]) {
|
|
44
|
+
worker[kTaskInfo].done(null, result);
|
|
45
|
+
worker[kTaskInfo] = null;
|
|
46
|
+
}
|
|
47
|
+
this.freeWorkers.push(worker);
|
|
48
|
+
this.emit(kWorkerFreedEvent);
|
|
49
|
+
});
|
|
50
|
+
worker.on('error', (err) => {
|
|
51
|
+
// In case of an uncaught exception: Call the callback that was passed to
|
|
52
|
+
// `runTask` with the error.
|
|
53
|
+
if (worker[kTaskInfo])
|
|
54
|
+
worker[kTaskInfo].done(err, null);
|
|
55
|
+
else
|
|
56
|
+
this.emit('error', err);
|
|
57
|
+
// Remove the worker from the list and start a new Worker to replace the
|
|
58
|
+
// current one.
|
|
59
|
+
this.workers.splice(this.workers.indexOf(worker), 1);
|
|
60
|
+
this.addNewWorker();
|
|
61
|
+
});
|
|
62
|
+
this.workers.push(worker);
|
|
63
|
+
worker.postMessage(this.initTask);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async run(name, req) {
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
this.runTask({name,req}, (error, result) => {
|
|
69
|
+
if (error) {
|
|
70
|
+
return reject(error)
|
|
71
|
+
}
|
|
72
|
+
return resolve(result)
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
runTask(task, callback) {
|
|
78
|
+
if (this.freeWorkers.length === 0) {
|
|
79
|
+
// No free threads, wait until a worker thread becomes free.
|
|
80
|
+
console.log('no free worker.. waiting')
|
|
81
|
+
this.once(kWorkerFreedEvent, () => this.runTask(task, callback));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const worker = this.freeWorkers.pop();
|
|
85
|
+
worker[kTaskInfo] = new WorkerPoolTaskInfo(callback);
|
|
86
|
+
worker.postMessage(task);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
memoryUsage() {
|
|
90
|
+
for (let worker of this.freeWorkers) {
|
|
91
|
+
worker[kTaskInfo] = new WorkerPoolTaskInfo((result) => {})
|
|
92
|
+
worker.postMessage({name:'memoryUsage'})
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
close() {
|
|
97
|
+
for (const worker of this.workers) worker.terminate();
|
|
98
|
+
}
|
|
99
|
+
}
|
package/data.jsontag
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"persons": [
|
|
3
|
-
<object id="john" class="Person">{
|
|
4
|
-
"name": "John",
|
|
5
|
-
"lastName": "Doe",
|
|
6
|
-
"dob": <date>"1972-09-20",
|
|
7
|
-
"foaf": [
|
|
8
|
-
<link>"jane"
|
|
9
|
-
]
|
|
10
|
-
},
|
|
11
|
-
<object id="jane" class="Person">{
|
|
12
|
-
"name": "Jane",
|
|
13
|
-
"lastName": "Doe",
|
|
14
|
-
"dob": <date>"1986-01-01",
|
|
15
|
-
"foaf": [
|
|
16
|
-
<link>"john"
|
|
17
|
-
]
|
|
18
|
-
}
|
|
19
|
-
]
|
|
20
|
-
}
|
package/src/share.mjs
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import JSONTag from '@muze-nl/jsontag'
|
|
2
|
-
|
|
3
|
-
const handler = function(root, index, buffer)
|
|
4
|
-
{
|
|
5
|
-
return {
|
|
6
|
-
get(target, key, receiver)
|
|
7
|
-
{
|
|
8
|
-
let keyNumber = index.key[key]
|
|
9
|
-
if (root[keyNumber]) {
|
|
10
|
-
let keyStart = root[keyNumber].s + root.s
|
|
11
|
-
let keyEnd = root[keyNumber].e + root.s
|
|
12
|
-
subobjecten hoeven niet geparsed...
|
|
13
|
-
if (root[keyNumber].c) {
|
|
14
|
-
// object
|
|
15
|
-
return new jsontagProxy(root[keyNumber], index, buffer)
|
|
16
|
-
}
|
|
17
|
-
return JSON.parse(buffer.slice(keyStart,keyEnd))
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
has(target, key)
|
|
22
|
-
{
|
|
23
|
-
let keyNumber = index.key[key]
|
|
24
|
-
return typeof root[keyNumber] !== 'undefined'
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
ownKeys(target)
|
|
28
|
-
{
|
|
29
|
-
return root.c.map(n => index.reverse[n])
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export class jsontagProxy extends proxy
|
|
35
|
-
{
|
|
36
|
-
constructor(root, index, buffer)
|
|
37
|
-
{
|
|
38
|
-
super({}, handler(root, index, buffer))
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export default function share(data)
|
|
44
|
-
{
|
|
45
|
-
let jsontag = JSONTag.stringify(data)
|
|
46
|
-
let buffer = new SharedArrayBuffer(jsontag.length)
|
|
47
|
-
let dv = new DataView(buffer)
|
|
48
|
-
let encode = new TextEncoder('utf-8')
|
|
49
|
-
let root = {}
|
|
50
|
-
let index = {
|
|
51
|
-
key: {},
|
|
52
|
-
reverse: [],
|
|
53
|
-
types: {}
|
|
54
|
-
}
|
|
55
|
-
let current = 0
|
|
56
|
-
|
|
57
|
-
function getKey(key) {
|
|
58
|
-
let l;
|
|
59
|
-
if (typeof index.key[key] == 'undefined') {
|
|
60
|
-
l = Object.keys(index.key)
|
|
61
|
-
index.key[key] = l
|
|
62
|
-
index.reverse[l] = key
|
|
63
|
-
}
|
|
64
|
-
return index.key[key]
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function getType(type) {
|
|
68
|
-
if (typeof index.types[type] == 'undefined') {
|
|
69
|
-
l = Object.keys(index.types);
|
|
70
|
-
index.types[type] = l
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function store(container, key, value) {
|
|
76
|
-
let l = getKey(key)
|
|
77
|
-
container[l] = {
|
|
78
|
-
s: current
|
|
79
|
-
}
|
|
80
|
-
container = container[l]
|
|
81
|
-
let attributes = JSONTag.getAttributes(value)
|
|
82
|
-
if (attributes) {
|
|
83
|
-
container.a = {
|
|
84
|
-
s: current,
|
|
85
|
-
c: {}
|
|
86
|
-
}
|
|
87
|
-
attributes.forEach((v,k) => {
|
|
88
|
-
let l = getKey(k)
|
|
89
|
-
let t = getType('string')
|
|
90
|
-
container.a.c[k] = {
|
|
91
|
-
s: current,
|
|
92
|
-
t
|
|
93
|
-
}
|
|
94
|
-
let v = JSON.stringify(value)
|
|
95
|
-
let (r,w) = encoder.encodeInto(v, dv, current)
|
|
96
|
-
current += w
|
|
97
|
-
container.a.c[k].e = current
|
|
98
|
-
})
|
|
99
|
-
}
|
|
100
|
-
let type = JSONTag.getType(node)
|
|
101
|
-
let t = getType(type)
|
|
102
|
-
container.t = t
|
|
103
|
-
let v = JSON.stringify(value)
|
|
104
|
-
let (r,w) = encoder.encodeInto(v, dv, current)
|
|
105
|
-
current+= w
|
|
106
|
-
container.e = current
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
function walk(node, parentKey, parent, save)
|
|
111
|
-
{
|
|
112
|
-
let type = JSONTag.getType(node)
|
|
113
|
-
let t = getType(type)
|
|
114
|
-
switch (type) {
|
|
115
|
-
case 'array':
|
|
116
|
-
save.s = current
|
|
117
|
-
save.t = t
|
|
118
|
-
save.c = []
|
|
119
|
-
node.forEach((v,k) => walk(v, k, node, save.c))
|
|
120
|
-
save.e = current
|
|
121
|
-
break
|
|
122
|
-
case 'object':
|
|
123
|
-
save.s = current
|
|
124
|
-
save.c = []
|
|
125
|
-
save.t = t
|
|
126
|
-
Object.entries(node).forEach((k,v) => walk(v, k, node, save.c))
|
|
127
|
-
save.e = current
|
|
128
|
-
break
|
|
129
|
-
default:
|
|
130
|
-
store(save, parentKey, node)
|
|
131
|
-
break
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
walk(data, null, null, root)
|
|
136
|
-
|
|
137
|
-
return {
|
|
138
|
-
root: new jsontagProxy(root, index, buffer),
|
|
139
|
-
index,
|
|
140
|
-
buffer
|
|
141
|
-
}
|
|
142
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import JSONTag from '@muze-nl/jsontag';
|
|
2
|
-
import worker_threads from 'node:worker_threads';
|
|
3
|
-
import * as queryWorker from './worker-query.mjs';
|
|
4
|
-
|
|
5
|
-
async function initialize() {
|
|
6
|
-
let meta = {}
|
|
7
|
-
let dataspace = JSONTag.parse(worker_threads.workerData, null, meta)
|
|
8
|
-
//console.log('starting')
|
|
9
|
-
await queryWorker.initialize(dataspace,meta)
|
|
10
|
-
//console.log('initialized')
|
|
11
|
-
return queryWorker.runQuery
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export default initialize()
|