veryfront 0.1.87 → 0.1.88
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/esm/deno.js +1 -1
- package/esm/src/cache/distributed-cache-init.d.ts +9 -0
- package/esm/src/cache/distributed-cache-init.d.ts.map +1 -1
- package/esm/src/cache/distributed-cache-init.js +70 -52
- package/esm/src/cache/module-cache.d.ts +6 -2
- package/esm/src/cache/module-cache.d.ts.map +1 -1
- package/esm/src/cache/module-cache.js +73 -56
- package/esm/src/transforms/esm/http-cache-wrapper.d.ts +3 -0
- package/esm/src/transforms/esm/http-cache-wrapper.d.ts.map +1 -1
- package/esm/src/transforms/esm/http-cache-wrapper.js +21 -7
- package/esm/src/utils/version.d.ts +1 -1
- package/esm/src/utils/version.js +1 -1
- package/package.json +1 -1
- package/src/deno.js +1 -1
- package/src/src/cache/distributed-cache-init.ts +95 -59
- package/src/src/cache/module-cache.ts +95 -57
- package/src/src/transforms/esm/http-cache-wrapper.ts +28 -7
- package/src/src/utils/version.ts +1 -1
package/esm/deno.js
CHANGED
|
@@ -4,7 +4,16 @@ interface DistributedCacheStatus {
|
|
|
4
4
|
ssrModuleCache: boolean;
|
|
5
5
|
fileCache: boolean;
|
|
6
6
|
projectCSSCache: boolean;
|
|
7
|
+
httpModuleCache: boolean;
|
|
7
8
|
}
|
|
9
|
+
type DistributedCacheInitializers = {
|
|
10
|
+
transformCache: () => Promise<boolean>;
|
|
11
|
+
ssrModuleCache: () => Promise<boolean>;
|
|
12
|
+
fileCache: () => Promise<boolean>;
|
|
13
|
+
projectCSSCache: () => Promise<boolean>;
|
|
14
|
+
httpModuleCache: () => Promise<boolean>;
|
|
15
|
+
};
|
|
16
|
+
export declare function __runDistributedCacheInitializationForTests(backend: DistributedCacheStatus["backend"], initializers: DistributedCacheInitializers): Promise<DistributedCacheStatus>;
|
|
8
17
|
export declare function initializeDistributedCaches(): Promise<DistributedCacheStatus>;
|
|
9
18
|
export {};
|
|
10
19
|
//# sourceMappingURL=distributed-cache-init.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"distributed-cache-init.d.ts","sourceRoot":"","sources":["../../../src/src/cache/distributed-cache-init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"distributed-cache-init.d.ts","sourceRoot":"","sources":["../../../src/src/cache/distributed-cache-init.ts"],"names":[],"mappings":"AAaA,UAAU,sBAAsB;IAC9B,OAAO,EAAE,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC7C,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,KAAK,4BAA4B,GAAG;IAClC,cAAc,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,cAAc,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,eAAe,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,eAAe,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACzC,CAAC;AAyFF,wBAAgB,2CAA2C,CACzD,OAAO,EAAE,sBAAsB,CAAC,SAAS,CAAC,EAC1C,YAAY,EAAE,4BAA4B,GACzC,OAAO,CAAC,sBAAsB,CAAC,CAEjC;AAED,wBAAgB,2BAA2B,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAmB7E"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { initializeFileCacheBackend } from "../platform/adapters/fs/cache/file-cache.js";
|
|
2
2
|
import { initializeSSRDistributedCache } from "../modules/react-loader/ssr-module-loader/index.js";
|
|
3
3
|
import { initializeTransformCache } from "../transforms/esm/transform-cache.js";
|
|
4
|
+
import { initializeHttpModuleDistributedCache } from "../transforms/esm/http-cache-wrapper.js";
|
|
4
5
|
import { SpanNames } from "../observability/tracing/span-names.js";
|
|
5
6
|
import { withSpan } from "../observability/tracing/otlp-setup.js";
|
|
6
7
|
import { initializeProjectCSSCache } from "../html/styles-builder/tailwind-compiler.js";
|
|
@@ -8,6 +9,13 @@ import { logger as baseLogger } from "../utils/logger/logger.js";
|
|
|
8
9
|
import { isRedisConfigured } from "../utils/redis-client.js";
|
|
9
10
|
import { isApiCacheAvailable, isDiskCacheConfigured } from "./backend.js";
|
|
10
11
|
const logger = baseLogger.component("distributed-cache");
|
|
12
|
+
const defaultInitializers = {
|
|
13
|
+
transformCache: initializeTransformCache,
|
|
14
|
+
ssrModuleCache: initializeSSRDistributedCache,
|
|
15
|
+
fileCache: initializeFileCacheBackend,
|
|
16
|
+
projectCSSCache: initializeProjectCSSCache,
|
|
17
|
+
httpModuleCache: initializeHttpModuleDistributedCache,
|
|
18
|
+
};
|
|
11
19
|
function determineBackend() {
|
|
12
20
|
if (isApiCacheAvailable())
|
|
13
21
|
return "api";
|
|
@@ -20,6 +28,66 @@ function determineBackend() {
|
|
|
20
28
|
function wasSuccessful(result) {
|
|
21
29
|
return result.status === "fulfilled" && result.value;
|
|
22
30
|
}
|
|
31
|
+
async function initializeDistributedCachesWithInitializers(backend, initializers) {
|
|
32
|
+
logger.info("Initializing caches...", { backend });
|
|
33
|
+
const cacheNames = [
|
|
34
|
+
"transformCache",
|
|
35
|
+
"ssrModuleCache",
|
|
36
|
+
"fileCache",
|
|
37
|
+
"projectCSSCache",
|
|
38
|
+
"httpModuleCache",
|
|
39
|
+
];
|
|
40
|
+
const results = await Promise.allSettled([
|
|
41
|
+
initializers.transformCache(),
|
|
42
|
+
initializers.ssrModuleCache(),
|
|
43
|
+
initializers.fileCache(),
|
|
44
|
+
initializers.projectCSSCache(),
|
|
45
|
+
initializers.httpModuleCache(),
|
|
46
|
+
]);
|
|
47
|
+
for (let i = 0; i < results.length; i++) {
|
|
48
|
+
const result = results[i];
|
|
49
|
+
if (result && result.status === "rejected") {
|
|
50
|
+
logger.error(`Cache initialization failed: ${cacheNames[i]}`, {
|
|
51
|
+
backend,
|
|
52
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const status = {
|
|
57
|
+
backend,
|
|
58
|
+
transformCache: wasSuccessful(results[0]),
|
|
59
|
+
ssrModuleCache: wasSuccessful(results[1]),
|
|
60
|
+
fileCache: wasSuccessful(results[2]),
|
|
61
|
+
projectCSSCache: wasSuccessful(results[3]),
|
|
62
|
+
httpModuleCache: wasSuccessful(results[4]),
|
|
63
|
+
};
|
|
64
|
+
const enabled = [
|
|
65
|
+
status.transformCache,
|
|
66
|
+
status.ssrModuleCache,
|
|
67
|
+
status.fileCache,
|
|
68
|
+
status.projectCSSCache,
|
|
69
|
+
status.httpModuleCache,
|
|
70
|
+
].filter(Boolean).length;
|
|
71
|
+
if (enabled === 0) {
|
|
72
|
+
logger.warn("No caches enabled despite backend being available", {
|
|
73
|
+
backend,
|
|
74
|
+
});
|
|
75
|
+
return status;
|
|
76
|
+
}
|
|
77
|
+
logger.info("Initialization complete", {
|
|
78
|
+
backend,
|
|
79
|
+
enabled,
|
|
80
|
+
transform: status.transformCache,
|
|
81
|
+
ssrModule: status.ssrModuleCache,
|
|
82
|
+
file: status.fileCache,
|
|
83
|
+
projectCSS: status.projectCSSCache,
|
|
84
|
+
httpModule: status.httpModuleCache,
|
|
85
|
+
});
|
|
86
|
+
return status;
|
|
87
|
+
}
|
|
88
|
+
export function __runDistributedCacheInitializationForTests(backend, initializers) {
|
|
89
|
+
return initializeDistributedCachesWithInitializers(backend, initializers);
|
|
90
|
+
}
|
|
23
91
|
export function initializeDistributedCaches() {
|
|
24
92
|
const backend = determineBackend();
|
|
25
93
|
if (backend === "memory") {
|
|
@@ -29,58 +97,8 @@ export function initializeDistributedCaches() {
|
|
|
29
97
|
ssrModuleCache: false,
|
|
30
98
|
fileCache: false,
|
|
31
99
|
projectCSSCache: false,
|
|
100
|
+
httpModuleCache: false,
|
|
32
101
|
});
|
|
33
102
|
}
|
|
34
|
-
return withSpan(SpanNames.CACHE_DISTRIBUTED_INIT,
|
|
35
|
-
logger.info("Initializing caches...", { backend });
|
|
36
|
-
const cacheNames = [
|
|
37
|
-
"transformCache",
|
|
38
|
-
"ssrModuleCache",
|
|
39
|
-
"fileCache",
|
|
40
|
-
"projectCSSCache",
|
|
41
|
-
];
|
|
42
|
-
const results = await Promise.allSettled([
|
|
43
|
-
initializeTransformCache(),
|
|
44
|
-
initializeSSRDistributedCache(),
|
|
45
|
-
initializeFileCacheBackend(),
|
|
46
|
-
initializeProjectCSSCache(),
|
|
47
|
-
]);
|
|
48
|
-
for (let i = 0; i < results.length; i++) {
|
|
49
|
-
const result = results[i];
|
|
50
|
-
if (result && result.status === "rejected") {
|
|
51
|
-
logger.error(`Cache initialization failed: ${cacheNames[i]}`, {
|
|
52
|
-
backend,
|
|
53
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
const status = {
|
|
58
|
-
backend,
|
|
59
|
-
transformCache: wasSuccessful(results[0]),
|
|
60
|
-
ssrModuleCache: wasSuccessful(results[1]),
|
|
61
|
-
fileCache: wasSuccessful(results[2]),
|
|
62
|
-
projectCSSCache: wasSuccessful(results[3]),
|
|
63
|
-
};
|
|
64
|
-
const enabled = [
|
|
65
|
-
status.transformCache,
|
|
66
|
-
status.ssrModuleCache,
|
|
67
|
-
status.fileCache,
|
|
68
|
-
status.projectCSSCache,
|
|
69
|
-
].filter(Boolean).length;
|
|
70
|
-
if (enabled === 0) {
|
|
71
|
-
logger.warn("No caches enabled despite backend being available", {
|
|
72
|
-
backend,
|
|
73
|
-
});
|
|
74
|
-
return status;
|
|
75
|
-
}
|
|
76
|
-
logger.info("Initialization complete", {
|
|
77
|
-
backend,
|
|
78
|
-
enabled,
|
|
79
|
-
transform: status.transformCache,
|
|
80
|
-
ssrModule: status.ssrModuleCache,
|
|
81
|
-
file: status.fileCache,
|
|
82
|
-
projectCSS: status.projectCSSCache,
|
|
83
|
-
});
|
|
84
|
-
return status;
|
|
85
|
-
}, { "cache.backend": backend });
|
|
103
|
+
return withSpan(SpanNames.CACHE_DISTRIBUTED_INIT, () => initializeDistributedCachesWithInitializers(backend, defaultInitializers), { "cache.backend": backend });
|
|
86
104
|
}
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Pod-Level Module Cache Singleton
|
|
3
3
|
**************************/
|
|
4
4
|
import { LRUCache } from "../utils/lru-wrapper.js";
|
|
5
|
+
export interface ModuleCacheMap extends Map<string, string> {
|
|
6
|
+
getOrInsert(key: string, value: string): string;
|
|
7
|
+
getOrInsertComputed(key: string, callback: (key: string) => string): string;
|
|
8
|
+
}
|
|
5
9
|
interface ModuleCacheStats {
|
|
6
10
|
moduleCache: {
|
|
7
11
|
size: number;
|
|
@@ -16,8 +20,8 @@ interface ModuleCacheStats {
|
|
|
16
20
|
}
|
|
17
21
|
export declare function getModuleCache(): LRUCache<string, string>;
|
|
18
22
|
export declare function getEsmCache(): LRUCache<string, string>;
|
|
19
|
-
export declare function createModuleCache():
|
|
20
|
-
export declare function createEsmCache():
|
|
23
|
+
export declare function createModuleCache(): ModuleCacheMap;
|
|
24
|
+
export declare function createEsmCache(): ModuleCacheMap;
|
|
21
25
|
export declare function getModuleCacheStats(): ModuleCacheStats;
|
|
22
26
|
export declare function clearModuleCaches(): void;
|
|
23
27
|
export declare function clearModuleCacheForProject(projectId: string): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-cache.d.ts","sourceRoot":"","sources":["../../../src/src/cache/module-cache.ts"],"names":[],"mappings":"AAAA;;4BAE4B;AAE5B,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAenD,UAAU,gBAAgB;IACxB,WAAW,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAqDD,wBAAgB,cAAc,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAEzD;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAEtD;AAED,wBAAgB,iBAAiB,IAAI,
|
|
1
|
+
{"version":3,"file":"module-cache.d.ts","sourceRoot":"","sources":["../../../src/src/cache/module-cache.ts"],"names":[],"mappings":"AAAA;;4BAE4B;AAE5B,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAenD,MAAM,WAAW,cAAe,SAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IACzD,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAChD,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAAC;CAC7E;AAED,UAAU,gBAAgB;IACxB,WAAW,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAqDD,wBAAgB,cAAc,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAEzD;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAEtD;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAElD;AAED,wBAAgB,cAAc,IAAI,cAAc,CAE/C;AA8FD,wBAAgB,mBAAmB,IAAI,gBAAgB,CAatD;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAIxC;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAgBpE;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAM1C"}
|
|
@@ -57,64 +57,81 @@ export function createEsmCache() {
|
|
|
57
57
|
return createMapInterface(getEsmCache());
|
|
58
58
|
}
|
|
59
59
|
function createMapInterface(cache) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
60
|
+
return new LRUBackedMap(cache);
|
|
61
|
+
}
|
|
62
|
+
class LRUBackedMap {
|
|
63
|
+
cache;
|
|
64
|
+
[Symbol.toStringTag] = "Map";
|
|
65
|
+
constructor(cache) {
|
|
66
|
+
this.cache = cache;
|
|
67
|
+
}
|
|
68
|
+
get(key) {
|
|
69
|
+
return this.cache.get(key);
|
|
70
|
+
}
|
|
71
|
+
set(key, value) {
|
|
72
|
+
this.cache.set(key, value);
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
has(key) {
|
|
76
|
+
return this.cache.has(key);
|
|
77
|
+
}
|
|
78
|
+
delete(key) {
|
|
79
|
+
return this.cache.delete(key);
|
|
80
|
+
}
|
|
81
|
+
clear() {
|
|
82
|
+
this.cache.clear();
|
|
83
|
+
}
|
|
84
|
+
getOrInsert(key, value) {
|
|
85
|
+
const existing = this.cache.get(key);
|
|
86
|
+
if (existing !== undefined)
|
|
87
|
+
return existing;
|
|
88
|
+
this.cache.set(key, value);
|
|
89
|
+
return value;
|
|
90
|
+
}
|
|
91
|
+
getOrInsertComputed(key, callback) {
|
|
92
|
+
const existing = this.cache.get(key);
|
|
93
|
+
if (existing !== undefined)
|
|
94
|
+
return existing;
|
|
95
|
+
const value = callback(key);
|
|
96
|
+
this.cache.set(key, value);
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
get size() {
|
|
100
|
+
return this.cache.size;
|
|
101
|
+
}
|
|
102
|
+
keys() {
|
|
103
|
+
return this.cache.keys();
|
|
104
|
+
}
|
|
105
|
+
values() {
|
|
106
|
+
const keysIter = this.cache.keys();
|
|
107
|
+
const cacheRef = this.cache;
|
|
108
|
+
return (function* () {
|
|
109
|
+
for (const key of keysIter) {
|
|
110
|
+
const value = cacheRef.get(key);
|
|
108
111
|
if (value !== undefined)
|
|
109
|
-
|
|
112
|
+
yield value;
|
|
110
113
|
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
114
|
+
})();
|
|
115
|
+
}
|
|
116
|
+
entries() {
|
|
117
|
+
const keysIter = this.cache.keys();
|
|
118
|
+
const cacheRef = this.cache;
|
|
119
|
+
return (function* () {
|
|
120
|
+
for (const key of keysIter) {
|
|
121
|
+
const value = cacheRef.get(key);
|
|
122
|
+
if (value !== undefined)
|
|
123
|
+
yield [key, value];
|
|
124
|
+
}
|
|
125
|
+
})();
|
|
126
|
+
}
|
|
127
|
+
forEach(callback, thisArg) {
|
|
128
|
+
for (const [key, value] of this.entries()) {
|
|
129
|
+
callback.call(thisArg, value, key, this);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
[Symbol.iterator]() {
|
|
133
|
+
return this.entries();
|
|
134
|
+
}
|
|
118
135
|
}
|
|
119
136
|
export function getModuleCacheStats() {
|
|
120
137
|
return {
|
|
@@ -10,8 +10,11 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @module transforms/esm/http-cache-wrapper
|
|
12
12
|
*/
|
|
13
|
+
import type { CacheBackend } from "../../cache/types.js";
|
|
13
14
|
import type { BundleHash, LocalModuleCode, NormalizedUrl, PortableModuleCode } from "./http-cache-types.js";
|
|
14
15
|
import { asBundleHash } from "./http-cache-invariants.js";
|
|
16
|
+
export declare function __setDistributedCacheAccessorForTests(accessor: (() => Promise<CacheBackend | null>) | null): void;
|
|
17
|
+
export declare function initializeHttpModuleDistributedCache(): Promise<boolean>;
|
|
15
18
|
/**
|
|
16
19
|
* Tokenize local code paths to portable format.
|
|
17
20
|
* Replaces absolute cache directory paths with __VF_CACHE_DIR__ tokens.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-cache-wrapper.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/http-cache-wrapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"http-cache-wrapper.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/http-cache-wrapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,KAAK,EACV,UAAU,EAEV,eAAe,EACf,aAAa,EACb,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,YAAY,EAKb,MAAM,4BAA4B,CAAC;AAoBpC,wBAAgB,qCAAqC,CACnD,QAAQ,EAAE,CAAC,MAAM,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,GACpD,IAAI,CAEN;AAED,wBAAsB,oCAAoC,IAAI,OAAO,CAAC,OAAO,CAAC,CAM7E;AAWD;;;;;;GAMG;AACH,iBAAS,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,kBAAkB,CAoB3D;AAED;;;GAGG;AACH,iBAAS,UAAU,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,GAAG,eAAe,CAMtE;AAmCD;;GAEG;AACH,UAAU,aAAa;IACrB,wEAAwE;IACxE,IAAI,EAAE,eAAe,GAAG,IAAI,CAAC;IAC7B,uDAAuD;IACvD,UAAU,EAAE,OAAO,CAAC;IACpB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,WAAW,GAAG,oBAAoB,GAAG,cAAc,GAAG,OAAO,CAAC;CAC5E;AAED;;;;;;;;;GASG;AACH,cAAM,eAAe;IACnB;;;;;;OAMG;IACG,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAiDtE;;;;;;OAMG;IACG,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAqCrE;;;;;;;;OAQG;IACG,OAAO,CACX,IAAI,EAAE,UAAU,GAAG,MAAM,EACzB,IAAI,EAAE,eAAe,EACrB,GAAG,EAAE,aAAa,GAAG,MAAM,EAC3B,GAAG,GAAE,MAAwC,GAC5C,OAAO,CAAC,IAAI,CAAC;IA+BhB;;;;;;OAMG;IACG,aAAa,CACjB,MAAM,EAAE,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC,GACjC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IA8CxC;;;;;OAKG;IACG,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAcvE;;;;;;OAMG;IACG,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAsB7D;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAItC;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,iBAAwB,CAAC;AAErD;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -23,6 +23,20 @@ const logger = rendererLogger.component("http-cache-wrapper");
|
|
|
23
23
|
const BATCH_FETCH_CHUNK_SIZE = 100;
|
|
24
24
|
/** Lazy-loaded distributed cache backend for cross-pod sharing */
|
|
25
25
|
const getDistributedCache = createDistributedCacheAccessor(() => CacheBackends.httpModule(), "HTTP-CACHE-WRAPPER");
|
|
26
|
+
let testDistributedCacheAccessor = null;
|
|
27
|
+
function resolveDistributedCache() {
|
|
28
|
+
return testDistributedCacheAccessor ? testDistributedCacheAccessor() : getDistributedCache();
|
|
29
|
+
}
|
|
30
|
+
export function __setDistributedCacheAccessorForTests(accessor) {
|
|
31
|
+
testDistributedCacheAccessor = accessor;
|
|
32
|
+
}
|
|
33
|
+
export async function initializeHttpModuleDistributedCache() {
|
|
34
|
+
const distributed = await resolveDistributedCache();
|
|
35
|
+
if (!distributed)
|
|
36
|
+
return false;
|
|
37
|
+
logger.info("Initialized distributed cache backend", { backend: distributed.type });
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
26
40
|
/**
|
|
27
41
|
* Generate versioned cache key for HTTP bundles.
|
|
28
42
|
* Format: {VERSION}:{prefix}:{hash}
|
|
@@ -110,7 +124,7 @@ class HttpBundleCache {
|
|
|
110
124
|
* @returns Result containing local code or failure reason
|
|
111
125
|
*/
|
|
112
126
|
async getCodeByHash(hash) {
|
|
113
|
-
const distributed = await
|
|
127
|
+
const distributed = await resolveDistributedCache();
|
|
114
128
|
if (!distributed) {
|
|
115
129
|
return { code: null, wasGzipped: false, failReason: "not_found" };
|
|
116
130
|
}
|
|
@@ -160,7 +174,7 @@ class HttpBundleCache {
|
|
|
160
174
|
* @returns Result containing local code or failure reason
|
|
161
175
|
*/
|
|
162
176
|
async getCodeByUrl(hash) {
|
|
163
|
-
const distributed = await
|
|
177
|
+
const distributed = await resolveDistributedCache();
|
|
164
178
|
if (!distributed) {
|
|
165
179
|
return { code: null, wasGzipped: false, failReason: "not_found" };
|
|
166
180
|
}
|
|
@@ -200,7 +214,7 @@ class HttpBundleCache {
|
|
|
200
214
|
* @param ttl - TTL in seconds (defaults to HTTP_MODULE_DISTRIBUTED_TTL_SEC)
|
|
201
215
|
*/
|
|
202
216
|
async setCode(hash, code, url, ttl = HTTP_MODULE_DISTRIBUTED_TTL_SEC) {
|
|
203
|
-
const distributed = await
|
|
217
|
+
const distributed = await resolveDistributedCache();
|
|
204
218
|
if (!distributed)
|
|
205
219
|
return;
|
|
206
220
|
const hashStr = typeof hash === "string" ? hash : hash;
|
|
@@ -233,7 +247,7 @@ class HttpBundleCache {
|
|
|
233
247
|
* @returns Map of hash -> local code (missing/failed hashes not included)
|
|
234
248
|
*/
|
|
235
249
|
async getBatchCodes(hashes) {
|
|
236
|
-
const distributed = await
|
|
250
|
+
const distributed = await resolveDistributedCache();
|
|
237
251
|
if (!distributed)
|
|
238
252
|
return new Map();
|
|
239
253
|
const results = new Map();
|
|
@@ -278,7 +292,7 @@ class HttpBundleCache {
|
|
|
278
292
|
* @returns Original URL or null
|
|
279
293
|
*/
|
|
280
294
|
async getOriginalUrl(hash) {
|
|
281
|
-
const distributed = await
|
|
295
|
+
const distributed = await resolveDistributedCache();
|
|
282
296
|
if (!distributed)
|
|
283
297
|
return null;
|
|
284
298
|
const hashStr = typeof hash === "string" ? hash : hash;
|
|
@@ -298,7 +312,7 @@ class HttpBundleCache {
|
|
|
298
312
|
* @returns true if deletion was attempted, false if cache unavailable
|
|
299
313
|
*/
|
|
300
314
|
async deleteCode(hash) {
|
|
301
|
-
const distributed = await
|
|
315
|
+
const distributed = await resolveDistributedCache();
|
|
302
316
|
if (!distributed)
|
|
303
317
|
return false;
|
|
304
318
|
const hashStr = typeof hash === "string" ? hash : hash;
|
|
@@ -321,7 +335,7 @@ class HttpBundleCache {
|
|
|
321
335
|
* Check if distributed cache is available.
|
|
322
336
|
*/
|
|
323
337
|
async isAvailable() {
|
|
324
|
-
const distributed = await
|
|
338
|
+
const distributed = await resolveDistributedCache();
|
|
325
339
|
return distributed !== null;
|
|
326
340
|
}
|
|
327
341
|
}
|
package/esm/src/utils/version.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Keep in sync with deno.json version.
|
|
2
2
|
// scripts/release.ts updates this constant during releases.
|
|
3
|
-
export const VERSION = "0.1.
|
|
3
|
+
export const VERSION = "0.1.88";
|
|
4
4
|
export const SERVER_START_TIME = Date.now();
|
|
5
5
|
export function createBuildVersion(projectUpdatedAt) {
|
|
6
6
|
return {
|
package/package.json
CHANGED
package/src/deno.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { initializeFileCacheBackend } from "../platform/adapters/fs/cache/file-cache.js";
|
|
2
2
|
import { initializeSSRDistributedCache } from "../modules/react-loader/ssr-module-loader/index.js";
|
|
3
3
|
import { initializeTransformCache } from "../transforms/esm/transform-cache.js";
|
|
4
|
+
import { initializeHttpModuleDistributedCache } from "../transforms/esm/http-cache-wrapper.js";
|
|
4
5
|
import { SpanNames } from "../observability/tracing/span-names.js";
|
|
5
6
|
import { withSpan } from "../observability/tracing/otlp-setup.js";
|
|
6
7
|
import { initializeProjectCSSCache } from "../html/styles-builder/tailwind-compiler.js";
|
|
@@ -16,8 +17,25 @@ interface DistributedCacheStatus {
|
|
|
16
17
|
ssrModuleCache: boolean;
|
|
17
18
|
fileCache: boolean;
|
|
18
19
|
projectCSSCache: boolean;
|
|
20
|
+
httpModuleCache: boolean;
|
|
19
21
|
}
|
|
20
22
|
|
|
23
|
+
type DistributedCacheInitializers = {
|
|
24
|
+
transformCache: () => Promise<boolean>;
|
|
25
|
+
ssrModuleCache: () => Promise<boolean>;
|
|
26
|
+
fileCache: () => Promise<boolean>;
|
|
27
|
+
projectCSSCache: () => Promise<boolean>;
|
|
28
|
+
httpModuleCache: () => Promise<boolean>;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const defaultInitializers: DistributedCacheInitializers = {
|
|
32
|
+
transformCache: initializeTransformCache,
|
|
33
|
+
ssrModuleCache: initializeSSRDistributedCache,
|
|
34
|
+
fileCache: initializeFileCacheBackend,
|
|
35
|
+
projectCSSCache: initializeProjectCSSCache,
|
|
36
|
+
httpModuleCache: initializeHttpModuleDistributedCache,
|
|
37
|
+
};
|
|
38
|
+
|
|
21
39
|
function determineBackend(): DistributedCacheStatus["backend"] {
|
|
22
40
|
if (isApiCacheAvailable()) return "api";
|
|
23
41
|
if (isRedisConfigured()) return "redis";
|
|
@@ -29,6 +47,81 @@ function wasSuccessful(result: PromiseSettledResult<boolean>): boolean {
|
|
|
29
47
|
return result.status === "fulfilled" && result.value;
|
|
30
48
|
}
|
|
31
49
|
|
|
50
|
+
async function initializeDistributedCachesWithInitializers(
|
|
51
|
+
backend: DistributedCacheStatus["backend"],
|
|
52
|
+
initializers: DistributedCacheInitializers,
|
|
53
|
+
): Promise<DistributedCacheStatus> {
|
|
54
|
+
logger.info("Initializing caches...", { backend });
|
|
55
|
+
|
|
56
|
+
const cacheNames = [
|
|
57
|
+
"transformCache",
|
|
58
|
+
"ssrModuleCache",
|
|
59
|
+
"fileCache",
|
|
60
|
+
"projectCSSCache",
|
|
61
|
+
"httpModuleCache",
|
|
62
|
+
] as const;
|
|
63
|
+
const results = await Promise.allSettled([
|
|
64
|
+
initializers.transformCache(),
|
|
65
|
+
initializers.ssrModuleCache(),
|
|
66
|
+
initializers.fileCache(),
|
|
67
|
+
initializers.projectCSSCache(),
|
|
68
|
+
initializers.httpModuleCache(),
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
for (let i = 0; i < results.length; i++) {
|
|
72
|
+
const result = results[i];
|
|
73
|
+
if (result && result.status === "rejected") {
|
|
74
|
+
logger.error(`Cache initialization failed: ${cacheNames[i]}`, {
|
|
75
|
+
backend,
|
|
76
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const status: DistributedCacheStatus = {
|
|
82
|
+
backend,
|
|
83
|
+
transformCache: wasSuccessful(results[0]),
|
|
84
|
+
ssrModuleCache: wasSuccessful(results[1]),
|
|
85
|
+
fileCache: wasSuccessful(results[2]),
|
|
86
|
+
projectCSSCache: wasSuccessful(results[3]),
|
|
87
|
+
httpModuleCache: wasSuccessful(results[4]),
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const enabled = [
|
|
91
|
+
status.transformCache,
|
|
92
|
+
status.ssrModuleCache,
|
|
93
|
+
status.fileCache,
|
|
94
|
+
status.projectCSSCache,
|
|
95
|
+
status.httpModuleCache,
|
|
96
|
+
].filter(Boolean).length;
|
|
97
|
+
|
|
98
|
+
if (enabled === 0) {
|
|
99
|
+
logger.warn("No caches enabled despite backend being available", {
|
|
100
|
+
backend,
|
|
101
|
+
});
|
|
102
|
+
return status;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
logger.info("Initialization complete", {
|
|
106
|
+
backend,
|
|
107
|
+
enabled,
|
|
108
|
+
transform: status.transformCache,
|
|
109
|
+
ssrModule: status.ssrModuleCache,
|
|
110
|
+
file: status.fileCache,
|
|
111
|
+
projectCSS: status.projectCSSCache,
|
|
112
|
+
httpModule: status.httpModuleCache,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return status;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function __runDistributedCacheInitializationForTests(
|
|
119
|
+
backend: DistributedCacheStatus["backend"],
|
|
120
|
+
initializers: DistributedCacheInitializers,
|
|
121
|
+
): Promise<DistributedCacheStatus> {
|
|
122
|
+
return initializeDistributedCachesWithInitializers(backend, initializers);
|
|
123
|
+
}
|
|
124
|
+
|
|
32
125
|
export function initializeDistributedCaches(): Promise<DistributedCacheStatus> {
|
|
33
126
|
const backend = determineBackend();
|
|
34
127
|
|
|
@@ -39,70 +132,13 @@ export function initializeDistributedCaches(): Promise<DistributedCacheStatus> {
|
|
|
39
132
|
ssrModuleCache: false,
|
|
40
133
|
fileCache: false,
|
|
41
134
|
projectCSSCache: false,
|
|
135
|
+
httpModuleCache: false,
|
|
42
136
|
});
|
|
43
137
|
}
|
|
44
138
|
|
|
45
139
|
return withSpan(
|
|
46
140
|
SpanNames.CACHE_DISTRIBUTED_INIT,
|
|
47
|
-
|
|
48
|
-
logger.info("Initializing caches...", { backend });
|
|
49
|
-
|
|
50
|
-
const cacheNames = [
|
|
51
|
-
"transformCache",
|
|
52
|
-
"ssrModuleCache",
|
|
53
|
-
"fileCache",
|
|
54
|
-
"projectCSSCache",
|
|
55
|
-
] as const;
|
|
56
|
-
const results = await Promise.allSettled([
|
|
57
|
-
initializeTransformCache(),
|
|
58
|
-
initializeSSRDistributedCache(),
|
|
59
|
-
initializeFileCacheBackend(),
|
|
60
|
-
initializeProjectCSSCache(),
|
|
61
|
-
]);
|
|
62
|
-
|
|
63
|
-
for (let i = 0; i < results.length; i++) {
|
|
64
|
-
const result = results[i];
|
|
65
|
-
if (result && result.status === "rejected") {
|
|
66
|
-
logger.error(`Cache initialization failed: ${cacheNames[i]}`, {
|
|
67
|
-
backend,
|
|
68
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const status: DistributedCacheStatus = {
|
|
74
|
-
backend,
|
|
75
|
-
transformCache: wasSuccessful(results[0]),
|
|
76
|
-
ssrModuleCache: wasSuccessful(results[1]),
|
|
77
|
-
fileCache: wasSuccessful(results[2]),
|
|
78
|
-
projectCSSCache: wasSuccessful(results[3]),
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const enabled = [
|
|
82
|
-
status.transformCache,
|
|
83
|
-
status.ssrModuleCache,
|
|
84
|
-
status.fileCache,
|
|
85
|
-
status.projectCSSCache,
|
|
86
|
-
].filter(Boolean).length;
|
|
87
|
-
|
|
88
|
-
if (enabled === 0) {
|
|
89
|
-
logger.warn("No caches enabled despite backend being available", {
|
|
90
|
-
backend,
|
|
91
|
-
});
|
|
92
|
-
return status;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
logger.info("Initialization complete", {
|
|
96
|
-
backend,
|
|
97
|
-
enabled,
|
|
98
|
-
transform: status.transformCache,
|
|
99
|
-
ssrModule: status.ssrModuleCache,
|
|
100
|
-
file: status.fileCache,
|
|
101
|
-
projectCSS: status.projectCSSCache,
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
return status;
|
|
105
|
-
},
|
|
141
|
+
() => initializeDistributedCachesWithInitializers(backend, defaultInitializers),
|
|
106
142
|
{ "cache.backend": backend },
|
|
107
143
|
);
|
|
108
144
|
}
|
|
@@ -17,6 +17,11 @@ const logger = rendererLogger.component("module-cache");
|
|
|
17
17
|
let moduleCache: LRUCache<string, string> | null = null;
|
|
18
18
|
let esmCache: LRUCache<string, string> | null = null;
|
|
19
19
|
|
|
20
|
+
export interface ModuleCacheMap extends Map<string, string> {
|
|
21
|
+
getOrInsert(key: string, value: string): string;
|
|
22
|
+
getOrInsertComputed(key: string, callback: (key: string) => string): string;
|
|
23
|
+
}
|
|
24
|
+
|
|
20
25
|
interface ModuleCacheStats {
|
|
21
26
|
moduleCache: {
|
|
22
27
|
size: number;
|
|
@@ -89,71 +94,104 @@ export function getEsmCache(): LRUCache<string, string> {
|
|
|
89
94
|
return getOrInitPodCache(esmPodCacheOptions);
|
|
90
95
|
}
|
|
91
96
|
|
|
92
|
-
export function createModuleCache():
|
|
97
|
+
export function createModuleCache(): ModuleCacheMap {
|
|
93
98
|
return createMapInterface(getModuleCache());
|
|
94
99
|
}
|
|
95
100
|
|
|
96
|
-
export function createEsmCache():
|
|
101
|
+
export function createEsmCache(): ModuleCacheMap {
|
|
97
102
|
return createMapInterface(getEsmCache());
|
|
98
103
|
}
|
|
99
104
|
|
|
100
|
-
function createMapInterface(cache: LRUCache<string, string>):
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
105
|
+
function createMapInterface(cache: LRUCache<string, string>): ModuleCacheMap {
|
|
106
|
+
return new LRUBackedMap(cache);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
class LRUBackedMap implements ModuleCacheMap {
|
|
110
|
+
readonly [Symbol.toStringTag] = "Map";
|
|
111
|
+
|
|
112
|
+
constructor(private readonly cache: LRUCache<string, string>) {
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
get(key: string): string | undefined {
|
|
116
|
+
return this.cache.get(key);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
set(key: string, value: string): this {
|
|
120
|
+
this.cache.set(key, value);
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
has(key: string): boolean {
|
|
125
|
+
return this.cache.has(key);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
delete(key: string): boolean {
|
|
129
|
+
return this.cache.delete(key);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
clear(): void {
|
|
133
|
+
this.cache.clear();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
getOrInsert(key: string, value: string): string {
|
|
137
|
+
const existing = this.cache.get(key);
|
|
138
|
+
if (existing !== undefined) return existing;
|
|
139
|
+
|
|
140
|
+
this.cache.set(key, value);
|
|
141
|
+
return value;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
getOrInsertComputed(key: string, callback: (key: string) => string): string {
|
|
145
|
+
const existing = this.cache.get(key);
|
|
146
|
+
if (existing !== undefined) return existing;
|
|
147
|
+
|
|
148
|
+
const value = callback(key);
|
|
149
|
+
this.cache.set(key, value);
|
|
150
|
+
return value;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
get size(): number {
|
|
154
|
+
return this.cache.size;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
keys(): MapIterator<string> {
|
|
158
|
+
return this.cache.keys() as unknown as MapIterator<string>;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
values(): MapIterator<string> {
|
|
162
|
+
const keysIter = this.cache.keys();
|
|
163
|
+
const cacheRef = this.cache;
|
|
164
|
+
return (function* () {
|
|
165
|
+
for (const key of keysIter) {
|
|
166
|
+
const value = cacheRef.get(key);
|
|
167
|
+
if (value !== undefined) yield value;
|
|
148
168
|
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return map.entries();
|
|
152
|
-
},
|
|
153
|
-
[Symbol.toStringTag]: "Map",
|
|
154
|
-
};
|
|
169
|
+
})() as unknown as MapIterator<string>;
|
|
170
|
+
}
|
|
155
171
|
|
|
156
|
-
|
|
172
|
+
entries(): MapIterator<[string, string]> {
|
|
173
|
+
const keysIter = this.cache.keys();
|
|
174
|
+
const cacheRef = this.cache;
|
|
175
|
+
return (function* () {
|
|
176
|
+
for (const key of keysIter) {
|
|
177
|
+
const value = cacheRef.get(key);
|
|
178
|
+
if (value !== undefined) yield [key, value] as [string, string];
|
|
179
|
+
}
|
|
180
|
+
})() as unknown as MapIterator<[string, string]>;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
forEach(
|
|
184
|
+
callback: (value: string, key: string, map: Map<string, string>) => void,
|
|
185
|
+
thisArg?: unknown,
|
|
186
|
+
): void {
|
|
187
|
+
for (const [key, value] of this.entries()) {
|
|
188
|
+
callback.call(thisArg, value, key, this);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
[Symbol.iterator](): MapIterator<[string, string]> {
|
|
193
|
+
return this.entries();
|
|
194
|
+
}
|
|
157
195
|
}
|
|
158
196
|
|
|
159
197
|
export function getModuleCacheStats(): ModuleCacheStats {
|
|
@@ -16,6 +16,7 @@ import { rendererLogger } from "../../utils/index.js";
|
|
|
16
16
|
import { VERSION } from "../../utils/version.js";
|
|
17
17
|
import { getCacheBaseDir } from "../../utils/cache-dir.js";
|
|
18
18
|
import { CacheBackends, createDistributedCacheAccessor } from "../../cache/backend.js";
|
|
19
|
+
import type { CacheBackend } from "../../cache/types.js";
|
|
19
20
|
import { HTTP_MODULE_DISTRIBUTED_TTL_SEC } from "../../utils/constants/cache.js";
|
|
20
21
|
import type {
|
|
21
22
|
BundleHash,
|
|
@@ -44,6 +45,26 @@ const getDistributedCache = createDistributedCacheAccessor(
|
|
|
44
45
|
"HTTP-CACHE-WRAPPER",
|
|
45
46
|
);
|
|
46
47
|
|
|
48
|
+
let testDistributedCacheAccessor: (() => Promise<CacheBackend | null>) | null = null;
|
|
49
|
+
|
|
50
|
+
function resolveDistributedCache(): Promise<CacheBackend | null> {
|
|
51
|
+
return testDistributedCacheAccessor ? testDistributedCacheAccessor() : getDistributedCache();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function __setDistributedCacheAccessorForTests(
|
|
55
|
+
accessor: (() => Promise<CacheBackend | null>) | null,
|
|
56
|
+
): void {
|
|
57
|
+
testDistributedCacheAccessor = accessor;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function initializeHttpModuleDistributedCache(): Promise<boolean> {
|
|
61
|
+
const distributed = await resolveDistributedCache();
|
|
62
|
+
if (!distributed) return false;
|
|
63
|
+
|
|
64
|
+
logger.info("Initialized distributed cache backend", { backend: distributed.type });
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
47
68
|
/**
|
|
48
69
|
* Generate versioned cache key for HTTP bundles.
|
|
49
70
|
* Format: {VERSION}:{prefix}:{hash}
|
|
@@ -158,7 +179,7 @@ class HttpBundleCache {
|
|
|
158
179
|
* @returns Result containing local code or failure reason
|
|
159
180
|
*/
|
|
160
181
|
async getCodeByHash(hash: BundleHash | string): Promise<GetCodeResult> {
|
|
161
|
-
const distributed = await
|
|
182
|
+
const distributed = await resolveDistributedCache();
|
|
162
183
|
if (!distributed) {
|
|
163
184
|
return { code: null, wasGzipped: false, failReason: "not_found" };
|
|
164
185
|
}
|
|
@@ -214,7 +235,7 @@ class HttpBundleCache {
|
|
|
214
235
|
* @returns Result containing local code or failure reason
|
|
215
236
|
*/
|
|
216
237
|
async getCodeByUrl(hash: BundleHash | string): Promise<GetCodeResult> {
|
|
217
|
-
const distributed = await
|
|
238
|
+
const distributed = await resolveDistributedCache();
|
|
218
239
|
if (!distributed) {
|
|
219
240
|
return { code: null, wasGzipped: false, failReason: "not_found" };
|
|
220
241
|
}
|
|
@@ -265,7 +286,7 @@ class HttpBundleCache {
|
|
|
265
286
|
url: NormalizedUrl | string,
|
|
266
287
|
ttl: number = HTTP_MODULE_DISTRIBUTED_TTL_SEC,
|
|
267
288
|
): Promise<void> {
|
|
268
|
-
const distributed = await
|
|
289
|
+
const distributed = await resolveDistributedCache();
|
|
269
290
|
if (!distributed) return;
|
|
270
291
|
|
|
271
292
|
const hashStr = typeof hash === "string" ? hash : (hash as unknown as string);
|
|
@@ -305,7 +326,7 @@ class HttpBundleCache {
|
|
|
305
326
|
async getBatchCodes(
|
|
306
327
|
hashes: Array<BundleHash | string>,
|
|
307
328
|
): Promise<Map<string, LocalModuleCode>> {
|
|
308
|
-
const distributed = await
|
|
329
|
+
const distributed = await resolveDistributedCache();
|
|
309
330
|
if (!distributed) return new Map();
|
|
310
331
|
|
|
311
332
|
const results = new Map<string, LocalModuleCode>();
|
|
@@ -357,7 +378,7 @@ class HttpBundleCache {
|
|
|
357
378
|
* @returns Original URL or null
|
|
358
379
|
*/
|
|
359
380
|
async getOriginalUrl(hash: BundleHash | string): Promise<string | null> {
|
|
360
|
-
const distributed = await
|
|
381
|
+
const distributed = await resolveDistributedCache();
|
|
361
382
|
if (!distributed) return null;
|
|
362
383
|
|
|
363
384
|
const hashStr = typeof hash === "string" ? hash : (hash as unknown as string);
|
|
@@ -378,7 +399,7 @@ class HttpBundleCache {
|
|
|
378
399
|
* @returns true if deletion was attempted, false if cache unavailable
|
|
379
400
|
*/
|
|
380
401
|
async deleteCode(hash: BundleHash | string): Promise<boolean> {
|
|
381
|
-
const distributed = await
|
|
402
|
+
const distributed = await resolveDistributedCache();
|
|
382
403
|
if (!distributed) return false;
|
|
383
404
|
|
|
384
405
|
const hashStr = typeof hash === "string" ? hash : (hash as unknown as string);
|
|
@@ -403,7 +424,7 @@ class HttpBundleCache {
|
|
|
403
424
|
* Check if distributed cache is available.
|
|
404
425
|
*/
|
|
405
426
|
async isAvailable(): Promise<boolean> {
|
|
406
|
-
const distributed = await
|
|
427
|
+
const distributed = await resolveDistributedCache();
|
|
407
428
|
return distributed !== null;
|
|
408
429
|
}
|
|
409
430
|
}
|
package/src/src/utils/version.ts
CHANGED