@global-cache/core 0.4.1 → 0.5.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/dist/client/api.d.ts +1 -0
- package/dist/client/api.d.ts.map +1 -1
- package/dist/client/api.js +5 -0
- package/dist/client/api.js.map +1 -1
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +8 -0
- package/dist/client/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/server/getter.d.ts +0 -1
- package/dist/server/getter.d.ts.map +1 -1
- package/dist/server/getter.js +42 -29
- package/dist/server/getter.js.map +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +8 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/routes/delete.d.ts +6 -0
- package/dist/server/routes/delete.d.ts.map +1 -0
- package/dist/server/routes/delete.js +19 -0
- package/dist/server/routes/delete.js.map +1 -0
- package/dist/server/storage/single-instance/memory.d.ts +15 -1
- package/dist/server/storage/single-instance/memory.d.ts.map +1 -1
- package/dist/server/storage/single-instance/memory.js +26 -1
- package/dist/server/storage/single-instance/memory.js.map +1 -1
- package/dist/server/storage/types.d.ts +3 -1
- package/dist/server/storage/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/client/api.ts +7 -0
- package/src/client/index.ts +9 -0
- package/src/index.ts +1 -0
- package/src/server/getter.ts +46 -36
- package/src/server/index.ts +8 -1
- package/src/server/routes/delete.ts +23 -0
- package/src/server/storage/single-instance/memory.ts +27 -1
- package/src/server/storage/types.ts +3 -1
package/dist/client/api.d.ts
CHANGED
|
@@ -17,5 +17,6 @@ export declare class StorageApi {
|
|
|
17
17
|
getStale({ key }: GetStaleParams): Promise<unknown>;
|
|
18
18
|
getStaleList({ prefix }: GetStaleListParams): Promise<unknown[]>;
|
|
19
19
|
clearTestRun(): Promise<void>;
|
|
20
|
+
deleteKey(key: string): Promise<void>;
|
|
20
21
|
}
|
|
21
22
|
//# sourceMappingURL=api.d.ts.map
|
package/dist/client/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/client/api.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAoB,MAAM,4BAA4B,CAAC;AACnF,OAAO,KAAK,EAAE,kBAAkB,EAAwB,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/client/api.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAoB,MAAM,4BAA4B,CAAC;AACnF,OAAO,KAAK,EAAE,kBAAkB,EAAwB,MAAM,iCAAiC,CAAC;AAEhG,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAMpC,qBAAa,UAAU;IACrB,OAAO,CAAC,IAAI,CAAa;gBAEb,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM;IAQlD,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE;IAO9D,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE;IAOzE,QAAQ,CAAC,EAAE,GAAG,EAAE,EAAE,cAAc;IAOhC,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,kBAAkB;IAO3C,YAAY;IAKZ,SAAS,CAAC,GAAG,EAAE,MAAM;CAK5B"}
|
package/dist/client/api.js
CHANGED
|
@@ -41,6 +41,11 @@ class StorageApi {
|
|
|
41
41
|
const res = await this.http.post('clear');
|
|
42
42
|
await (0, http_error_1.throwIfHttpError)(res, 'Failed to clear test run:');
|
|
43
43
|
}
|
|
44
|
+
async deleteKey(key) {
|
|
45
|
+
const body = { key };
|
|
46
|
+
const res = await this.http.post('delete', body);
|
|
47
|
+
await (0, http_error_1.throwIfHttpError)(res, `Failed to delete key "${key}":`);
|
|
48
|
+
}
|
|
44
49
|
}
|
|
45
50
|
exports.StorageApi = StorageApi;
|
|
46
51
|
//# sourceMappingURL=api.js.map
|
package/dist/client/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/client/api.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/client/api.ts"],"names":[],"mappings":"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"}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -27,6 +27,10 @@ export declare class GlobalCacheClient<S extends DefaultKeysSchema = DefaultKeys
|
|
|
27
27
|
* - for persistent keys it would be the old value if it was changed during this run
|
|
28
28
|
*/
|
|
29
29
|
getStaleList<ValueType>(prefix: string): Promise<ValueType[]>;
|
|
30
|
+
/**
|
|
31
|
+
* Delete a cached value by key, forcing re-computation on the next get() call.
|
|
32
|
+
*/
|
|
33
|
+
delete<K extends StringKeys<S>>(key: K): Promise<void>;
|
|
30
34
|
/**
|
|
31
35
|
* Reset current test run:
|
|
32
36
|
* - clear all non-persistent values
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAK3D,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGjE,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAE7B,qBAAa,iBAAiB,CAAC,CAAC,SAAS,iBAAiB,GAAG,iBAAiB;IAI5E,MAAM,CAAC,MAAM,EAAE,iBAAiB;IAIhC;;;;;;OAMG;IACH,OAAO,KAAK,GAAG,GAGd;IAED;;OAEG;IAEG,GAAG,CAAC,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAsDzE;;;;OAIG;IACG,QAAQ,CAAC,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;IAQ9C;;;;OAIG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM;IAQ5C;;;;OAIG;IACG,YAAY;YA8BJ,YAAY;CAS3B"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAK3D,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGjE,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAE7B,qBAAa,iBAAiB,CAAC,CAAC,SAAS,iBAAiB,GAAG,iBAAiB;IAI5E,MAAM,CAAC,MAAM,EAAE,iBAAiB;IAIhC;;;;;;OAMG;IACH,OAAO,KAAK,GAAG,GAGd;IAED;;OAEG;IAEG,GAAG,CAAC,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAsDzE;;;;OAIG;IACG,QAAQ,CAAC,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;IAQ9C;;;;OAIG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM;IAQ5C;;OAEG;IACG,MAAM,CAAC,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;IAM5C;;;;OAIG;IACG,YAAY;YA8BJ,YAAY;CAS3B"}
|
package/dist/client/index.js
CHANGED
|
@@ -95,6 +95,14 @@ class GlobalCacheClient {
|
|
|
95
95
|
(0, debug_1.debugKey)(prefix, `Fetched: ${values.length} value(s)`);
|
|
96
96
|
return values;
|
|
97
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Delete a cached value by key, forcing re-computation on the next get() call.
|
|
100
|
+
*/
|
|
101
|
+
async delete(key) {
|
|
102
|
+
(0, debug_1.debugKey)(key, `Deleting value...`);
|
|
103
|
+
await this.api.deleteKey(key);
|
|
104
|
+
(0, debug_1.debugKey)(key, `Deleted.`);
|
|
105
|
+
}
|
|
98
106
|
/**
|
|
99
107
|
* Reset current test run:
|
|
100
108
|
* - clear all non-persistent values
|
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":";;;AAAA,qCAA2D;AAC3D,2CAAkD;AAClD,6CAA0C;AAC1C,uCAA8C;AAC9C,+BAAmC;AAEnC,yDAAqD;AAIrD,MAAa,iBAAiB;IAC5B;;OAEG;IACH,MAAM,CAAC,MAAyB;QAC9B,qBAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAED;;;;;;OAMG;IACH,IAAY,GAAG;QACb,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,qBAAY,CAAC;QAC1C,OAAO,IAAI,gBAAU,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,6DAA6D;IAC7D,KAAK,CAAC,GAAG,CAA0B,GAAG,IAAmB;QACvD,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QAEjD,IAAI,qBAAY,CAAC,QAAQ,EAAE,CAAC;YAC1B,IAAA,gBAAQ,EAAC,GAAG,EAAE,qCAAqC,CAAC,CAAC;YACrD,OAAO,EAAE,EAAE,CAAC;QACd,CAAC;QAED,MAAM,GAAG,GAAG,qBAAY,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;QAE5D,gEAAgE;QAChE,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;QACzF,MAAM,GAAG,GAAG,IAAA,mBAAa,EAAC,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;QAE9C,IAAA,gBAAQ,EAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;QAEnD,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAChC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC;YACjC,IAAA,gBAAQ,EAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,KAAK,IAAA,4BAAY,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACxD,OAAO,KAAa,CAAC;QACvB,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;YACnC,eAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1B,IAAA,gBAAQ,EAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,gBAAgB,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,IAAA,gBAAQ,EAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,OAAO,iBAAiB,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACrD,IAAA,gBAAQ,EAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,aAAa,IAAA,4BAAY,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAEtF,IAAI,IAAI,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;YACnC,IAAA,gBAAQ,EAAC,GAAG,EAAE,iDAAiD,CAAC,CAAC;YACjE,IAAI,KAAK;gBAAE,MAAM,KAAK,CAAC;YACvB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAA,gBAAQ,EAAC,GAAG,EAAE,oBAAoB,GAAG,IAAI,aAAa,KAAK,CAAC,CAAC;QAC7D,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5D,IAAA,gBAAQ,EAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;QAErC,IAAI,KAAK;YAAE,MAAM,KAAK,CAAC;QAEvB,8EAA8E;QAC9E,gDAAgD;QAChD,OAAO,SAAS,CAAC,KAAa,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,QAAQ,CAA0B,GAAM;QAC5C,IAAA,gBAAQ,EAAC,GAAG,EAAE,yBAAyB,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/C,IAAA,gBAAQ,EAAC,GAAG,EAAE,YAAY,IAAA,4BAAY,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAEjD,OAAO,KAAyB,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,YAAY,CAAY,MAAc;QAC1C,IAAA,gBAAQ,EAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACvD,IAAA,gBAAQ,EAAC,MAAM,EAAE,YAAY,MAAM,CAAC,MAAM,WAAW,CAAC,CAAC;QAEvD,OAAO,MAAqB,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CAA0B,GAAM;QAC1C,IAAA,gBAAQ,EAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;QACnC,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAA,gBAAQ,EAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,YAAY;QAChB,qDAAqD;QACrD,oEAAoE;QACpE,IAAI,CAAC,qBAAY,CAAC,SAAS;YAAE,OAAO;QAEpC,kEAAkE;QAClE,IAAI,qBAAY,CAAC,aAAa;YAAE,OAAO;QAEvC,IAAI,CAAC,qBAAY,CAAC,KAAK,EAAE,CAAC;YACxB,eAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;YACrC,OAAO;QACT,CAAC;QAED,IAAA,aAAK,EAAC,sBAAsB,qBAAY,CAAC,KAAK,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YAC9B,IAAA,aAAK,EAAC,UAAU,CAAC,CAAC;QACpB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,+DAA+D;YAC/D,eAAM,CAAC,IAAI,CAAC,0CAA0C,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QACtE,CAAC;QAED,4BAA4B;QAC5B,8EAA8E;QAC9E,8DAA8D;QAC9D,uDAAuD;QACvD,gFAAgF;QAChF,qBAAY,CAAC,UAAU,EAAE,CAAC;IAC5B,CAAC;IAEO,KAAK,CAAC,YAAY,CAAY,EAAmB;QACvD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,EAAE,EAAE,CAAC;YACzB,OAAO,EAAE,KAAK,EAAE,CAAC;QACnB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,KAAK,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5D,OAAO,EAAE,KAAK,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;CACF;AA7JD,8CA6JC;AAED,SAAS,cAAc,CAAuD,IAAmB;IAC/F,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC;QACtB,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE;QAC3C,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5D,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.globalConfig = exports.GlobalCacheClient = void 0;
|
|
3
|
+
exports.logger = exports.globalConfig = exports.GlobalCacheClient = void 0;
|
|
4
4
|
var index_js_1 = require("./client/index.js");
|
|
5
5
|
Object.defineProperty(exports, "GlobalCacheClient", { enumerable: true, get: function () { return index_js_1.GlobalCacheClient; } });
|
|
6
6
|
var config_js_1 = require("./client/config.js");
|
|
7
7
|
Object.defineProperty(exports, "globalConfig", { enumerable: true, get: function () { return config_js_1.globalConfig; } });
|
|
8
|
+
var logger_js_1 = require("./shared/logger.js");
|
|
9
|
+
Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return logger_js_1.logger; } });
|
|
8
10
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,8CAAyE;AAAhE,6GAAA,iBAAiB,OAAA;AAC1B,gDAAqE;AAA5D,yGAAA,YAAY,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,8CAAyE;AAAhE,6GAAA,iBAAiB,OAAA;AAC1B,gDAAqE;AAA5D,yGAAA,YAAY,OAAA;AACrB,gDAA4C;AAAnC,mGAAA,MAAM,OAAA"}
|
package/dist/server/getter.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getter.d.ts","sourceRoot":"","sources":["../../src/server/getter.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEtE,KAAK,eAAe,GAAG;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AACjE,KAAK,cAAc,GAAG;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAC3E,KAAK,WAAW,GAAG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AACxD,KAAK,uBAAuB,GAAG;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3E,MAAM,MAAM,YAAY,GAAG,eAAe,GAAG,cAAc,GAAG,WAAW,GAAG,uBAAuB,CAAC;AAEpG,qBAAa,MAAM;IAEf,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,iBAAiB;gBADjB,cAAc,EAAE,eAAe,EAC/B,iBAAiB,EAAE,kBAAkB;IAIzC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"getter.d.ts","sourceRoot":"","sources":["../../src/server/getter.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEtE,KAAK,eAAe,GAAG;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AACjE,KAAK,cAAc,GAAG;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAC3E,KAAK,WAAW,GAAG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AACxD,KAAK,uBAAuB,GAAG;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3E,MAAM,MAAM,YAAY,GAAG,eAAe,GAAG,cAAc,GAAG,WAAW,GAAG,uBAAuB,CAAC;AAEpG,qBAAa,MAAM;IAEf,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,iBAAiB;gBADjB,cAAc,EAAE,eAAe,EAC/B,iBAAiB,EAAE,kBAAkB;IAIzC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAwCxE,OAAO,CAAC,uBAAuB;IAO/B,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,WAAW;YAIL,aAAa;YAWb,aAAa;YAwCb,aAAa;YAMb,eAAe;CAI9B"}
|
package/dist/server/getter.js
CHANGED
|
@@ -23,36 +23,26 @@ class Getter {
|
|
|
23
23
|
}
|
|
24
24
|
// wait if computing
|
|
25
25
|
if (valueInfo?.state === 'computing') {
|
|
26
|
-
valueInfo = await this.testRunStorage.
|
|
26
|
+
valueInfo = await this.testRunStorage.waitForComputed(key);
|
|
27
27
|
return valueInfo.state === 'computed'
|
|
28
28
|
? this.handleComputed(valueInfo)
|
|
29
29
|
: this.handleError(valueInfo);
|
|
30
30
|
}
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const signatureMismatch = (0, sig_1.checkSignature)(key, valueInfo.sig, sig);
|
|
36
|
-
// eslint-disable-next-line max-depth
|
|
37
|
-
if (signatureMismatch) {
|
|
38
|
-
return this.handleSignatureChanged(valueInfo, sig, signatureMismatch);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
31
|
+
// no value in memory -- claim the key atomically before touching persistent storage,
|
|
32
|
+
// so concurrent callers for the same key can't all decide to recompute independently
|
|
33
|
+
if (!valueInfo) {
|
|
34
|
+
return this.handleNoValue(key, sig, ttl);
|
|
41
35
|
}
|
|
42
36
|
// check expired
|
|
43
|
-
if (valueInfo
|
|
37
|
+
if (valueInfo.state === 'computed' && valueInfo.persistent && ttl) {
|
|
44
38
|
if ((0, ttl_1.isExpired)(valueInfo.computedAt, ttl)) {
|
|
45
39
|
return this.handleExpired(valueInfo, ttl);
|
|
46
40
|
}
|
|
47
41
|
}
|
|
48
42
|
// normal cache hit
|
|
49
|
-
if (valueInfo
|
|
43
|
+
if (valueInfo.state === 'computed') {
|
|
50
44
|
return this.handleComputed(valueInfo);
|
|
51
45
|
}
|
|
52
|
-
// no value
|
|
53
|
-
if (!valueInfo) {
|
|
54
|
-
return this.handleNoValue(key, sig, ttl);
|
|
55
|
-
}
|
|
56
46
|
return this.handleDefault(valueInfo);
|
|
57
47
|
}
|
|
58
48
|
handleSignatureMismatch(key, signatureMismatch) {
|
|
@@ -64,16 +54,6 @@ class Getter {
|
|
|
64
54
|
handleError(valueInfo) {
|
|
65
55
|
return { result: 'error', message: valueInfo.errorMessage || 'Unknown error' };
|
|
66
56
|
}
|
|
67
|
-
async handleSignatureChanged(loadedValueInfo, newSig, { field }) {
|
|
68
|
-
await this.updateValueInfo(loadedValueInfo, {
|
|
69
|
-
state: 'computing',
|
|
70
|
-
sig: newSig,
|
|
71
|
-
prevValue: loadedValueInfo.value,
|
|
72
|
-
value: undefined,
|
|
73
|
-
computedAt: undefined,
|
|
74
|
-
});
|
|
75
|
-
return { result: 'cache-miss', message: `signature changed: ${field}` };
|
|
76
|
-
}
|
|
77
57
|
async handleExpired(valueInfo, ttl) {
|
|
78
58
|
await this.updateValueInfo(valueInfo, {
|
|
79
59
|
state: 'computing',
|
|
@@ -83,9 +63,42 @@ class Getter {
|
|
|
83
63
|
});
|
|
84
64
|
return { result: 'cache-miss', message: `expired: ${ttl}` };
|
|
85
65
|
}
|
|
66
|
+
// eslint-disable-next-line visual/complexity, max-statements
|
|
86
67
|
async handleNoValue(key, sig, ttl) {
|
|
87
|
-
|
|
88
|
-
|
|
68
|
+
const placeholder = {
|
|
69
|
+
key,
|
|
70
|
+
state: 'computing',
|
|
71
|
+
sig,
|
|
72
|
+
persistent: Boolean(ttl),
|
|
73
|
+
};
|
|
74
|
+
const claimed = this.testRunStorage.claimForComputing(placeholder);
|
|
75
|
+
if (!claimed) {
|
|
76
|
+
const resolved = await this.testRunStorage.waitForComputed(key);
|
|
77
|
+
return resolved.state === 'computed'
|
|
78
|
+
? this.handleComputed(resolved)
|
|
79
|
+
: this.handleError(resolved);
|
|
80
|
+
}
|
|
81
|
+
if (!ttl)
|
|
82
|
+
return { result: 'cache-miss', message: 'no cached value' };
|
|
83
|
+
// We own the 'computing' slot now, so no other concurrent caller can also decide
|
|
84
|
+
// to recompute this key while we consult persistent storage.
|
|
85
|
+
const persisted = await this.persistentStorage.load(key);
|
|
86
|
+
if (!persisted)
|
|
87
|
+
return { result: 'cache-miss', message: 'no cached value' };
|
|
88
|
+
const signatureMismatch = (0, sig_1.checkSignature)(key, persisted.sig, sig);
|
|
89
|
+
if (signatureMismatch) {
|
|
90
|
+
placeholder.prevValue = persisted.value;
|
|
91
|
+
return { result: 'cache-miss', message: `signature changed: ${signatureMismatch.field}` };
|
|
92
|
+
}
|
|
93
|
+
if ((0, ttl_1.isExpired)(persisted.computedAt, ttl)) {
|
|
94
|
+
placeholder.prevValue = persisted.value;
|
|
95
|
+
return { result: 'cache-miss', message: `expired: ${ttl}` };
|
|
96
|
+
}
|
|
97
|
+
// Persistent value is fresh and valid -- adopt it as computed, update the map entry
|
|
98
|
+
// (already resident via claimForComputing) and notify any waiters.
|
|
99
|
+
Object.assign(placeholder, persisted);
|
|
100
|
+
await this.testRunStorage.save(placeholder, { notify: true });
|
|
101
|
+
return this.handleComputed(placeholder);
|
|
89
102
|
}
|
|
90
103
|
async handleDefault(valueInfo) {
|
|
91
104
|
const message = `old state: ${valueInfo.state}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getter.js","sourceRoot":"","sources":["../../src/server/getter.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,uCAAkE;AAClE,uCAA0C;AAW1C,MAAa,MAAM;IACjB,YACU,cAA+B,EAC/B,iBAAqC;QADrC,mBAAc,GAAd,cAAc,CAAiB;QAC/B,sBAAiB,GAAjB,iBAAiB,CAAoB;IAC5C,CAAC;IAEJ,6DAA6D;IAC7D,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,GAAW,EAAE,GAAY;QAC9C,IAAI,SAAS,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpD,+CAA+C;QAC/C,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,iBAAiB,GAAG,IAAA,oBAAc,EAAC,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAClE,IAAI,iBAAiB,EAAE,CAAC;gBACtB,OAAO,IAAI,CAAC,uBAAuB,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,IAAI,SAAS,EAAE,KAAK,KAAK,WAAW,EAAE,CAAC;YACrC,SAAS,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"getter.js","sourceRoot":"","sources":["../../src/server/getter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,uBAAuB,EAA4B,MAAM,UAAU,CAAC;AAG7E,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,MAAM,CAA4B;;IAe1C,IAAI,IAAI,WAGP;IAED,IAAI,QAAQ,WAEX;IAED,IAAI,SAAS,YAEZ;IAEK,KAAK,CAAC,cAAc,CAAC,EAAE,uBAAuB;IAc9C,IAAI;CAUX;AAGD,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
|
package/dist/server/index.js
CHANGED
|
@@ -12,6 +12,7 @@ const set_1 = require("./routes/set");
|
|
|
12
12
|
const get_stale_1 = require("./routes/get-stale");
|
|
13
13
|
const get_stale_list_1 = require("./routes/get-stale-list");
|
|
14
14
|
const clear_1 = require("./routes/clear");
|
|
15
|
+
const delete_1 = require("./routes/delete");
|
|
15
16
|
const error_1 = require("./error");
|
|
16
17
|
const config_1 = require("./config");
|
|
17
18
|
const express_2 = require("./utils/express");
|
|
@@ -19,13 +20,14 @@ class GlobalCacheServer {
|
|
|
19
20
|
constructor() {
|
|
20
21
|
this.app = (0, express_1.default)();
|
|
21
22
|
this.server = null;
|
|
22
|
-
this.app.use(express_1.default.json());
|
|
23
|
+
this.app.use(express_1.default.json({ limit: '10mb' }));
|
|
23
24
|
this.app.use('/', root_1.router);
|
|
24
25
|
this.app.use('/', get_1.router);
|
|
25
26
|
this.app.use('/', set_1.router);
|
|
26
27
|
this.app.use('/', get_stale_1.router);
|
|
27
28
|
this.app.use('/', get_stale_list_1.router);
|
|
28
29
|
this.app.use('/', clear_1.router);
|
|
30
|
+
this.app.use('/', delete_1.router);
|
|
29
31
|
// Must be after all other middleware and routes
|
|
30
32
|
this.app.use(error_1.errorHandler);
|
|
31
33
|
}
|
|
@@ -45,6 +47,11 @@ class GlobalCacheServer {
|
|
|
45
47
|
const config = (0, config_1.resolveConfig)(providedConfig);
|
|
46
48
|
(0, config_1.setConfig)(this.app, config);
|
|
47
49
|
this.server = await (0, express_2.startExpressServer)(this.app, config.port);
|
|
50
|
+
// unref() so the server does not prevent the Node.js process from exiting
|
|
51
|
+
// naturally when all other work is done (e.g. in CLI mode after tests finish).
|
|
52
|
+
// In VSCode / UI mode the process is kept alive by Playwright's own IPC
|
|
53
|
+
// channels, so the server stays up automatically for subsequent runs.
|
|
54
|
+
this.server.unref();
|
|
48
55
|
(0, debug_1.debug)(`Starting server: done ${this.localUrl}`);
|
|
49
56
|
}
|
|
50
57
|
async stop() {
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";;;;;;AASA,sDAA8B;AAC9B,2CAAwC;AACxC,wCAAoD;AACpD,sCAAkD;AAClD,sCAAkD;AAClD,kDAA6D;AAC7D,4DAAsE;AACtE,0CAA6D;AAC7D,mCAAuC;AACvC,qCAA6E;AAC7E,6CAAwE;AAExE,MAAa,iBAAiB;IAI5B;QAHQ,QAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;QAChB,WAAM,GAAuB,IAAI,CAAC;QAGxC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../src/server/routes/delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,MAAM,EAAE,MAAM,SAAS,CAAC;AAI1C,eAAO,MAAM,MAAM,EAAE,UAAU,CAAC,OAAO,MAAM,CAAY,CAAC;AAE1D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,MAAM,CAAC;CACb,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.router = void 0;
|
|
4
|
+
const express_1 = require("express");
|
|
5
|
+
const config_1 = require("../config");
|
|
6
|
+
const storage_1 = require("../storage");
|
|
7
|
+
exports.router = (0, express_1.Router)();
|
|
8
|
+
exports.router.post('/run/:runId/delete', async (req, res) => {
|
|
9
|
+
const { runId } = req.params;
|
|
10
|
+
const { key } = req.body;
|
|
11
|
+
const config = (0, config_1.getConfig)(req.app);
|
|
12
|
+
const { testRunStorage, persistentStorage } = (0, storage_1.getStorage)(config, runId);
|
|
13
|
+
const valueInfo = await testRunStorage.load(key);
|
|
14
|
+
await testRunStorage.delete(key);
|
|
15
|
+
if (valueInfo?.persistent)
|
|
16
|
+
await persistentStorage.delete(key);
|
|
17
|
+
res.end();
|
|
18
|
+
});
|
|
19
|
+
//# sourceMappingURL=delete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete.js","sourceRoot":"","sources":["../../../src/server/routes/delete.ts"],"names":[],"mappings":";;;AAAA,qCAA0C;AAC1C,sCAAsC;AACtC,wCAAwC;AAE3B,QAAA,MAAM,GAA8B,IAAA,gBAAM,GAAE,CAAC;AAM1D,cAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACnD,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;IAC7B,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,IAAyB,CAAC;IAC9C,MAAM,MAAM,GAAG,IAAA,kBAAS,EAAC,GAAG,CAAC,GAAc,CAAC,CAAC;IAE7C,MAAM,EAAE,cAAc,EAAE,iBAAiB,EAAE,GAAG,IAAA,oBAAU,EAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAExE,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,SAAS,EAAE,UAAU;QAAE,MAAM,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAE/D,GAAG,CAAC,GAAG,EAAE,CAAC;AACZ,CAAC,CAAC,CAAC"}
|
|
@@ -8,8 +8,22 @@ export declare class MemoryStorage implements ITestRunStorage {
|
|
|
8
8
|
save(valueInfo: TestRunValueInfo, { notify }?: {
|
|
9
9
|
notify?: boolean | undefined;
|
|
10
10
|
}): Promise<void>;
|
|
11
|
+
delete(key: string): Promise<void>;
|
|
11
12
|
clear(): Promise<void>;
|
|
12
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Atomically claims the key for computing if it is not yet present.
|
|
15
|
+
*
|
|
16
|
+
* Concurrent workers all call `await testRunStorage.load(key)`, which yields the event loop,
|
|
17
|
+
* so all of them can see `undefined` simultaneously. Using async `save()` for the initial
|
|
18
|
+
* write would let every worker return `cache-miss`, compute in parallel, and collide in
|
|
19
|
+
* `setter.set()` — which only accepts a single `'computing'` caller.
|
|
20
|
+
*
|
|
21
|
+
* Because this method has no `await`, Node.js's single-threaded event loop makes
|
|
22
|
+
* `Map.has()` + `Map.set()` atomic. Only the first caller gets `true` (proceeds to compute);
|
|
23
|
+
* all subsequent callers get `false` (and wait).
|
|
24
|
+
*/
|
|
25
|
+
claimForComputing(valueInfo: TestRunValueInfo): boolean;
|
|
26
|
+
waitForComputed(key: string): Promise<TestRunValueInfo>;
|
|
13
27
|
private notify;
|
|
14
28
|
}
|
|
15
29
|
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../../src/server/storage/single-instance/memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAI3C,qBAAa,aAAc,YAAW,eAAe;IACnD,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,SAAS,CAA2C;IAEtD,IAAI,CAAC,GAAG,EAAE,MAAM;IAIhB,YAAY,CAAC,MAAM,EAAE,MAAM;IAI3B,IAAI,CAAC,SAAS,EAAE,gBAAgB,EAAE,EAAE,MAAc,EAAE;;KAAK;IAKzD,KAAK;
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../../src/server/storage/single-instance/memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAI3C,qBAAa,aAAc,YAAW,eAAe;IACnD,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,SAAS,CAA2C;IAEtD,IAAI,CAAC,GAAG,EAAE,MAAM;IAIhB,YAAY,CAAC,MAAM,EAAE,MAAM;IAI3B,IAAI,CAAC,SAAS,EAAE,gBAAgB,EAAE,EAAE,MAAc,EAAE;;KAAK;IAKzD,MAAM,CAAC,GAAG,EAAE,MAAM;IAIlB,KAAK;IAIX;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO;IAMjD,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAY7D,OAAO,CAAC,MAAM;CAQf"}
|
|
@@ -17,10 +17,35 @@ class MemoryStorage {
|
|
|
17
17
|
if (notify)
|
|
18
18
|
this.notify(valueInfo);
|
|
19
19
|
}
|
|
20
|
+
async delete(key) {
|
|
21
|
+
this.values.delete(key);
|
|
22
|
+
}
|
|
20
23
|
async clear() {
|
|
21
24
|
this.values.clear();
|
|
22
25
|
}
|
|
23
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Atomically claims the key for computing if it is not yet present.
|
|
28
|
+
*
|
|
29
|
+
* Concurrent workers all call `await testRunStorage.load(key)`, which yields the event loop,
|
|
30
|
+
* so all of them can see `undefined` simultaneously. Using async `save()` for the initial
|
|
31
|
+
* write would let every worker return `cache-miss`, compute in parallel, and collide in
|
|
32
|
+
* `setter.set()` — which only accepts a single `'computing'` caller.
|
|
33
|
+
*
|
|
34
|
+
* Because this method has no `await`, Node.js's single-threaded event loop makes
|
|
35
|
+
* `Map.has()` + `Map.set()` atomic. Only the first caller gets `true` (proceeds to compute);
|
|
36
|
+
* all subsequent callers get `false` (and wait).
|
|
37
|
+
*/
|
|
38
|
+
claimForComputing(valueInfo) {
|
|
39
|
+
if (this.values.has(valueInfo.key))
|
|
40
|
+
return false;
|
|
41
|
+
this.values.set(valueInfo.key, valueInfo);
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
async waitForComputed(key) {
|
|
45
|
+
// Guard: if notify already fired before we registered, return immediately.
|
|
46
|
+
const existing = this.values.get(key);
|
|
47
|
+
if (existing && existing.state !== 'computing')
|
|
48
|
+
return existing;
|
|
24
49
|
return new Promise((resolve) => {
|
|
25
50
|
const listeners = this.listeners.get(key) || [];
|
|
26
51
|
listeners.push(resolve);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../../src/server/storage/single-instance/memory.ts"],"names":[],"mappings":";;;AAKA,MAAa,aAAa;IAA1B;QACU,WAAM,GAAG,IAAI,GAAG,EAA4B,CAAC;QAC7C,cAAS,GAAG,IAAI,GAAG,EAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../../src/server/storage/single-instance/memory.ts"],"names":[],"mappings":";;;AAKA,MAAa,aAAa;IAA1B;QACU,WAAM,GAAG,IAAI,GAAG,EAA4B,CAAC;QAC7C,cAAS,GAAG,IAAI,GAAG,EAAgC,CAAC;IA6D9D,CAAC;IA3DC,KAAK,CAAC,IAAI,CAAC,GAAW;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAc;QAC/B,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3F,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAA2B,EAAE,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,EAAE;QAC7D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC1C,IAAI,MAAM;YAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IAED;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,SAA2B;QAC3C,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QACjD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,GAAW;QAC/B,2EAA2E;QAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,QAAQ,IAAI,QAAQ,CAAC,KAAK,KAAK,WAAW;YAAE,OAAO,QAAQ,CAAC;QAEhE,OAAO,IAAI,OAAO,CAAmB,CAAC,OAAO,EAAE,EAAE;YAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YAChD,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACxB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,SAA2B;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACpD,IAAI,CAAC;YACH,SAAS,EAAE,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QACtD,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;CACF;AA/DD,sCA+DC"}
|
|
@@ -4,7 +4,9 @@ export type ITestRunStorage = {
|
|
|
4
4
|
save(valueInfo: TestRunValueInfo, options?: {
|
|
5
5
|
notify?: boolean;
|
|
6
6
|
}): Promise<void>;
|
|
7
|
-
|
|
7
|
+
delete(key: string): Promise<void>;
|
|
8
|
+
waitForComputed(key: string): Promise<TestRunValueInfo>;
|
|
9
|
+
claimForComputing(valueInfo: TestRunValueInfo): boolean;
|
|
8
10
|
};
|
|
9
11
|
export type IPersistentStorage = {
|
|
10
12
|
load(key: string): Promise<TestRunValueInfo | undefined>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/server/storage/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;IACzD,IAAI,CAAC,SAAS,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjF,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/server/storage/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;IACzD,IAAI,CAAC,SAAS,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACxD,iBAAiB,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAAC;CACzD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;IACzD,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@global-cache/core",
|
|
3
3
|
"description": "Key-value cache for sharing data between parallel workers.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.1",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"README.md"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@types/debug": "^4.1.
|
|
33
|
+
"@types/debug": "^4.1.13",
|
|
34
34
|
"@types/express": "^5.0.6",
|
|
35
35
|
"@types/ms": "^2.1.0",
|
|
36
36
|
"debug": "^4.4.3",
|
package/src/client/api.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { GetValueParams, GetValueResponse } from '../server/routes/get';
|
|
|
2
2
|
import type { SetValueParams, SetValueResponse } from '../server/routes/set';
|
|
3
3
|
import type { GetStaleParams, SetStaleResponse } from '../server/routes/get-stale';
|
|
4
4
|
import type { GetStaleListParams, SetStaleListResponse } from '../server/routes/get-stale-list';
|
|
5
|
+
import type { DeleteValueParams } from '../server/routes/delete';
|
|
5
6
|
import { TTL } from '../shared/ttl';
|
|
6
7
|
import { HttpClient } from './utils/http-client';
|
|
7
8
|
import { prepareQueryParams } from './utils/http-query';
|
|
@@ -51,4 +52,10 @@ export class StorageApi {
|
|
|
51
52
|
const res = await this.http.post('clear');
|
|
52
53
|
await throwIfHttpError(res, 'Failed to clear test run:');
|
|
53
54
|
}
|
|
55
|
+
|
|
56
|
+
async deleteKey(key: string) {
|
|
57
|
+
const body: DeleteValueParams = { key };
|
|
58
|
+
const res = await this.http.post('delete', body);
|
|
59
|
+
await throwIfHttpError(res, `Failed to delete key "${key}":`);
|
|
60
|
+
}
|
|
54
61
|
}
|
package/src/client/index.ts
CHANGED
|
@@ -112,6 +112,15 @@ export class GlobalCacheClient<S extends DefaultKeysSchema = DefaultKeysSchema>
|
|
|
112
112
|
return values as ValueType[];
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Delete a cached value by key, forcing re-computation on the next get() call.
|
|
117
|
+
*/
|
|
118
|
+
async delete<K extends StringKeys<S>>(key: K) {
|
|
119
|
+
debugKey(key, `Deleting value...`);
|
|
120
|
+
await this.api.deleteKey(key);
|
|
121
|
+
debugKey(key, `Deleted.`);
|
|
122
|
+
}
|
|
123
|
+
|
|
115
124
|
/**
|
|
116
125
|
* Reset current test run:
|
|
117
126
|
* - clear all non-persistent values
|
package/src/index.ts
CHANGED
package/src/server/getter.ts
CHANGED
|
@@ -33,41 +33,30 @@ export class Getter {
|
|
|
33
33
|
|
|
34
34
|
// wait if computing
|
|
35
35
|
if (valueInfo?.state === 'computing') {
|
|
36
|
-
valueInfo = await this.testRunStorage.
|
|
36
|
+
valueInfo = await this.testRunStorage.waitForComputed(key);
|
|
37
37
|
return valueInfo.state === 'computed'
|
|
38
38
|
? this.handleComputed(valueInfo)
|
|
39
39
|
: this.handleError(valueInfo);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const signatureMismatch = checkSignature(key, valueInfo.sig, sig);
|
|
47
|
-
// eslint-disable-next-line max-depth
|
|
48
|
-
if (signatureMismatch) {
|
|
49
|
-
return this.handleSignatureChanged(valueInfo, sig, signatureMismatch);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
42
|
+
// no value in memory -- claim the key atomically before touching persistent storage,
|
|
43
|
+
// so concurrent callers for the same key can't all decide to recompute independently
|
|
44
|
+
if (!valueInfo) {
|
|
45
|
+
return this.handleNoValue(key, sig, ttl);
|
|
52
46
|
}
|
|
53
47
|
|
|
54
48
|
// check expired
|
|
55
|
-
if (valueInfo
|
|
49
|
+
if (valueInfo.state === 'computed' && valueInfo.persistent && ttl) {
|
|
56
50
|
if (isExpired(valueInfo.computedAt, ttl)) {
|
|
57
51
|
return this.handleExpired(valueInfo, ttl);
|
|
58
52
|
}
|
|
59
53
|
}
|
|
60
54
|
|
|
61
55
|
// normal cache hit
|
|
62
|
-
if (valueInfo
|
|
56
|
+
if (valueInfo.state === 'computed') {
|
|
63
57
|
return this.handleComputed(valueInfo);
|
|
64
58
|
}
|
|
65
59
|
|
|
66
|
-
// no value
|
|
67
|
-
if (!valueInfo) {
|
|
68
|
-
return this.handleNoValue(key, sig, ttl);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
60
|
return this.handleDefault(valueInfo);
|
|
72
61
|
}
|
|
73
62
|
|
|
@@ -86,21 +75,6 @@ export class Getter {
|
|
|
86
75
|
return { result: 'error', message: valueInfo.errorMessage || 'Unknown error' };
|
|
87
76
|
}
|
|
88
77
|
|
|
89
|
-
private async handleSignatureChanged(
|
|
90
|
-
loadedValueInfo: TestRunValueInfo,
|
|
91
|
-
newSig: string,
|
|
92
|
-
{ field }: SignatureMismatch,
|
|
93
|
-
): Promise<GetterCacheMiss> {
|
|
94
|
-
await this.updateValueInfo(loadedValueInfo, {
|
|
95
|
-
state: 'computing',
|
|
96
|
-
sig: newSig,
|
|
97
|
-
prevValue: loadedValueInfo.value,
|
|
98
|
-
value: undefined,
|
|
99
|
-
computedAt: undefined,
|
|
100
|
-
});
|
|
101
|
-
return { result: 'cache-miss', message: `signature changed: ${field}` };
|
|
102
|
-
}
|
|
103
|
-
|
|
104
78
|
private async handleExpired(valueInfo: TestRunValueInfo, ttl: number): Promise<GetterCacheMiss> {
|
|
105
79
|
await this.updateValueInfo(valueInfo, {
|
|
106
80
|
state: 'computing',
|
|
@@ -111,9 +85,45 @@ export class Getter {
|
|
|
111
85
|
return { result: 'cache-miss', message: `expired: ${ttl}` };
|
|
112
86
|
}
|
|
113
87
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
88
|
+
// eslint-disable-next-line visual/complexity, max-statements
|
|
89
|
+
private async handleNoValue(key: string, sig: string, ttl?: number): Promise<GetterResult> {
|
|
90
|
+
const placeholder: TestRunValueInfo = {
|
|
91
|
+
key,
|
|
92
|
+
state: 'computing',
|
|
93
|
+
sig,
|
|
94
|
+
persistent: Boolean(ttl),
|
|
95
|
+
};
|
|
96
|
+
const claimed = this.testRunStorage.claimForComputing(placeholder);
|
|
97
|
+
if (!claimed) {
|
|
98
|
+
const resolved = await this.testRunStorage.waitForComputed(key);
|
|
99
|
+
return resolved.state === 'computed'
|
|
100
|
+
? this.handleComputed(resolved)
|
|
101
|
+
: this.handleError(resolved);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!ttl) return { result: 'cache-miss', message: 'no cached value' };
|
|
105
|
+
|
|
106
|
+
// We own the 'computing' slot now, so no other concurrent caller can also decide
|
|
107
|
+
// to recompute this key while we consult persistent storage.
|
|
108
|
+
const persisted = await this.persistentStorage.load(key);
|
|
109
|
+
if (!persisted) return { result: 'cache-miss', message: 'no cached value' };
|
|
110
|
+
|
|
111
|
+
const signatureMismatch = checkSignature(key, persisted.sig, sig);
|
|
112
|
+
if (signatureMismatch) {
|
|
113
|
+
placeholder.prevValue = persisted.value;
|
|
114
|
+
return { result: 'cache-miss', message: `signature changed: ${signatureMismatch.field}` };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (isExpired(persisted.computedAt, ttl)) {
|
|
118
|
+
placeholder.prevValue = persisted.value;
|
|
119
|
+
return { result: 'cache-miss', message: `expired: ${ttl}` };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Persistent value is fresh and valid -- adopt it as computed, update the map entry
|
|
123
|
+
// (already resident via claimForComputing) and notify any waiters.
|
|
124
|
+
Object.assign(placeholder, persisted);
|
|
125
|
+
await this.testRunStorage.save(placeholder, { notify: true });
|
|
126
|
+
return this.handleComputed(placeholder);
|
|
117
127
|
}
|
|
118
128
|
|
|
119
129
|
private async handleDefault(valueInfo: TestRunValueInfo): Promise<GetterCacheMiss> {
|
package/src/server/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { router as routeSet } from './routes/set';
|
|
|
15
15
|
import { router as routeGetStale } from './routes/get-stale';
|
|
16
16
|
import { router as routeGetStaleList } from './routes/get-stale-list';
|
|
17
17
|
import { router as routeClearTestRun } from './routes/clear';
|
|
18
|
+
import { router as routeDeleteValue } from './routes/delete';
|
|
18
19
|
import { errorHandler } from './error';
|
|
19
20
|
import { GlobalCacheServerConfig, resolveConfig, setConfig } from './config';
|
|
20
21
|
import { startExpressServer, stopExpressServer } from './utils/express';
|
|
@@ -24,13 +25,14 @@ export class GlobalCacheServer {
|
|
|
24
25
|
private server: http.Server | null = null;
|
|
25
26
|
|
|
26
27
|
constructor() {
|
|
27
|
-
this.app.use(express.json());
|
|
28
|
+
this.app.use(express.json({ limit: '10mb' }));
|
|
28
29
|
this.app.use('/', routeRoot);
|
|
29
30
|
this.app.use('/', routeGet);
|
|
30
31
|
this.app.use('/', routeSet);
|
|
31
32
|
this.app.use('/', routeGetStale);
|
|
32
33
|
this.app.use('/', routeGetStaleList);
|
|
33
34
|
this.app.use('/', routeClearTestRun);
|
|
35
|
+
this.app.use('/', routeDeleteValue);
|
|
34
36
|
// Must be after all other middleware and routes
|
|
35
37
|
this.app.use(errorHandler);
|
|
36
38
|
}
|
|
@@ -54,6 +56,11 @@ export class GlobalCacheServer {
|
|
|
54
56
|
const config = resolveConfig(providedConfig);
|
|
55
57
|
setConfig(this.app, config);
|
|
56
58
|
this.server = await startExpressServer(this.app, config.port);
|
|
59
|
+
// unref() so the server does not prevent the Node.js process from exiting
|
|
60
|
+
// naturally when all other work is done (e.g. in CLI mode after tests finish).
|
|
61
|
+
// In VSCode / UI mode the process is kept alive by Playwright's own IPC
|
|
62
|
+
// channels, so the server stays up automatically for subsequent runs.
|
|
63
|
+
this.server.unref();
|
|
57
64
|
debug(`Starting server: done ${this.localUrl}`);
|
|
58
65
|
}
|
|
59
66
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Express, Router } from 'express';
|
|
2
|
+
import { getConfig } from '../config';
|
|
3
|
+
import { getStorage } from '../storage';
|
|
4
|
+
|
|
5
|
+
export const router: ReturnType<typeof Router> = Router();
|
|
6
|
+
|
|
7
|
+
export type DeleteValueParams = {
|
|
8
|
+
key: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
router.post('/run/:runId/delete', async (req, res) => {
|
|
12
|
+
const { runId } = req.params;
|
|
13
|
+
const { key } = req.body as DeleteValueParams;
|
|
14
|
+
const config = getConfig(req.app as Express);
|
|
15
|
+
|
|
16
|
+
const { testRunStorage, persistentStorage } = getStorage(config, runId);
|
|
17
|
+
|
|
18
|
+
const valueInfo = await testRunStorage.load(key);
|
|
19
|
+
await testRunStorage.delete(key);
|
|
20
|
+
if (valueInfo?.persistent) await persistentStorage.delete(key);
|
|
21
|
+
|
|
22
|
+
res.end();
|
|
23
|
+
});
|
|
@@ -20,11 +20,37 @@ export class MemoryStorage implements ITestRunStorage {
|
|
|
20
20
|
if (notify) this.notify(valueInfo);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
async delete(key: string) {
|
|
24
|
+
this.values.delete(key);
|
|
25
|
+
}
|
|
26
|
+
|
|
23
27
|
async clear() {
|
|
24
28
|
this.values.clear();
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Atomically claims the key for computing if it is not yet present.
|
|
33
|
+
*
|
|
34
|
+
* Concurrent workers all call `await testRunStorage.load(key)`, which yields the event loop,
|
|
35
|
+
* so all of them can see `undefined` simultaneously. Using async `save()` for the initial
|
|
36
|
+
* write would let every worker return `cache-miss`, compute in parallel, and collide in
|
|
37
|
+
* `setter.set()` — which only accepts a single `'computing'` caller.
|
|
38
|
+
*
|
|
39
|
+
* Because this method has no `await`, Node.js's single-threaded event loop makes
|
|
40
|
+
* `Map.has()` + `Map.set()` atomic. Only the first caller gets `true` (proceeds to compute);
|
|
41
|
+
* all subsequent callers get `false` (and wait).
|
|
42
|
+
*/
|
|
43
|
+
claimForComputing(valueInfo: TestRunValueInfo): boolean {
|
|
44
|
+
if (this.values.has(valueInfo.key)) return false;
|
|
45
|
+
this.values.set(valueInfo.key, valueInfo);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async waitForComputed(key: string): Promise<TestRunValueInfo> {
|
|
50
|
+
// Guard: if notify already fired before we registered, return immediately.
|
|
51
|
+
const existing = this.values.get(key);
|
|
52
|
+
if (existing && existing.state !== 'computing') return existing;
|
|
53
|
+
|
|
28
54
|
return new Promise<TestRunValueInfo>((resolve) => {
|
|
29
55
|
const listeners = this.listeners.get(key) || [];
|
|
30
56
|
listeners.push(resolve);
|
|
@@ -3,7 +3,9 @@ import { TestRunValueInfo } from '../../shared/value-info';
|
|
|
3
3
|
export type ITestRunStorage = {
|
|
4
4
|
load(key: string): Promise<TestRunValueInfo | undefined>;
|
|
5
5
|
save(valueInfo: TestRunValueInfo, options?: { notify?: boolean }): Promise<void>;
|
|
6
|
-
|
|
6
|
+
delete(key: string): Promise<void>;
|
|
7
|
+
waitForComputed(key: string): Promise<TestRunValueInfo>;
|
|
8
|
+
claimForComputing(valueInfo: TestRunValueInfo): boolean;
|
|
7
9
|
};
|
|
8
10
|
|
|
9
11
|
export type IPersistentStorage = {
|