querysub 0.430.0 → 0.432.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/.cursor/rules/css.mdc +58 -0
- package/.cursor/rules/general.mdc +35 -0
- package/.cursor/rules/react.mdc +27 -0
- package/package.json +2 -2
- package/src/-f-node-discovery/NodeDiscovery.ts +1 -2
- package/src/-h-path-value-serialize/PathValueSerializer.ts +1056 -865
- package/src/0-path-value-core/pathValueArchives.ts +7 -1
- package/src/0-path-value-core/pathValueCore.ts +1 -1
- package/src/2-proxy/PathValueProxyWatcher.ts +4 -0
- package/src/2-proxy/schema2.ts +1 -1
- package/src/4-querysub/Querysub.ts +3 -2
- package/test.ts +9 -6
- package/src/misc/PromiseRace.ts +0 -101
|
@@ -128,7 +128,13 @@ export class PathValueArchives {
|
|
|
128
128
|
values = await this.filterForDiskStorage(values);
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
let buffers = await pathValueSerializer.serialize(values, {
|
|
131
|
+
let buffers = await pathValueSerializer.serialize(values, {
|
|
132
|
+
noLocks: true,
|
|
133
|
+
compress: getCompressNetwork(),
|
|
134
|
+
singleBuffer: true,
|
|
135
|
+
// NOTE: The system natively handles the concept of knowing not to do a commit if it doesn't have any value. The only reason transactions are required is we might have a value, but it might not be the latest value. However, if we're writing to the disk, we're not going to have an even older value. Anything we write to the disk is going to be the oldest value that we'll receive.
|
|
136
|
+
noTransactionPaths: true
|
|
137
|
+
});
|
|
132
138
|
let data = buffers[0];
|
|
133
139
|
|
|
134
140
|
let minTime = values[0].time.time;
|
|
@@ -14,7 +14,7 @@ import { pathValueSerializer } from "../-h-path-value-serialize/PathValueSeriali
|
|
|
14
14
|
import { AuthoritySpec, PathRouter } from "./PathRouter";
|
|
15
15
|
import { formatTime } from "socket-function/src/formatting/format";
|
|
16
16
|
import { isOwnNodeId } from "../-f-node-discovery/NodeDiscovery";
|
|
17
|
-
import { PromiseRace } from "
|
|
17
|
+
import { PromiseRace } from "socket-function/src/PromiseRace";
|
|
18
18
|
|
|
19
19
|
import yargs from "yargs";
|
|
20
20
|
import { PromiseObj } from "../promise";
|
|
@@ -554,6 +554,7 @@ export class PathValueProxyWatcher {
|
|
|
554
554
|
public getCallbackPathValue = (pathStr: string, syncParentKeys?: "parentKeys"): PathValue | undefined => {
|
|
555
555
|
const watcher = this.runningWatcher;
|
|
556
556
|
if (!watcher) {
|
|
557
|
+
debugger;
|
|
557
558
|
throw new Error(`Tried to get path "${pathStr}" outside of a watcher function.`);
|
|
558
559
|
}
|
|
559
560
|
|
|
@@ -652,6 +653,7 @@ export class PathValueProxyWatcher {
|
|
|
652
653
|
}
|
|
653
654
|
const watcher = this.runningWatcher;
|
|
654
655
|
if (!watcher) {
|
|
656
|
+
debugger;
|
|
655
657
|
throw new Error(`Tried to get path "${pathStr}" outside of a watcher function.`);
|
|
656
658
|
}
|
|
657
659
|
|
|
@@ -762,6 +764,7 @@ export class PathValueProxyWatcher {
|
|
|
762
764
|
if (lastPart.startsWith("__") || lastPart === "type") {
|
|
763
765
|
return;
|
|
764
766
|
}
|
|
767
|
+
debugger;
|
|
765
768
|
throw new Error(`Tried to set path "${pathStr}" outside of a watcher function.`);
|
|
766
769
|
}
|
|
767
770
|
if (!watcher.options.canWrite) {
|
|
@@ -899,6 +902,7 @@ export class PathValueProxyWatcher {
|
|
|
899
902
|
|
|
900
903
|
const watcher = this.runningWatcher;
|
|
901
904
|
if (!watcher) {
|
|
905
|
+
debugger;
|
|
902
906
|
throw new Error(`Tried to getKeys on path "${pathStr}" outside of a watcher function.`);
|
|
903
907
|
}
|
|
904
908
|
|
package/src/2-proxy/schema2.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
import "../inject";
|
|
5
5
|
|
|
6
6
|
// Shim Promise.race, as no one wants their promises to leak...
|
|
7
|
-
import {
|
|
8
|
-
Promise.race =
|
|
7
|
+
import { PromiseRace } from "socket-function/src/promiseRace";
|
|
8
|
+
Promise.race = PromiseRace;
|
|
9
9
|
|
|
10
10
|
import { shimDateNow } from "socket-function/time/trueTimeShim";
|
|
11
11
|
shimDateNow();
|
|
@@ -378,6 +378,7 @@ export class Querysub {
|
|
|
378
378
|
public static fastReadAsync<T>(fnc: () => T, options?: Partial<WatcherOptions<T>>) {
|
|
379
379
|
return Querysub.serviceWrite(fnc, { ...options, allowProxyResults: true, noWaitForCommit: true });
|
|
380
380
|
}
|
|
381
|
+
public static readLocal = Querysub.localRead;
|
|
381
382
|
public static localRead<T>(fnc: () => T, options?: Partial<WatcherOptions<T>>) {
|
|
382
383
|
return proxyWatcher.runOnce({
|
|
383
384
|
watchFunction: fnc,
|
package/test.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { getControllerNodeIdList } from "./src/-g-core-values/NodeCapabilities";
|
|
|
7
7
|
import { delay } from "socket-function/src/batching";
|
|
8
8
|
import { green, yellow } from "socket-function/src/formatting/logColors";
|
|
9
9
|
import { Querysub, t } from "./src/4-querysub/Querysub";
|
|
10
|
-
import { pathValueArchives } from "./src/0-path-value-core/pathValueArchives";
|
|
10
|
+
import { archives, pathValueArchives } from "./src/0-path-value-core/pathValueArchives";
|
|
11
11
|
import { getAllAuthoritySpec } from "./src/0-path-value-core/PathRouterServerAuthoritySpec";
|
|
12
12
|
import { deploySchema } from "./src/4-deploy/deploySchema";
|
|
13
13
|
import { getDomain } from "./src/config";
|
|
@@ -17,6 +17,8 @@ import { RemoteWatcher } from "./src/1-path-client/RemoteWatcher";
|
|
|
17
17
|
import { PathRouter } from "./src/0-path-value-core/PathRouter";
|
|
18
18
|
import { shutdown } from "./src/diagnostics/periodic";
|
|
19
19
|
import { getShardPrefixes } from "./src/0-path-value-core/ShardPrefixes";
|
|
20
|
+
import { PathValue, epochTime } from "./src/0-path-value-core/pathValueCore";
|
|
21
|
+
import { pathValueSerializer } from "./src/-h-path-value-serialize/PathValueSerializer";
|
|
20
22
|
|
|
21
23
|
let tempTestSchema = Querysub.createSchema({
|
|
22
24
|
value: t.number,
|
|
@@ -28,13 +30,14 @@ let tempTestSchema = Querysub.createSchema({
|
|
|
28
30
|
});
|
|
29
31
|
|
|
30
32
|
async function main() {
|
|
31
|
-
|
|
32
|
-
let prefixes = await getShardPrefixes();
|
|
33
|
-
for (let prefix of prefixes) {
|
|
34
|
-
console.log(prefix);
|
|
35
|
-
}
|
|
36
33
|
// await Querysub.hostService("test");
|
|
37
34
|
|
|
35
|
+
// let testValues: PathValue[] = [];
|
|
36
|
+
// let buffers = await pathValueSerializer.serialize(testValues);
|
|
37
|
+
// let values = await pathValueSerializer.deserialize(buffers);
|
|
38
|
+
|
|
39
|
+
let values = await pathValueArchives.loadValues(await getAllAuthoritySpec());
|
|
40
|
+
|
|
38
41
|
// let path = getProxyPath(() => tempTestSchema.data().value);
|
|
39
42
|
// console.log({ path });
|
|
40
43
|
// let authorities = PathRouter.getAllAuthorities(path);
|
package/src/misc/PromiseRace.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/** Fixed Promise.race, which doesn't leak promises values. Promises still leak, but a Promise is < 100 bytes,
|
|
2
|
-
* where as the promise value might be huge.
|
|
3
|
-
*/
|
|
4
|
-
export function PromiseRace<T extends any[]>(promises: { [K in keyof T]: Promise<T[K]> }): Promise<T[number]> {
|
|
5
|
-
return new PromiseLessLeaky((resolve: any, reject: any) => {
|
|
6
|
-
function onFinally() {
|
|
7
|
-
for (let promise of promises) {
|
|
8
|
-
if (promise && typeof promise === "object" && promise instanceof Promise) {
|
|
9
|
-
let callbackObj = promiseCallbacks.get(promise);
|
|
10
|
-
if (!callbackObj) continue;
|
|
11
|
-
remove(callbackObj.onResolve, resolve);
|
|
12
|
-
remove(callbackObj.onReject, reject);
|
|
13
|
-
remove(callbackObj.onFinally, onFinally);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
for (let promise of promises) {
|
|
18
|
-
// NOTE: This "if" statement greatly reduce leaks, although it might
|
|
19
|
-
// reduce speed as well?
|
|
20
|
-
if (promise && typeof promise === "object" && promise instanceof Promise) {
|
|
21
|
-
let callbackObj = promiseCallbacks.get(promise);
|
|
22
|
-
if (!callbackObj) {
|
|
23
|
-
callbackObj = {
|
|
24
|
-
onResolve: [],
|
|
25
|
-
onReject: [],
|
|
26
|
-
onFinally: [],
|
|
27
|
-
};
|
|
28
|
-
promiseCallbacks.set(promise, callbackObj);
|
|
29
|
-
connectPromiseToCallbackObj(promise, callbackObj);
|
|
30
|
-
}
|
|
31
|
-
callbackObj.onResolve.push(resolve);
|
|
32
|
-
callbackObj.onReject.push(reject);
|
|
33
|
-
callbackObj.onFinally.push(onFinally);
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
Promise.resolve(promise).then(resolve, reject);
|
|
38
|
-
}
|
|
39
|
-
}) as any;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Less leaky promise.
|
|
43
|
-
// See https://github.com/nodejs/node/issues/17469
|
|
44
|
-
// See https://bugs.chromium.org/p/v8/issues/detail?id=9858#c9
|
|
45
|
-
// Basically, make resolve/reject weakly reference the Promise, so that
|
|
46
|
-
// resolved promises aren't kept alive. The `resolve` function is still leaked
|
|
47
|
-
// itself, but at least it doesn't leak the underlying data.
|
|
48
|
-
// IMPORTANT! This still leaks! So... maybe don't even use Promise.race?
|
|
49
|
-
class PromiseLessLeaky extends Promise<any> {
|
|
50
|
-
constructor(executor: any) {
|
|
51
|
-
super((resolve, reject) => {
|
|
52
|
-
executor(
|
|
53
|
-
function PromiseLessLeakyResolved(value: any) {
|
|
54
|
-
let callback = resolve;
|
|
55
|
-
resolve = undefined as any;
|
|
56
|
-
reject = undefined as any;
|
|
57
|
-
if (callback) {
|
|
58
|
-
callback(value);
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
function PromiseLessLeakyRejected(value: any) {
|
|
62
|
-
let callback = reject;
|
|
63
|
-
resolve = undefined as any;
|
|
64
|
-
reject = undefined as any;
|
|
65
|
-
if (callback) {
|
|
66
|
-
callback(value);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
);
|
|
70
|
-
executor = undefined;
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
function remove(list: any, value: any) {
|
|
75
|
-
let index = list.indexOf(value);
|
|
76
|
-
if (index >= 0) {
|
|
77
|
-
list.splice(index, 1);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
const promiseCallbacks = new WeakMap();
|
|
81
|
-
|
|
82
|
-
function connectPromiseToCallbackObj(promise: any, callbackObj: any) {
|
|
83
|
-
// NOTE: If the promise stays alive forever... this will leak callbackObj. BUT,
|
|
84
|
-
// it is only called once per promise, ever, so... the leak isn't so bad!
|
|
85
|
-
promise.then(
|
|
86
|
-
(value: any) => {
|
|
87
|
-
for (let fnc of callbackObj.onResolve) {
|
|
88
|
-
try { fnc(value); } finally { }
|
|
89
|
-
}
|
|
90
|
-
},
|
|
91
|
-
(value: any) => {
|
|
92
|
-
for (let fnc of callbackObj.onReject) {
|
|
93
|
-
try { fnc(value); } finally { }
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
).finally(() => {
|
|
97
|
-
for (let fnc of callbackObj.onFinally) {
|
|
98
|
-
try { fnc(); } finally { }
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
}
|