datafolder 1.0.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/README.md +169 -0
- package/index.js +3 -0
- package/package.json +27 -0
- package/sample.js +37 -0
- package/scripts/airbnb.js +73 -0
- package/scripts/airbnb2.js +74 -0
- package/scripts/airbnb2_queries.js +231 -0
- package/scripts/airbnb_queries.js +264 -0
- package/scripts/downloadFile.js +42 -0
- package/scripts/express.js +46 -0
- package/scripts/fastify.js +79 -0
- package/scripts/flights.js +75 -0
- package/scripts/flights2.js +81 -0
- package/scripts/flights2_queries.js +453 -0
- package/scripts/flights_queries.js +403 -0
- package/src/QyAcl.js +252 -0
- package/src/QyAclSaver.js +14 -0
- package/src/QyAclSaver_Worker.js +29 -0
- package/src/QyAclWriter.js +19 -0
- package/src/QyBatch.js +501 -0
- package/src/QyBinWriter.js +140 -0
- package/src/QyCD.js +61 -0
- package/src/QyCache.js +212 -0
- package/src/QyCompressor.js +60 -0
- package/src/QyCompressor_Worker.js +13 -0
- package/src/QyDB.js +122 -0
- package/src/QyDefaultOptions.js +59 -0
- package/src/QyDir.js +192 -0
- package/src/QyFetch.js +38 -0
- package/src/QyFile.js +124 -0
- package/src/QyFileContentUtils.js +175 -0
- package/src/QyFileLogger.js +58 -0
- package/src/QyIndex.js +237 -0
- package/src/QyIndexPropTree.js +92 -0
- package/src/QyIntersectNode.js +48 -0
- package/src/QyItem.js +105 -0
- package/src/QyJsonSaver.js +20 -0
- package/src/QyKVData.js +289 -0
- package/src/QyKVDataCleaner.js +17 -0
- package/src/QyKVDataCleaner_Worker.js +94 -0
- package/src/QyKVDataLoader.js +65 -0
- package/src/QyKVDataSaver.js +17 -0
- package/src/QyKVDataSaver_Worker.js +81 -0
- package/src/QyLogFileSaver.js +14 -0
- package/src/QyLogFileSaver_Worker.js +26 -0
- package/src/QyLogger.js +76 -0
- package/src/QyMessageWorker.js +41 -0
- package/src/QyMessager.js +84 -0
- package/src/QyMessager_Run.js +13 -0
- package/src/QyMod.js +15 -0
- package/src/QyOpRunner.js +73 -0
- package/src/QyQueue.js +60 -0
- package/src/QySaver.js +83 -0
- package/src/QySnapshotCompactor.js +17 -0
- package/src/QySnapshotCompactor_Worker.js +151 -0
- package/src/QySnapshotSaver.js +17 -0
- package/src/QySnapshotSaver_Worker.js +164 -0
- package/src/QySnapshots.js +354 -0
- package/src/QyStructure.js +50 -0
- package/src/QyTrigger.js +133 -0
- package/src/QyUnionNode.js +105 -0
- package/src/QyUtils.js +250 -0
- package/src/QyWorker.js +33 -0
- package/src/hackernews.js +93 -0
- package/src/rpc/evalCode.js +9 -0
- package/src/rpc/getFileContent.js +16 -0
- package/src/rpc/getSubItems.js +32 -0
- package/src/rpc/queryFiles.js +33 -0
- package/src/rpc/reloadRpc.js +1 -0
- package/src/simulate.js +114 -0
- package/src/simulate2.js +110 -0
- package/src/soc_pokec.js +43 -0
- package/static/bootstrap-5.3.8-dist/css/bootstrap.min.css +6 -0
- package/static/bootstrap-5.3.8-dist/js/bootstrap.bundle.js +6312 -0
- package/static/datafolderui/QyStyledElement.js +30 -0
- package/static/datafolderui/QyUIFolderTree.js +203 -0
- package/static/datafolderui/QyUIUtils.js +42 -0
- package/static/datafolderui/display-tree.js +108 -0
- package/static/datafolderui/explore-tree.js +122 -0
- package/static/datafolderui/folder-tree.js +5 -0
- package/static/datafolderui/hscrpt.js +25 -0
- package/static/datafolderui/index.css +6 -0
- package/static/datafolderui/index.html +20 -0
- package/static/datafolderui/json-view.js +74 -0
- package/static/datafolderui/kv-input.js +66 -0
- package/static/datafolderui/list-input.js +52 -0
- package/static/datafolderui/main-page.js +98 -0
- package/static/datafolderui/num-input.js +27 -0
- package/static/datafolderui/query-editor.js +229 -0
- package/static/datafolderui/querySelectorShadowRoot.js +24 -0
- package/static/datafolderui/resizable-input.js +67 -0
- package/static/favicon.ico +0 -0
- package/static/icons-1.13.1/font/bootstrap-icons.min.css +5 -0
- package/static/icons-1.13.1/font/fonts/bootstrap-icons.woff +0 -0
- package/static/icons-1.13.1/font/fonts/bootstrap-icons.woff2 +0 -0
- package/static/json-view/dist/jsonview.js +433 -0
- package/static/tree.js/tree.css +106 -0
- package/static/tree.js/tree.js +374 -0
- package/static/w2ui/dist/w2ui.min.css +2 -0
- package/static/w2ui/src/less/icons/icons.json +1 -0
- package/static/w2ui/src/less/icons/preview.html +33 -0
- package/static/w2ui/src/less/icons/readme.md +15 -0
- package/static/w2ui/src/less/icons/svg/box.svg +3 -0
- package/static/w2ui/src/less/icons/svg/check.svg +3 -0
- package/static/w2ui/src/less/icons/svg/colors.svg +3 -0
- package/static/w2ui/src/less/icons/svg/columns.svg +5 -0
- package/static/w2ui/src/less/icons/svg/cross.svg +4 -0
- package/static/w2ui/src/less/icons/svg/drop.svg +6 -0
- package/static/w2ui/src/less/icons/svg/empty.svg +3 -0
- package/static/w2ui/src/less/icons/svg/eye-dropper.svg +4 -0
- package/static/w2ui/src/less/icons/svg/info.svg +8 -0
- package/static/w2ui/src/less/icons/svg/paste.svg +4 -0
- package/static/w2ui/src/less/icons/svg/pencil.svg +5 -0
- package/static/w2ui/src/less/icons/svg/plus.svg +3 -0
- package/static/w2ui/src/less/icons/svg/reload.svg +5 -0
- package/static/w2ui/src/less/icons/svg/search.svg +3 -0
- package/static/w2ui/src/less/icons/svg/settings.svg +8 -0
- package/static/w2ui/src/less/icons/w2ui-font.css +36 -0
- package/static/w2ui/src/less/icons/w2ui-font.woff +0 -0
- package/static/w2ui/src/less/src/buttons.less +184 -0
- package/static/w2ui/src/less/src/common.less +541 -0
- package/static/w2ui/src/less/src/fields.less +302 -0
- package/static/w2ui/src/less/src/form.less +319 -0
- package/static/w2ui/src/less/src/grid.less +1057 -0
- package/static/w2ui/src/less/src/icons.less +37 -0
- package/static/w2ui/src/less/src/layout.less +86 -0
- package/static/w2ui/src/less/src/mixins.less +87 -0
- package/static/w2ui/src/less/src/popup.less +277 -0
- package/static/w2ui/src/less/src/sidebar.less +343 -0
- package/static/w2ui/src/less/src/tabs.less +145 -0
- package/static/w2ui/src/less/src/toolbar.less +219 -0
- package/static/w2ui/src/less/src/tooltip.less +948 -0
- package/static/w2ui/src/less/w2ui.less +196 -0
- package/static/w2ui/src/locale/az-az.json +114 -0
- package/static/w2ui/src/locale/ba-ba.json +114 -0
- package/static/w2ui/src/locale/bg-bg.json +114 -0
- package/static/w2ui/src/locale/ca-es.json +114 -0
- package/static/w2ui/src/locale/da-dk.json +114 -0
- package/static/w2ui/src/locale/de-de.json +114 -0
- package/static/w2ui/src/locale/en-gb.json +17 -0
- package/static/w2ui/src/locale/en-us.json +17 -0
- package/static/w2ui/src/locale/es-ar.json +115 -0
- package/static/w2ui/src/locale/es-cr.json +119 -0
- package/static/w2ui/src/locale/es-es.json +114 -0
- package/static/w2ui/src/locale/es-mx.json +114 -0
- package/static/w2ui/src/locale/fr-fr.json +114 -0
- package/static/w2ui/src/locale/gl-es.json +114 -0
- package/static/w2ui/src/locale/hr-hr.json +114 -0
- package/static/w2ui/src/locale/hu-hu.json +114 -0
- package/static/w2ui/src/locale/id-id.json +114 -0
- package/static/w2ui/src/locale/it-it.json +114 -0
- package/static/w2ui/src/locale/ja-jp.json +114 -0
- package/static/w2ui/src/locale/kk-kz.json +116 -0
- package/static/w2ui/src/locale/ko-kr.json +114 -0
- package/static/w2ui/src/locale/lt-lt.json +114 -0
- package/static/w2ui/src/locale/nl-nl.json +114 -0
- package/static/w2ui/src/locale/no-no.json +114 -0
- package/static/w2ui/src/locale/pl-pl.json +114 -0
- package/static/w2ui/src/locale/pt-br.json +114 -0
- package/static/w2ui/src/locale/ru-ru.json +116 -0
- package/static/w2ui/src/locale/sk-sk.json +114 -0
- package/static/w2ui/src/locale/sl-si.json +116 -0
- package/static/w2ui/src/locale/sr-rs.json +114 -0
- package/static/w2ui/src/locale/tr-tr.json +114 -0
- package/static/w2ui/src/locale/uk-ua.json +114 -0
- package/static/w2ui/src/locale/zh-cn.json +114 -0
- package/static/w2ui/src/locale/zh-tw.json +114 -0
- package/static/w2ui/src/query.js +583 -0
- package/static/w2ui/src/readme.md +11 -0
- package/static/w2ui/src/w2base.js +311 -0
- package/static/w2ui/src/w2compat.js +207 -0
- package/static/w2ui/src/w2field.js +1854 -0
- package/static/w2ui/src/w2form.js +2411 -0
- package/static/w2ui/src/w2grid.js +8916 -0
- package/static/w2ui/src/w2layout.js +1194 -0
- package/static/w2ui/src/w2locale.js +129 -0
- package/static/w2ui/src/w2popup.js +909 -0
- package/static/w2ui/src/w2sidebar.js +1769 -0
- package/static/w2ui/src/w2tabs.js +669 -0
- package/static/w2ui/src/w2toolbar.js +1180 -0
- package/static/w2ui/src/w2tooltip.js +3134 -0
- package/static/w2ui/src/w2utils.js +2457 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
let parentPort = require("node:worker_threads").parentPort, getDefaultOptions = require("./QyDefaultOptions.js").getDefaultOptions, logger = require("./QyLogger.js").logger, QyOpRunner = require("./QyOpRunner.js").QyOpRunner;
|
|
2
|
+
|
|
3
|
+
class QyMessageWorker extends QyOpRunner {
|
|
4
|
+
constructor(e, r, s) {
|
|
5
|
+
super(e = {
|
|
6
|
+
...getDefaultOptions("QyMessageWorker"),
|
|
7
|
+
...e
|
|
8
|
+
}, r, s), parentPort.on("message", async e => {
|
|
9
|
+
var {
|
|
10
|
+
opName: r,
|
|
11
|
+
_cast: s
|
|
12
|
+
} = e;
|
|
13
|
+
if (r) {
|
|
14
|
+
var t = e.args || [];
|
|
15
|
+
try {
|
|
16
|
+
var a = await this[r](...t);
|
|
17
|
+
s || parentPort.postMessage({
|
|
18
|
+
ack: r,
|
|
19
|
+
result: a
|
|
20
|
+
}), "stop" == r && process.exit();
|
|
21
|
+
} catch (e) {
|
|
22
|
+
logger.error(`Running ${r} failed:`, e), s || parentPort.postMessage({
|
|
23
|
+
ack: r,
|
|
24
|
+
exception: e
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
} else logger.warn("Msg ignored:", e);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
castParent(e, ...r) {
|
|
31
|
+
parentPort.postMessage({
|
|
32
|
+
opName: e,
|
|
33
|
+
args: r,
|
|
34
|
+
_cast: !0
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
Object.assign(module.exports, {
|
|
40
|
+
QyMessageWorker: QyMessageWorker
|
|
41
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
let path = require("node:path"), {
|
|
2
|
+
Worker,
|
|
3
|
+
setEnvironmentData
|
|
4
|
+
} = require("node:worker_threads"), getDefaultOptions = require("./QyDefaultOptions.js").getDefaultOptions, logger = require("./QyLogger.js").logger, setPromise = require("./QyUtils.js").setPromise, QyQueue = require("./QyQueue.js").QyQueue;
|
|
5
|
+
|
|
6
|
+
class QyMessager {
|
|
7
|
+
constructor(e, r, t, s, o = [], i = []) {
|
|
8
|
+
s = {
|
|
9
|
+
...getDefaultOptions("QyMessager"),
|
|
10
|
+
...s
|
|
11
|
+
}, Object.assign(this, {
|
|
12
|
+
parent: e,
|
|
13
|
+
workerTypeFileName: r,
|
|
14
|
+
initArgMap: t,
|
|
15
|
+
options: s,
|
|
16
|
+
receiverQueueMap: {}
|
|
17
|
+
});
|
|
18
|
+
for (let r of o) this[r] || (this[r] = (...e) => this.callWorker(r, e));
|
|
19
|
+
for (let r of i) this[r] || (this[r] = (...e) => this.castWorker(r, e));
|
|
20
|
+
}
|
|
21
|
+
start(...e) {
|
|
22
|
+
return this.started = !0, setEnvironmentData("logLevel", logger.level),
|
|
23
|
+
this._startWorker(), this.callWorker("start", e);
|
|
24
|
+
}
|
|
25
|
+
stop(...e) {
|
|
26
|
+
if (this.started) return this.started = !1, this.callWorker("stop", e);
|
|
27
|
+
}
|
|
28
|
+
castWorker(e, r) {
|
|
29
|
+
this.worker.postMessage({
|
|
30
|
+
opName: e,
|
|
31
|
+
args: r,
|
|
32
|
+
_cast: !0
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
callWorker(e, r) {
|
|
36
|
+
var {
|
|
37
|
+
worker: t,
|
|
38
|
+
receiverQueueMap: s,
|
|
39
|
+
options: o
|
|
40
|
+
} = this;
|
|
41
|
+
t.postMessage({
|
|
42
|
+
opName: e,
|
|
43
|
+
args: r
|
|
44
|
+
});
|
|
45
|
+
let i = s[e];
|
|
46
|
+
i = i || (s[e] = new QyQueue(o));
|
|
47
|
+
t = setPromise({});
|
|
48
|
+
return i.push(t), t.promise;
|
|
49
|
+
}
|
|
50
|
+
_startWorker() {
|
|
51
|
+
if (!this.worker) {
|
|
52
|
+
let {
|
|
53
|
+
workerTypeFileName: s,
|
|
54
|
+
initArgMap: e,
|
|
55
|
+
receiverQueueMap: o
|
|
56
|
+
} = this;
|
|
57
|
+
var r = {
|
|
58
|
+
workerTypeFileName: s,
|
|
59
|
+
initArgMap: e
|
|
60
|
+
};
|
|
61
|
+
let i = this.worker = new Worker(path.join(__dirname, "QyMessager_Run.js"), {
|
|
62
|
+
workerData: r
|
|
63
|
+
});
|
|
64
|
+
i.on("error", e => {
|
|
65
|
+
logger.error(`Worker ${s} error:`, e);
|
|
66
|
+
}), i.on("message", e => {
|
|
67
|
+
var {
|
|
68
|
+
opName: r,
|
|
69
|
+
ack: t,
|
|
70
|
+
result: s
|
|
71
|
+
} = e;
|
|
72
|
+
r ? (e = e.args || [], (this.parent || this)[r](...e)) : o[t]?.shift().resolve(s);
|
|
73
|
+
}), i.on("exit", e => {
|
|
74
|
+
for (var r in i.removeAllListeners(), 0 != e ? logger.warn(`Worker ${s} stopped with exitCode ` + e) : logger.info(`Worker ${s} stopped.`),
|
|
75
|
+
o) for (var t = o[r]; !t.isEmpty; ) t.shift()?.resolve();
|
|
76
|
+
this.worker = void 0;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
Object.assign(module.exports, {
|
|
83
|
+
QyMessager: QyMessager
|
|
84
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
let path = require("node:path"), {
|
|
2
|
+
getEnvironmentData,
|
|
3
|
+
workerData
|
|
4
|
+
} = require("node:worker_threads"), logger = require("./QyLogger.js").logger;
|
|
5
|
+
|
|
6
|
+
(async () => {
|
|
7
|
+
logger.level = getEnvironmentData("logLevel");
|
|
8
|
+
var {
|
|
9
|
+
workerTypeFileName: e,
|
|
10
|
+
initArgMap: r
|
|
11
|
+
} = workerData;
|
|
12
|
+
new (require(path.join(__dirname, e)))(r);
|
|
13
|
+
})();
|
package/src/QyMod.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
let Module = require("node:module"), logger = require("./QyLogger.js").logger;
|
|
2
|
+
|
|
3
|
+
function requireFromModCode(o, r, d, e) {
|
|
4
|
+
if (d) try {
|
|
5
|
+
var l = o + "_" + r, i = `_${l}_qydb`, u = (globalThis[i] = e, new Module(r));
|
|
6
|
+
return u._compile(`(function(qyDB){${d}})(${i});`, l + ".js"), delete globalThis[i],
|
|
7
|
+
u.exports;
|
|
8
|
+
} catch (e) {
|
|
9
|
+
logger.error("requireFromModCode failed:", o, r, d, e);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
Object.assign(module.exports, {
|
|
14
|
+
requireFromModCode: requireFromModCode
|
|
15
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
let EventEmitter = require("node:events"), setPromise = require("./QyUtils.js").setPromise, logger = require("./QyLogger.js").logger, getDefaultOptions = require("./QyDefaultOptions.js").getDefaultOptions, QyQueue = require("./QyQueue.js").QyQueue;
|
|
2
|
+
|
|
3
|
+
class QyOpRunner extends EventEmitter {
|
|
4
|
+
constructor(e, s = [], t = []) {
|
|
5
|
+
super(), e = {
|
|
6
|
+
...getDefaultOptions("QyOpRunner"),
|
|
7
|
+
...e
|
|
8
|
+
}, Object.assign(this, {
|
|
9
|
+
options: e,
|
|
10
|
+
running: !1,
|
|
11
|
+
opQueue: new QyQueue(e)
|
|
12
|
+
}), this._setupOpNames(s, !0), this._setupOpNames(t);
|
|
13
|
+
}
|
|
14
|
+
_setupOpNames(e, i) {
|
|
15
|
+
for (let t of e) {
|
|
16
|
+
let s = "_op_" + t;
|
|
17
|
+
this[t] || (this[t] = i ? (...e) => this.pushAndRunWithPromise({
|
|
18
|
+
opName: t,
|
|
19
|
+
opFunName: s,
|
|
20
|
+
args: e
|
|
21
|
+
}) : (...e) => this.pushAndRun({
|
|
22
|
+
opName: t,
|
|
23
|
+
opFunName: s,
|
|
24
|
+
args: e
|
|
25
|
+
})), this[s] || (this[s] = () => logger.error(`Class method ${s} not implemented.`));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
get firstOp() {
|
|
29
|
+
return this.opQueue.first;
|
|
30
|
+
}
|
|
31
|
+
get lastOp() {
|
|
32
|
+
return this.opQueue.last;
|
|
33
|
+
}
|
|
34
|
+
finish() {
|
|
35
|
+
return this.lastOp?.promise || this.runningOp?.promise;
|
|
36
|
+
}
|
|
37
|
+
pushAndRunWithPromise(e) {
|
|
38
|
+
return setPromise(e), this.pushAndRun(e), e.promise;
|
|
39
|
+
}
|
|
40
|
+
pushAndRun(...e) {
|
|
41
|
+
var s = this.opQueue, t = this.lastOp;
|
|
42
|
+
"_op_stop" === t?.opFunName ? (s.pop(), s.push(...e, t)) : s.push(...e),
|
|
43
|
+
this.run();
|
|
44
|
+
}
|
|
45
|
+
async run() {
|
|
46
|
+
if (!this.running) {
|
|
47
|
+
this.running = !0;
|
|
48
|
+
for (var e = this.opQueue; !e.isEmpty; ) {
|
|
49
|
+
var s = e.shift(), {
|
|
50
|
+
opFunName: t,
|
|
51
|
+
eventName: i,
|
|
52
|
+
resolve: n,
|
|
53
|
+
args: r
|
|
54
|
+
} = s;
|
|
55
|
+
if (t) {
|
|
56
|
+
this.runningOp = s;
|
|
57
|
+
try {
|
|
58
|
+
var u = await (r ? this[t](...r) : this[t]());
|
|
59
|
+
n && n(u), i && this.emit(i, u);
|
|
60
|
+
} catch (e) {
|
|
61
|
+
logger.error(`Run ${t} failed:`, e), i && this.emit(i, e);
|
|
62
|
+
}
|
|
63
|
+
this.runningOp = void 0;
|
|
64
|
+
} else n && n(), i && this.emit(i);
|
|
65
|
+
}
|
|
66
|
+
this.running = !1;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
Object.assign(module.exports, {
|
|
72
|
+
QyOpRunner: QyOpRunner
|
|
73
|
+
});
|
package/src/QyQueue.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
let arrayLast = require("./QyUtils.js").arrayLast, getDefaultOptions = require("./QyDefaultOptions.js").getDefaultOptions, logger = require("./QyLogger.js").logger;
|
|
2
|
+
|
|
3
|
+
class QyQueue {
|
|
4
|
+
constructor(e) {
|
|
5
|
+
e = {
|
|
6
|
+
...getDefaultOptions("QyQueue"),
|
|
7
|
+
...e
|
|
8
|
+
}, Object.assign(this, {
|
|
9
|
+
options: e,
|
|
10
|
+
queue: [],
|
|
11
|
+
firstIdx: 0,
|
|
12
|
+
_waterMark: 0
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
get first() {
|
|
16
|
+
return this.queue[this.firstIdx];
|
|
17
|
+
}
|
|
18
|
+
get last() {
|
|
19
|
+
return this.isEmpty ? void 0 : arrayLast(this.queue);
|
|
20
|
+
}
|
|
21
|
+
get isEmpty() {
|
|
22
|
+
return this.firstIdx >= this.queue.length;
|
|
23
|
+
}
|
|
24
|
+
get waterMark() {
|
|
25
|
+
return this._waterMark;
|
|
26
|
+
}
|
|
27
|
+
pop() {
|
|
28
|
+
return this.queue.pop();
|
|
29
|
+
}
|
|
30
|
+
reset() {
|
|
31
|
+
this.firstIdx = 0, this.queue.length = 0;
|
|
32
|
+
}
|
|
33
|
+
push(...e) {
|
|
34
|
+
this.queue.push(...e);
|
|
35
|
+
e = this.queue.length;
|
|
36
|
+
e > this._waterMark && (this._waterMark = e);
|
|
37
|
+
}
|
|
38
|
+
shift() {
|
|
39
|
+
var e;
|
|
40
|
+
if (!this.isEmpty) return e = this.first, this._advanceIdx(), e;
|
|
41
|
+
}
|
|
42
|
+
_advanceIdx() {
|
|
43
|
+
var {
|
|
44
|
+
queue: t,
|
|
45
|
+
firstIdx: e,
|
|
46
|
+
options: s
|
|
47
|
+
} = this, r = t.length, i = e + 1;
|
|
48
|
+
if (r <= i) this.reset(); else {
|
|
49
|
+
var u = r - i;
|
|
50
|
+
if (i > s.maxLenBeforeRecycle || u <= i) {
|
|
51
|
+
for (let e = 0; e < u; ++e) t[e] = t[e + i];
|
|
52
|
+
this.firstIdx = 0, t.length = u;
|
|
53
|
+
} else this.firstIdx = i, t[e] = void 0;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
Object.assign(module.exports, {
|
|
59
|
+
QyQueue: QyQueue
|
|
60
|
+
});
|
package/src/QySaver.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
let fsPromises = require("node:fs/promises"), path = require("node:path"), logger = require("./QyLogger.js").logger, qyUtils = require("./QyUtils.js"), getDefaultOptions = require("./QyDefaultOptions.js").getDefaultOptions;
|
|
2
|
+
|
|
3
|
+
class QySaver {
|
|
4
|
+
constructor(e, r) {
|
|
5
|
+
Object.assign(this, {
|
|
6
|
+
dataFolder: e,
|
|
7
|
+
options: {
|
|
8
|
+
...getDefaultOptions("QySaver"),
|
|
9
|
+
...r
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
setDataFolder(e) {
|
|
14
|
+
return this.dataFolder = e, this;
|
|
15
|
+
}
|
|
16
|
+
processAfterLoad(e) {
|
|
17
|
+
return e;
|
|
18
|
+
}
|
|
19
|
+
processBeforeSave(e) {
|
|
20
|
+
return qyUtils.toBuffer(e);
|
|
21
|
+
}
|
|
22
|
+
async loadFromFile(e, r) {
|
|
23
|
+
var t = path.join(this.dataFolder, e);
|
|
24
|
+
if (null != r && !await qyUtils.folderOrFileExists(t)) return r;
|
|
25
|
+
try {
|
|
26
|
+
var a = await fsPromises.readFile(t);
|
|
27
|
+
return logger.info(`Loading "${t}" succeeded. Total size:${qyUtils.getSizeStr(a.length)}.`),
|
|
28
|
+
this.processAfterLoad(a, e);
|
|
29
|
+
} catch (e) {
|
|
30
|
+
if (null != r) return r;
|
|
31
|
+
logger.error(`Loading "${t}" failed:`, e);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async saveToFile(e, t, r = !1) {
|
|
35
|
+
var {
|
|
36
|
+
dataFolder: a,
|
|
37
|
+
options: i
|
|
38
|
+
} = this, s = path.join(a, t);
|
|
39
|
+
if (!r && await qyUtils.folderOrFileExists(s)) logger.error(s + " already exists."); else {
|
|
40
|
+
var {
|
|
41
|
+
retryTimes: o,
|
|
42
|
+
retryIntervalFactor: l,
|
|
43
|
+
maxRetryInterval: n
|
|
44
|
+
} = i, g = path.join(a, ".tmp", t), d = this.processBeforeSave(e, t);
|
|
45
|
+
let r;
|
|
46
|
+
for (let e = 0; e < o; ++e) {
|
|
47
|
+
if (await this._saveTmpFileAndRename(d, g, s)) return !0;
|
|
48
|
+
r = r ? Math.min(n, r * l) : 1, logger.warn(`Retrying to create ${s} in ${r} seconds.`),
|
|
49
|
+
await qyUtils.sleep(r);
|
|
50
|
+
}
|
|
51
|
+
logger.error(`Failed to create ${t} after retrying ${o} times.`);
|
|
52
|
+
}
|
|
53
|
+
return !1;
|
|
54
|
+
}
|
|
55
|
+
async _saveTmpFileAndRename(e, r, t) {
|
|
56
|
+
var a = e.length;
|
|
57
|
+
if (await this._saveContent(r, e) != a) logger.error(`Creating ${t} failed when trying to create ${r} first.`); else try {
|
|
58
|
+
if (await fsPromises.rename(r, t), await qyUtils.getSize(t) === a) return logger.info(`Renaming ${r} to ${t} succeeded.`),
|
|
59
|
+
!0;
|
|
60
|
+
logger.error(t + " size is not correct.");
|
|
61
|
+
} catch (e) {
|
|
62
|
+
logger.error(`Renaming ${r} to ${t} failed:`, e);
|
|
63
|
+
}
|
|
64
|
+
return !1;
|
|
65
|
+
}
|
|
66
|
+
async _saveContent(r, e) {
|
|
67
|
+
var t = e.length;
|
|
68
|
+
try {
|
|
69
|
+
await qyUtils.ensureParentDir(r), await fsPromises.writeFile(r, e, {
|
|
70
|
+
flush: !0
|
|
71
|
+
});
|
|
72
|
+
var a = `Saving ${r} size ` + qyUtils.getSizeStr(t), i = await qyUtils.getSize(r);
|
|
73
|
+
return i === t ? logger.info(a + " succeeded.") : logger.warn(a + " failed."),
|
|
74
|
+
i;
|
|
75
|
+
} catch (e) {
|
|
76
|
+
return logger.error(`Saving "${r}" failed:`, e), !1;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
Object.assign(module.exports, {
|
|
82
|
+
QySaver: QySaver
|
|
83
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
let QyMessager = require("./QyMessager.js").QyMessager, getDefaultOptions = require("./QyDefaultOptions.js").getDefaultOptions;
|
|
2
|
+
|
|
3
|
+
class QySnapshotCompactor extends QyMessager {
|
|
4
|
+
constructor(s, o, t) {
|
|
5
|
+
super(s, "QySnapshotCompactor_Worker.js", {
|
|
6
|
+
kvFolder: o,
|
|
7
|
+
options: t = {
|
|
8
|
+
...getDefaultOptions("QySnapshotCompactor"),
|
|
9
|
+
...t
|
|
10
|
+
}
|
|
11
|
+
}, t, [], [ "compactSnapshots", "saveSnapshotInfos" ]);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
Object.assign(module.exports, {
|
|
16
|
+
QySnapshotCompactor: QySnapshotCompactor
|
|
17
|
+
});
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
let path = require("node:path"), fsPromises = require("node:fs/promises"), getDefaultOptions = require("./QyDefaultOptions.js").getDefaultOptions, QyMessageWorker = require("./QyMessageWorker.js").QyMessageWorker, QyKVDataCleaner = require("./QyKVDataCleaner.js").QyKVDataCleaner, QySnapshots = require("./QySnapshots.js").QySnapshots, {
|
|
2
|
+
isEmptyObj,
|
|
3
|
+
listToMap,
|
|
4
|
+
readBufferAsync
|
|
5
|
+
} = require("./QyUtils.js");
|
|
6
|
+
|
|
7
|
+
class QySnapshotCompactor_Worker extends QyMessageWorker {
|
|
8
|
+
constructor({
|
|
9
|
+
kvFolder: a,
|
|
10
|
+
options: s
|
|
11
|
+
}) {
|
|
12
|
+
super(s = {
|
|
13
|
+
...getDefaultOptions("QySnapshotCompactor_Worker"),
|
|
14
|
+
...s
|
|
15
|
+
}, [], [ "compactSnapshots", "saveSnapshotInfos" ]);
|
|
16
|
+
var e = path.join(a, "snapshot");
|
|
17
|
+
Object.assign(this, {
|
|
18
|
+
kvFolder: a,
|
|
19
|
+
snapshotFolder: e,
|
|
20
|
+
qySnapshots: new QySnapshots(e, s),
|
|
21
|
+
qyKVDataCleaner: new QyKVDataCleaner(this, a, s),
|
|
22
|
+
pMInfoMap: {},
|
|
23
|
+
vLInfoMap: {}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
start() {
|
|
27
|
+
this.qyKVDataCleaner.start();
|
|
28
|
+
}
|
|
29
|
+
async stop() {
|
|
30
|
+
await this.qyKVDataCleaner.stop();
|
|
31
|
+
}
|
|
32
|
+
async _op_compactSnapshots(a, e, s) {
|
|
33
|
+
var o = {}, t = [];
|
|
34
|
+
if (0 < a.length) {
|
|
35
|
+
let s = o.pMUpdates = {};
|
|
36
|
+
t.push(...a.map(a => this._compactPosMap(a, s)));
|
|
37
|
+
}
|
|
38
|
+
if (0 < e.length) {
|
|
39
|
+
let s = o.vLUpdates = {};
|
|
40
|
+
t.push(...e.map(a => this._compactValueList(a, s)));
|
|
41
|
+
}
|
|
42
|
+
0 < s.length && t.push(this._combinePMLoadedSnapshots(s, o)), await Promise.all(t),
|
|
43
|
+
this.castParent("onCompactUpdates", o);
|
|
44
|
+
}
|
|
45
|
+
async _op_saveSnapshotInfos(a) {
|
|
46
|
+
var s, e, {
|
|
47
|
+
qySnapshots: o,
|
|
48
|
+
pMInfoMap: t,
|
|
49
|
+
vLInfoMap: p,
|
|
50
|
+
qyKVDataCleaner: n
|
|
51
|
+
} = this, i = (Object.assign(this, {
|
|
52
|
+
pMInfoMap: {},
|
|
53
|
+
vLInfoMap: {}
|
|
54
|
+
}), listToMap(a)), r = [];
|
|
55
|
+
for (s in t) s in i && r.push(o.saveSnapshotInfo(s, t[s]));
|
|
56
|
+
for (e in p) e in i && r.push(o.saveSnapshotInfo(e, p[e]));
|
|
57
|
+
if (0 < r.length) {
|
|
58
|
+
await Promise.all(r);
|
|
59
|
+
var h, l, M = [];
|
|
60
|
+
for (h in t) {
|
|
61
|
+
var f = t[h];
|
|
62
|
+
M.push([ h, f.pMVersion ]);
|
|
63
|
+
}
|
|
64
|
+
for (l in p) {
|
|
65
|
+
var y = p[l];
|
|
66
|
+
M.push([ l, y.pMVersion ]), n.cleanVLFiles(l, y.vLVersion);
|
|
67
|
+
}
|
|
68
|
+
n.cleanPMFiles(M);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async _combinePMLoadedSnapshots(a, s) {
|
|
72
|
+
var e, {
|
|
73
|
+
qySnapshots: o,
|
|
74
|
+
vLInfoMap: t
|
|
75
|
+
} = this, p = o.getMaxCombinedSnapshot(a), {
|
|
76
|
+
snapshotNum: n,
|
|
77
|
+
info: i,
|
|
78
|
+
keyValueMap: r
|
|
79
|
+
} = (await this._loadKVMap(p), p), h = (Object.assign(p, {
|
|
80
|
+
posMap: void 0,
|
|
81
|
+
prefixPM: void 0
|
|
82
|
+
}), []);
|
|
83
|
+
for (e of a) e != p && (h.push(e.snapshotNum), await this._loadKVMap(e),
|
|
84
|
+
Object.assign(r, e.keyValueMap), Object.assign(e, {
|
|
85
|
+
keyValueMap: void 0,
|
|
86
|
+
posMap: void 0,
|
|
87
|
+
prefixPM: void 0
|
|
88
|
+
}));
|
|
89
|
+
await o.saveKeyValueMap(p), t[n] = i, s.combineUpdate = {
|
|
90
|
+
snapshotNum: n,
|
|
91
|
+
combinedSnapshotNumList: h,
|
|
92
|
+
posMap: p.posMap
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
async _compactValueList(a, s) {
|
|
96
|
+
var e, o, {
|
|
97
|
+
qySnapshots: t,
|
|
98
|
+
vLInfoMap: p
|
|
99
|
+
} = this;
|
|
100
|
+
await this._loadPosMap(a) && (await this._loadKVMap(a), await t.saveKeyValueMap(a),
|
|
101
|
+
{
|
|
102
|
+
snapshotNum: t,
|
|
103
|
+
info: a,
|
|
104
|
+
posMap: e,
|
|
105
|
+
prefixPM: o
|
|
106
|
+
} = a, p[t] = a, s[t] = {
|
|
107
|
+
posMap: e,
|
|
108
|
+
prefixPM: o
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
async _compactPosMap(a, s) {
|
|
112
|
+
var {
|
|
113
|
+
qySnapshots: e,
|
|
114
|
+
pMInfoMap: o
|
|
115
|
+
} = this, {
|
|
116
|
+
snapshotNum: t,
|
|
117
|
+
info: p,
|
|
118
|
+
prefixPM: n
|
|
119
|
+
} = a;
|
|
120
|
+
(null == n || isEmptyObj(n) || await this._loadPosMap(a)) && (await e.savePosMap(a),
|
|
121
|
+
o[t] = p, s[t] = a.prefixPM);
|
|
122
|
+
}
|
|
123
|
+
async _loadPosMap(a) {
|
|
124
|
+
var s = this.qySnapshots;
|
|
125
|
+
let {
|
|
126
|
+
prefixPM: e,
|
|
127
|
+
posMap: o
|
|
128
|
+
} = a;
|
|
129
|
+
var t, p = s.getPMFilePath(a), n = await fsPromises.open(p);
|
|
130
|
+
for (t of Object.keys(e).sort()) {
|
|
131
|
+
var [ i, r ] = e[t], i = await readBufferAsync(p, n, i, r);
|
|
132
|
+
if (!i) return void n.close();
|
|
133
|
+
s.iterPMBuffer(i, (a, s) => o[a] = s);
|
|
134
|
+
}
|
|
135
|
+
return n.close(), !0;
|
|
136
|
+
}
|
|
137
|
+
async _loadKVMap(a) {
|
|
138
|
+
var s, e = this.qySnapshots, o = a.posMap, t = a.keyValueMap = {}, p = e.getVLFilePath(a), n = await fsPromises.open(p);
|
|
139
|
+
for (s of Object.keys(o).sort()) {
|
|
140
|
+
var [ i, r ] = o[s];
|
|
141
|
+
if (0 < r) {
|
|
142
|
+
i = await readBufferAsync(p, n, i, r);
|
|
143
|
+
if (!i) return void n.close();
|
|
144
|
+
t[s] = i;
|
|
145
|
+
} else t[s] = void 0;
|
|
146
|
+
}
|
|
147
|
+
return n.close(), !0;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
module.exports = QySnapshotCompactor_Worker;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
let QyMessager = require("./QyMessager.js").QyMessager, getDefaultOptions = require("./QyDefaultOptions.js").getDefaultOptions;
|
|
2
|
+
|
|
3
|
+
class QySnapshotSaver extends QyMessager {
|
|
4
|
+
constructor(e, s, a) {
|
|
5
|
+
super(e, "QySnapshotSaver_Worker.js", {
|
|
6
|
+
kvFolder: s,
|
|
7
|
+
options: a = {
|
|
8
|
+
...getDefaultOptions("QySnapshotSaver"),
|
|
9
|
+
...a
|
|
10
|
+
}
|
|
11
|
+
}, a, [], [ "saveSnapshot", "castSave", "releaseSnapshot" ]);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
Object.assign(module.exports, {
|
|
16
|
+
QySnapshotSaver: QySnapshotSaver
|
|
17
|
+
});
|