@memberjunction/core 6.1.0-edge.0 → 6.1.0-edge.2
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/generic/InMemoryLocalStorageProvider.d.ts +6 -0
- package/dist/generic/InMemoryLocalStorageProvider.d.ts.map +1 -1
- package/dist/generic/InMemoryLocalStorageProvider.js +6 -0
- package/dist/generic/InMemoryLocalStorageProvider.js.map +1 -1
- package/dist/generic/baseEngineRegistry.d.ts +14 -0
- package/dist/generic/baseEngineRegistry.d.ts.map +1 -1
- package/dist/generic/baseEngineRegistry.js +32 -0
- package/dist/generic/baseEngineRegistry.js.map +1 -1
- package/dist/generic/baseEntity.d.ts +366 -29
- package/dist/generic/baseEntity.d.ts.map +1 -1
- package/dist/generic/baseEntity.js +872 -96
- package/dist/generic/baseEntity.js.map +1 -1
- package/dist/generic/dataHooks.d.ts +5 -0
- package/dist/generic/dataHooks.d.ts.map +1 -1
- package/dist/generic/dataHooks.js +27 -3
- package/dist/generic/dataHooks.js.map +1 -1
- package/dist/generic/databaseProviderBase.d.ts +44 -17
- package/dist/generic/databaseProviderBase.d.ts.map +1 -1
- package/dist/generic/databaseProviderBase.js +96 -52
- package/dist/generic/databaseProviderBase.js.map +1 -1
- package/dist/generic/entityCompanion.d.ts +218 -0
- package/dist/generic/entityCompanion.d.ts.map +1 -0
- package/dist/generic/entityCompanion.js +170 -0
- package/dist/generic/entityCompanion.js.map +1 -0
- package/dist/generic/entityInfo.d.ts +21 -0
- package/dist/generic/entityInfo.d.ts.map +1 -1
- package/dist/generic/entityInfo.js +21 -0
- package/dist/generic/entityInfo.js.map +1 -1
- package/dist/generic/entitySavePlan.d.ts +199 -0
- package/dist/generic/entitySavePlan.d.ts.map +1 -0
- package/dist/generic/entitySavePlan.js +213 -0
- package/dist/generic/entitySavePlan.js.map +1 -0
- package/dist/generic/entityTransactionScope.d.ts +125 -0
- package/dist/generic/entityTransactionScope.d.ts.map +1 -0
- package/dist/generic/entityTransactionScope.js +115 -0
- package/dist/generic/entityTransactionScope.js.map +1 -0
- package/dist/generic/interfaces.d.ts +122 -35
- package/dist/generic/interfaces.d.ts.map +1 -1
- package/dist/generic/interfaces.js +27 -0
- package/dist/generic/interfaces.js.map +1 -1
- package/dist/generic/localCacheManager.d.ts +123 -5
- package/dist/generic/localCacheManager.d.ts.map +1 -1
- package/dist/generic/localCacheManager.js +254 -9
- package/dist/generic/localCacheManager.js.map +1 -1
- package/dist/generic/providerBase.d.ts +112 -0
- package/dist/generic/providerBase.d.ts.map +1 -1
- package/dist/generic/providerBase.js +303 -9
- package/dist/generic/providerBase.js.map +1 -1
- package/dist/generic/relatedRecordBatchLoader.d.ts +39 -0
- package/dist/generic/relatedRecordBatchLoader.d.ts.map +1 -0
- package/dist/generic/relatedRecordBatchLoader.js +154 -0
- package/dist/generic/relatedRecordBatchLoader.js.map +1 -0
- package/dist/generic/relatedRecordCollection.d.ts +588 -0
- package/dist/generic/relatedRecordCollection.d.ts.map +1 -0
- package/dist/generic/relatedRecordCollection.js +1020 -0
- package/dist/generic/relatedRecordCollection.js.map +1 -0
- package/dist/generic/saveEntityGraphOperation.d.ts +148 -0
- package/dist/generic/saveEntityGraphOperation.d.ts.map +1 -0
- package/dist/generic/saveEntityGraphOperation.js +157 -0
- package/dist/generic/saveEntityGraphOperation.js.map +1 -0
- package/dist/generic/telemetryManager.d.ts +21 -1
- package/dist/generic/telemetryManager.d.ts.map +1 -1
- package/dist/generic/telemetryManager.js +21 -6
- package/dist/generic/telemetryManager.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/views/runView.d.ts +66 -0
- package/dist/views/runView.d.ts.map +1 -1
- package/dist/views/runView.js.map +1 -1
- package/package.json +3 -3
- package/readme.md +195 -1
- package/dist/generic/runReport.d.ts +0 -25
- package/dist/generic/runReport.d.ts.map +0 -1
- package/dist/generic/runReport.js +0 -38
- package/dist/generic/runReport.js.map +0 -1
|
@@ -64,7 +64,18 @@ export interface CacheStats {
|
|
|
64
64
|
* to prevent data inconsistency.
|
|
65
65
|
*/
|
|
66
66
|
export interface CachedRunViewData {
|
|
67
|
-
/**
|
|
67
|
+
/**
|
|
68
|
+
* The cached result rows.
|
|
69
|
+
*
|
|
70
|
+
* ⚠️ These rows are SHARED: under a reference-sharing storage provider (see
|
|
71
|
+
* `ILocalStorageProvider.SharesReferences`) they are the same objects held by every reader
|
|
72
|
+
* of this slot, and they are deep-frozen at write time. Mutating one corrupts process-wide
|
|
73
|
+
* state and throws a `TypeError`. Build a new array / new rows instead.
|
|
74
|
+
*
|
|
75
|
+
* Deliberately typed mutable rather than `readonly`: the runtime freeze is the enforcement,
|
|
76
|
+
* and a `readonly` marker here would be a compile break for existing downstream code that
|
|
77
|
+
* reads cache entries — without adding protection the freeze does not already provide.
|
|
78
|
+
*/
|
|
68
79
|
results: unknown[];
|
|
69
80
|
/** The maximum __mj_UpdatedAt timestamp from the results */
|
|
70
81
|
maxUpdatedAt: string;
|
|
@@ -79,13 +90,24 @@ export interface CachedRunViewData {
|
|
|
79
90
|
* Backward-compatible: entries without this field are served normally (no regression).
|
|
80
91
|
*/
|
|
81
92
|
schemaHash?: string;
|
|
93
|
+
/**
|
|
94
|
+
* Set when the slot was written with {@link CacheWriteOptions.ProviderInternalScaffolding}.
|
|
95
|
+
* Persisted so that in-place slot maintenance (`storeCachedResults`, driven by BaseEntity
|
|
96
|
+
* save/delete events) can carry the exemption FORWARD. Without it, the first save event
|
|
97
|
+
* touching a scaffolding slot would freeze it and break the owner that mutates those rows.
|
|
98
|
+
*/
|
|
99
|
+
providerInternalScaffolding?: boolean;
|
|
82
100
|
}
|
|
83
101
|
/**
|
|
84
102
|
* Return type for GetRunViewResult and ApplyDifferentialUpdate.
|
|
85
103
|
* Includes rowCount (derived from results.length) and totalRowCount (from the database).
|
|
86
104
|
*/
|
|
87
105
|
export interface CachedRunViewResult {
|
|
88
|
-
/**
|
|
106
|
+
/**
|
|
107
|
+
* The cached result rows — shared and deep-frozen; see {@link CachedRunViewData.results}.
|
|
108
|
+
* Callers that need to transform rows (e.g. GraphQL transport field renaming) must map
|
|
109
|
+
* onto copies: `results.map(r => ({ ...r }))`.
|
|
110
|
+
*/
|
|
89
111
|
results: unknown[];
|
|
90
112
|
/** The maximum __mj_UpdatedAt timestamp from the results */
|
|
91
113
|
maxUpdatedAt: string;
|
|
@@ -102,6 +124,36 @@ export interface CachedRunViewResult {
|
|
|
102
124
|
* permanently disabling post-migration drift detection for that slot.
|
|
103
125
|
*/
|
|
104
126
|
schemaHash?: string;
|
|
127
|
+
/**
|
|
128
|
+
* Surfaced from the stored payload so in-place maintenance can carry the freeze exemption
|
|
129
|
+
* forward. See {@link CachedRunViewData.providerInternalScaffolding}.
|
|
130
|
+
*/
|
|
131
|
+
providerInternalScaffolding?: boolean;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Per-write options for the cache write methods.
|
|
135
|
+
*/
|
|
136
|
+
export interface CacheWriteOptions {
|
|
137
|
+
/**
|
|
138
|
+
* Declares that this slot is **provider-internal scaffolding**: the provider doing the
|
|
139
|
+
* write is its only consumer, and the rows are transient input to that provider's own
|
|
140
|
+
* assembly step rather than data served to arbitrary callers.
|
|
141
|
+
*
|
|
142
|
+
* Such slots are exempt from the defensive deep-freeze. The freeze exists to stop
|
|
143
|
+
* *consumers* from corrupting shared rows they were handed; it buys nothing for rows with
|
|
144
|
+
* a single owner, and it would break owners that legitimately use those rows as scratch
|
|
145
|
+
* space.
|
|
146
|
+
*
|
|
147
|
+
* The motivating case is metadata bootstrap: `GetDatasetByName` caches each dataset item
|
|
148
|
+
* through this cache, and `PostProcessEntityMetadata` then hydrates a graph by sorting the
|
|
149
|
+
* row array in place and attaching child collections onto each entity/field row. Freezing
|
|
150
|
+
* those rows makes `GetAllMetadata()` throw and the process boots with no metadata at all.
|
|
151
|
+
*
|
|
152
|
+
* **Do not set this to avoid fixing a mutation.** If the rows reach anything other than
|
|
153
|
+
* the writing provider, the correct fix is for the mutator to copy first. Defaults to
|
|
154
|
+
* `false` — caller-facing results are always frozen.
|
|
155
|
+
*/
|
|
156
|
+
ProviderInternalScaffolding?: boolean;
|
|
105
157
|
}
|
|
106
158
|
/**
|
|
107
159
|
* Configuration for the LocalCacheManager
|
|
@@ -248,6 +300,12 @@ export declare class LocalCacheManager extends BaseSingleton<LocalCacheManager>
|
|
|
248
300
|
*/
|
|
249
301
|
static get Instance(): LocalCacheManager;
|
|
250
302
|
private _storageProvider;
|
|
303
|
+
/**
|
|
304
|
+
* Whether the active storage provider hands back live object references, resolved once at
|
|
305
|
+
* initialization — from the provider's declared {@link ILocalStorageProvider.SharesReferences}
|
|
306
|
+
* when it states one, otherwise measured empirically. Gates the defensive deep-freeze.
|
|
307
|
+
*/
|
|
308
|
+
private _sharesReferences;
|
|
251
309
|
private _registry;
|
|
252
310
|
private _initialized;
|
|
253
311
|
private _initializePromise;
|
|
@@ -280,6 +338,23 @@ export declare class LocalCacheManager extends BaseSingleton<LocalCacheManager>
|
|
|
280
338
|
* @returns A promise that resolves when initialization is complete
|
|
281
339
|
*/
|
|
282
340
|
Initialize(storageProvider: ILocalStorageProvider, config?: Partial<LocalCacheManagerConfig>): Promise<void>;
|
|
341
|
+
/**
|
|
342
|
+
* Decides whether the storage provider hands back live object references — the condition
|
|
343
|
+
* that makes the defensive deep-freeze necessary.
|
|
344
|
+
*
|
|
345
|
+
* Prefers the provider's declared {@link ILocalStorageProvider.SharesReferences}. When a
|
|
346
|
+
* provider does not state one (any implementation written before that property existed),
|
|
347
|
+
* MEASURE it rather than guessing: store a sentinel object, read it back, and compare
|
|
348
|
+
* identity. A reference-sharing store returns the very same object; anything with a
|
|
349
|
+
* serialization or structured-clone boundary returns a copy. This is what keeps the
|
|
350
|
+
* property optional — an external provider that never declares it still gets the correct
|
|
351
|
+
* protection instead of silently losing it to a falsy default.
|
|
352
|
+
*
|
|
353
|
+
* Fails closed to `false` if the probe cannot complete (a provider whose backing store is
|
|
354
|
+
* not ready at init): that matches the pre-freeze behavior rather than immobilizing rows
|
|
355
|
+
* for a provider we could not classify.
|
|
356
|
+
*/
|
|
357
|
+
private resolveSharesReferences;
|
|
283
358
|
/**
|
|
284
359
|
* Internal initialization logic - only called once by the first caller
|
|
285
360
|
*/
|
|
@@ -609,7 +684,8 @@ export declare class LocalCacheManager extends BaseSingleton<LocalCacheManager>
|
|
|
609
684
|
*
|
|
610
685
|
* @param name - The dataset name
|
|
611
686
|
* @param itemFilters - Optional filters applied to the dataset
|
|
612
|
-
* @param dataset - The dataset result to cache
|
|
687
|
+
* @param dataset - The dataset result to cache. Deep-frozen on reference-sharing storage,
|
|
688
|
+
* like every other cache write funnel — see below.
|
|
613
689
|
* @param keyPrefix - Prefix for the cache key (typically includes connection info)
|
|
614
690
|
*/
|
|
615
691
|
SetDataset(name: string, itemFilters: DatasetItemFilterType[] | undefined, dataset: DatasetResultType, keyPrefix: string): Promise<void>;
|
|
@@ -669,7 +745,7 @@ export declare class LocalCacheManager extends BaseSingleton<LocalCacheManager>
|
|
|
669
745
|
* pre-RLS format so normal cache sharing is preserved and no existing entries are invalidated.
|
|
670
746
|
* @returns A unique, human-readable fingerprint string
|
|
671
747
|
*/
|
|
672
|
-
GenerateRunViewFingerprint(params: RunViewParams, connectionPrefix?: string, rlsWhereClause?: string): string;
|
|
748
|
+
GenerateRunViewFingerprint(params: RunViewParams, connectionPrefix?: string, rlsWhereClause?: string, datasetSegment?: string): string;
|
|
673
749
|
/**
|
|
674
750
|
* Generates a hash string representing the aggregate expressions.
|
|
675
751
|
* This ensures different aggregate configurations get different fingerprints.
|
|
@@ -711,6 +787,41 @@ export declare class LocalCacheManager extends BaseSingleton<LocalCacheManager>
|
|
|
711
787
|
* @returns The schema hash string, or undefined if the entity can't be resolved
|
|
712
788
|
*/
|
|
713
789
|
ComputeSchemaHash(provider: IMetadataProvider | undefined, entityName: string): string | undefined;
|
|
790
|
+
/**
|
|
791
|
+
* Deep-freezes an about-to-be-stored cache payload when — and only when — the active
|
|
792
|
+
* storage provider hands out live object references
|
|
793
|
+
* ({@link ILocalStorageProvider.SharesReferences}).
|
|
794
|
+
*
|
|
795
|
+
* This is the cache's structural defense against consumer corruption. Under a
|
|
796
|
+
* reference-sharing provider the rows a caller receives ARE the cached rows, in both
|
|
797
|
+
* directions: on a hit the reader gets the stored array, and on a miss the cache stored
|
|
798
|
+
* the caller's own array. Any in-place mutation therefore edits process-wide state. One
|
|
799
|
+
* such mutation shipped as a P1 (a resolver renamed `__mj_CreatedAt` to its GraphQL
|
|
800
|
+
* transport alias in place, so every later read served rows `BaseEntity.SetMany`
|
|
801
|
+
* rejects). Freezing makes that failure immediate and attributable — a `TypeError` at
|
|
802
|
+
* the offending line — instead of silent corruption, and costs nothing per cache hit.
|
|
803
|
+
*
|
|
804
|
+
* On serializing providers this is a no-op: their stored data is already isolated, and
|
|
805
|
+
* freezing would only immobilize the caller's own rows for no safety gain.
|
|
806
|
+
*
|
|
807
|
+
* @param payload - The envelope being handed to the storage provider. Frozen in place;
|
|
808
|
+
* the same reference is returned for call-site convenience.
|
|
809
|
+
*/
|
|
810
|
+
/**
|
|
811
|
+
* Whether the CURRENTLY-INSTALLED provider hands back live references.
|
|
812
|
+
*
|
|
813
|
+
* Prefers the active provider's own declaration, read live on each call — a property read,
|
|
814
|
+
* so it costs nothing on the write path, and it stays correct no matter how many times the
|
|
815
|
+
* provider is swapped or which code path does the swapping. `_sharesReferences` (resolved at
|
|
816
|
+
* `Initialize`/`SetStorageProvider`) is the fallback for providers that declare nothing, where
|
|
817
|
+
* the answer can only come from the async probe and therefore cannot be recomputed here.
|
|
818
|
+
*
|
|
819
|
+
* Belt-and-braces with the re-resolution in {@link SetStorageProvider}: that keeps the probed
|
|
820
|
+
* value correct across swaps, and this keeps DECLARED providers correct even if some future
|
|
821
|
+
* swap site forgets to re-resolve.
|
|
822
|
+
*/
|
|
823
|
+
private activeProviderSharesReferences;
|
|
824
|
+
private freezeRowDataIfProviderSharesReferences;
|
|
714
825
|
/**
|
|
715
826
|
* Stores a RunView result in the cache.
|
|
716
827
|
*
|
|
@@ -727,8 +838,11 @@ export declare class LocalCacheManager extends BaseSingleton<LocalCacheManager>
|
|
|
727
838
|
* AllowCaching gating in multi-provider scenarios (parallel client connections to multiple
|
|
728
839
|
* servers). Falls back to `Metadata.Provider` (global default) when omitted, which is fine
|
|
729
840
|
* for single-provider apps but wrong when AllowCaching differs across servers.
|
|
841
|
+
* @param ttlMs - Optional time-based expiry (required for external-data-source entities).
|
|
842
|
+
* @param options - See {@link CacheWriteOptions}. Pass `{ ProviderInternalScaffolding: true }`
|
|
843
|
+
* only for slots the writing provider is the sole consumer of.
|
|
730
844
|
*/
|
|
731
|
-
SetRunViewResult(fingerprint: string, params: RunViewParams, results: unknown[], maxUpdatedAt: string, aggregateResults?: AggregateResult[], totalRowCount?: number, provider?: IMetadataProvider, ttlMs?: number): Promise<void>;
|
|
845
|
+
SetRunViewResult(fingerprint: string, params: RunViewParams, results: unknown[], maxUpdatedAt: string, aggregateResults?: AggregateResult[], totalRowCount?: number, provider?: IMetadataProvider, ttlMs?: number, options?: CacheWriteOptions): Promise<void>;
|
|
732
846
|
/**
|
|
733
847
|
* Retrieves a cached RunView result.
|
|
734
848
|
*
|
|
@@ -887,6 +1001,10 @@ export declare class LocalCacheManager extends BaseSingleton<LocalCacheManager>
|
|
|
887
1001
|
* @returns The cached results, maxUpdatedAt, rowCount, and queryId, or null if not found
|
|
888
1002
|
*/
|
|
889
1003
|
GetRunQueryResult(fingerprint: string): Promise<{
|
|
1004
|
+
/**
|
|
1005
|
+
* The cached result rows — shared and deep-frozen under a reference-sharing storage
|
|
1006
|
+
* provider, exactly like {@link CachedRunViewData.results}. Do not mutate.
|
|
1007
|
+
*/
|
|
890
1008
|
results: unknown[];
|
|
891
1009
|
maxUpdatedAt: string;
|
|
892
1010
|
rowCount: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localCacheManager.d.ts","sourceRoot":"","sources":["../../src/generic/localCacheManager.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"localCacheManager.d.ts","sourceRoot":"","sources":["../../src/generic/localCacheManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,50 @@ import { CompositeKey, KeyValuePair } from "./compositeKey.js";
|
|
|
7
7
|
function LogStatusVerbose(message) {
|
|
8
8
|
LogStatusEx({ message, verboseOnly: true });
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Recursively freezes a value that is about to enter the cache, so consumers holding the
|
|
12
|
+
* same reference cannot mutate shared state.
|
|
13
|
+
*
|
|
14
|
+
* Only invoked when the storage provider reports
|
|
15
|
+
* {@link ILocalStorageProvider.SharesReferences} — a serializing backend (IndexedDB,
|
|
16
|
+
* localStorage, Redis, MMKV) already isolates stored data, and freezing there would
|
|
17
|
+
* needlessly immobilize the caller's own rows.
|
|
18
|
+
*
|
|
19
|
+
* Freezing the ARRAY matters as much as the rows: `results.sort()` / `.push()` on a live
|
|
20
|
+
* cache array silently reorders or grows the cached slot for every later reader.
|
|
21
|
+
*
|
|
22
|
+
* Freezes BEFORE recursing, so the `isFrozen` short-circuit both skips already-frozen
|
|
23
|
+
* subtrees (cheap re-entry for in-place slot maintenance, which carries existing rows
|
|
24
|
+
* forward by reference) and terminates cycles.
|
|
25
|
+
*
|
|
26
|
+
* Two value kinds are skipped, not frozen — accepted residuals:
|
|
27
|
+
* - Binary payloads (`Buffer`/TypedArray/`ArrayBuffer`, e.g. `varbinary` columns): the spec
|
|
28
|
+
* makes `Object.freeze` THROW on a non-empty view, so attempting it would turn a cache
|
|
29
|
+
* write into a crash.
|
|
30
|
+
* - `Date` internal slots: `Object.freeze` cannot protect them — `setHours` and friends
|
|
31
|
+
* still work.
|
|
32
|
+
*/
|
|
33
|
+
function deepFreezeCacheValue(value, visited = new WeakSet()) {
|
|
34
|
+
if (value === null || typeof value !== 'object'
|
|
35
|
+
|| ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
// Cycle termination and re-entry short-circuit key off an explicit visited set rather than
|
|
39
|
+
// `Object.isFrozen`. Those are not the same test: an object frozen SHALLOWLY by someone else
|
|
40
|
+
// (a caller that ran `Object.freeze(row)` before handing it over) reports frozen while its
|
|
41
|
+
// nested values are still writable, so keying off isFrozen would skip the whole subtree and
|
|
42
|
+
// leave shared state mutable. Already-frozen objects are cheap to re-freeze; unvisited
|
|
43
|
+
// children are the thing that must not be skipped.
|
|
44
|
+
if (visited.has(value)) {
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
visited.add(value);
|
|
48
|
+
Object.freeze(value);
|
|
49
|
+
for (const nested of Object.values(value)) {
|
|
50
|
+
deepFreezeCacheValue(nested, visited);
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
10
54
|
// ============================================================================
|
|
11
55
|
// DEFAULT CONFIGURATION
|
|
12
56
|
// ============================================================================
|
|
@@ -76,6 +120,12 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
76
120
|
constructor() {
|
|
77
121
|
super();
|
|
78
122
|
this._storageProvider = null;
|
|
123
|
+
/**
|
|
124
|
+
* Whether the active storage provider hands back live object references, resolved once at
|
|
125
|
+
* initialization — from the provider's declared {@link ILocalStorageProvider.SharesReferences}
|
|
126
|
+
* when it states one, otherwise measured empirically. Gates the defensive deep-freeze.
|
|
127
|
+
*/
|
|
128
|
+
this._sharesReferences = false;
|
|
79
129
|
this._registry = new Map();
|
|
80
130
|
this._initialized = false;
|
|
81
131
|
this._initializePromise = null;
|
|
@@ -138,14 +188,64 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
138
188
|
this._initializePromise = this.doInitialize(storageProvider, config);
|
|
139
189
|
return this._initializePromise;
|
|
140
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Decides whether the storage provider hands back live object references — the condition
|
|
193
|
+
* that makes the defensive deep-freeze necessary.
|
|
194
|
+
*
|
|
195
|
+
* Prefers the provider's declared {@link ILocalStorageProvider.SharesReferences}. When a
|
|
196
|
+
* provider does not state one (any implementation written before that property existed),
|
|
197
|
+
* MEASURE it rather than guessing: store a sentinel object, read it back, and compare
|
|
198
|
+
* identity. A reference-sharing store returns the very same object; anything with a
|
|
199
|
+
* serialization or structured-clone boundary returns a copy. This is what keeps the
|
|
200
|
+
* property optional — an external provider that never declares it still gets the correct
|
|
201
|
+
* protection instead of silently losing it to a falsy default.
|
|
202
|
+
*
|
|
203
|
+
* Fails closed to `false` if the probe cannot complete (a provider whose backing store is
|
|
204
|
+
* not ready at init): that matches the pre-freeze behavior rather than immobilizing rows
|
|
205
|
+
* for a provider we could not classify.
|
|
206
|
+
*/
|
|
207
|
+
async resolveSharesReferences(storageProvider) {
|
|
208
|
+
if (typeof storageProvider.SharesReferences === 'boolean') {
|
|
209
|
+
return storageProvider.SharesReferences;
|
|
210
|
+
}
|
|
211
|
+
const probeKey = '__mj_sharesreferences_probe__';
|
|
212
|
+
const sentinel = { probe: true };
|
|
213
|
+
try {
|
|
214
|
+
await storageProvider.SetItem(probeKey, sentinel, CacheCategory.Default);
|
|
215
|
+
const readBack = await storageProvider.GetItem(probeKey, CacheCategory.Default);
|
|
216
|
+
const shares = readBack === sentinel;
|
|
217
|
+
LogStatusVerbose(`[CACHE-INIT] Storage provider "${storageProvider.constructor?.name ?? 'unknown'}" did not declare ` +
|
|
218
|
+
`SharesReferences; probed it as ${shares} (freeze-on-write ${shares ? 'ENABLED' : 'disabled'}).`);
|
|
219
|
+
return shares;
|
|
220
|
+
}
|
|
221
|
+
catch (e) {
|
|
222
|
+
LogError(`LocalCacheManager: could not probe SharesReferences on the storage provider; ` +
|
|
223
|
+
`assuming it isolates (freeze-on-write disabled). Declare SharesReferences to be explicit. ${e}`);
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
try {
|
|
228
|
+
await storageProvider.Remove(probeKey, CacheCategory.Default);
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
/* best-effort cleanup — a leftover probe key is harmless */
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
141
235
|
/**
|
|
142
236
|
* Internal initialization logic - only called once by the first caller
|
|
143
237
|
*/
|
|
144
238
|
async doInitialize(storageProvider, config) {
|
|
145
|
-
this._storageProvider = storageProvider;
|
|
146
239
|
if (config) {
|
|
147
240
|
this._config = { ...this._config, ...config };
|
|
148
241
|
}
|
|
242
|
+
// Resolve the freeze decision BEFORE publishing the provider. The probe awaits I/O, and
|
|
243
|
+
// `_storageProvider` is what every write path reads to decide whether to freeze — so
|
|
244
|
+
// assigning it first opens a window where writes see the new provider paired with the
|
|
245
|
+
// PREVIOUS provider's (or the default `false`) freeze decision. Same ordering bug that
|
|
246
|
+
// `SetStorageProvider` had; fixed here too rather than left as the one asymmetric path.
|
|
247
|
+
this._sharesReferences = await this.resolveSharesReferences(storageProvider);
|
|
248
|
+
this._storageProvider = storageProvider;
|
|
149
249
|
await this.loadRegistry();
|
|
150
250
|
this._initialized = true;
|
|
151
251
|
// Start periodic eviction sweep for TTL-expired entries
|
|
@@ -193,12 +293,24 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
193
293
|
* @param newProvider - The new storage provider to use
|
|
194
294
|
*/
|
|
195
295
|
async SetStorageProvider(newProvider) {
|
|
296
|
+
// The freeze decision belongs to the ACTIVE provider, not to whichever one happened to be
|
|
297
|
+
// installed at Initialize. MJAPI initializes on the in-memory provider during engine
|
|
298
|
+
// loading and swaps to Redis afterward, so these two have OPPOSITE reference semantics on
|
|
299
|
+
// every Redis deployment — carrying the old answer forward means freezing rows Redis has
|
|
300
|
+
// already isolated (all of the hazard, none of the protection), or, on the reverse swap,
|
|
301
|
+
// silently dropping the protection.
|
|
302
|
+
//
|
|
303
|
+
// Resolved BEFORE `_storageProvider` is published in both branches: the probe awaits I/O,
|
|
304
|
+
// and write paths read `_storageProvider` to decide whether to freeze, so publishing first
|
|
305
|
+
// would pair the new provider with the old provider's decision for the duration of the probe.
|
|
196
306
|
if (!this._initialized) {
|
|
197
307
|
// Not yet initialized — just set the provider and return
|
|
308
|
+
this._sharesReferences = await this.resolveSharesReferences(newProvider);
|
|
198
309
|
this._storageProvider = newProvider;
|
|
199
310
|
return;
|
|
200
311
|
}
|
|
201
312
|
const oldProvider = this._storageProvider;
|
|
313
|
+
this._sharesReferences = await this.resolveSharesReferences(newProvider);
|
|
202
314
|
this._storageProvider = newProvider;
|
|
203
315
|
// Migrate existing cached data from old provider to new provider
|
|
204
316
|
const entries = this.GetAllEntries();
|
|
@@ -932,7 +1044,8 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
932
1044
|
*
|
|
933
1045
|
* @param name - The dataset name
|
|
934
1046
|
* @param itemFilters - Optional filters applied to the dataset
|
|
935
|
-
* @param dataset - The dataset result to cache
|
|
1047
|
+
* @param dataset - The dataset result to cache. Deep-frozen on reference-sharing storage,
|
|
1048
|
+
* like every other cache write funnel — see below.
|
|
936
1049
|
* @param keyPrefix - Prefix for the cache key (typically includes connection info)
|
|
937
1050
|
*/
|
|
938
1051
|
async SetDataset(name, itemFilters, dataset, keyPrefix) {
|
|
@@ -942,6 +1055,17 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
942
1055
|
// Estimate size from a string representation (used only for cache eviction
|
|
943
1056
|
// accounting; the actual stored value is the native object).
|
|
944
1057
|
const sizeBytes = this.estimateSize(JSON.stringify(dataset));
|
|
1058
|
+
// Fourth write funnel, held to the same contract as SetRunViewResult /
|
|
1059
|
+
// SetRunQueryResult / storeCachedResults. `GetDataset` hands this object straight back
|
|
1060
|
+
// out, so on a reference-sharing provider every reader shares it — the same exposure the
|
|
1061
|
+
// other three close. It has no in-repo caller today (GetDatasetByName caches per ITEM via
|
|
1062
|
+
// SetRunViewResult), but it is exported public API, so an external caller would otherwise
|
|
1063
|
+
// get an unprotected slot with no indication that it differs from the documented rule.
|
|
1064
|
+
//
|
|
1065
|
+
// Frozen BEFORE the awaited eviction below, for the same reason as the other funnels: a
|
|
1066
|
+
// yield point between the decision to cache and the freeze is a window in which the
|
|
1067
|
+
// caller can still mutate what is about to become shared state.
|
|
1068
|
+
this.freezeRowDataIfProviderSharesReferences(dataset);
|
|
945
1069
|
// Check if we need to evict entries
|
|
946
1070
|
await this.evictIfNeeded(sizeBytes);
|
|
947
1071
|
try {
|
|
@@ -1078,7 +1202,7 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
1078
1202
|
* pre-RLS format so normal cache sharing is preserved and no existing entries are invalidated.
|
|
1079
1203
|
* @returns A unique, human-readable fingerprint string
|
|
1080
1204
|
*/
|
|
1081
|
-
GenerateRunViewFingerprint(params, connectionPrefix, rlsWhereClause) {
|
|
1205
|
+
GenerateRunViewFingerprint(params, connectionPrefix, rlsWhereClause, datasetSegment) {
|
|
1082
1206
|
const entity = params.EntityName?.trim() || 'Unknown';
|
|
1083
1207
|
const rawFilter = params.ExtraFilter;
|
|
1084
1208
|
const filter = (typeof rawFilter === 'string' ? rawFilter : rawFilter ? JSON.stringify(rawFilter) : '').trim();
|
|
@@ -1158,6 +1282,25 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
1158
1282
|
if (viewKey.length > 0) {
|
|
1159
1283
|
parts.push(`vw:${viewKey}`);
|
|
1160
1284
|
}
|
|
1285
|
+
// Dataset namespace. `GetDatasetByName` caches each dataset ITEM's rows through this same
|
|
1286
|
+
// builder, supplying only entity + the item's WhereClause — and every shipped item has a
|
|
1287
|
+
// NULL WhereClause, so without this segment a dataset item emits the identical fingerprint
|
|
1288
|
+
// to a plain unfiltered read of the same entity and the two silently share one slot. That
|
|
1289
|
+
// is not merely a stale-data risk: the MJ_Metadata dataset writes its rows with
|
|
1290
|
+
// `ProviderInternalScaffolding` (deliberately UNFROZEN, because bootstrap rearranges them
|
|
1291
|
+
// in place), so the shared slot hands ordinary callers unprotected rows for the hottest
|
|
1292
|
+
// entities in the process — and, in the other direction, an ordinary read repopulating an
|
|
1293
|
+
// evicted slot stores it FROZEN and the next metadata refresh throws.
|
|
1294
|
+
//
|
|
1295
|
+
// Dataset items may also project columns (`DatasetItem.Columns`), where a RunView slot is
|
|
1296
|
+
// always the full field set — so the two are not interchangeable in shape either.
|
|
1297
|
+
//
|
|
1298
|
+
// Appended ONLY when supplied, so ordinary reads keep their exact pre-existing key and no
|
|
1299
|
+
// existing cache entry is invalidated by this change.
|
|
1300
|
+
const dataset = (datasetSegment ?? '').trim();
|
|
1301
|
+
if (dataset.length > 0) {
|
|
1302
|
+
parts.push(`ds:${dataset}`);
|
|
1303
|
+
}
|
|
1161
1304
|
// Only include connection if provided
|
|
1162
1305
|
if (connection) {
|
|
1163
1306
|
parts.push(connection);
|
|
@@ -1260,6 +1403,64 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
1260
1403
|
return undefined;
|
|
1261
1404
|
}
|
|
1262
1405
|
}
|
|
1406
|
+
/**
|
|
1407
|
+
* Deep-freezes an about-to-be-stored cache payload when — and only when — the active
|
|
1408
|
+
* storage provider hands out live object references
|
|
1409
|
+
* ({@link ILocalStorageProvider.SharesReferences}).
|
|
1410
|
+
*
|
|
1411
|
+
* This is the cache's structural defense against consumer corruption. Under a
|
|
1412
|
+
* reference-sharing provider the rows a caller receives ARE the cached rows, in both
|
|
1413
|
+
* directions: on a hit the reader gets the stored array, and on a miss the cache stored
|
|
1414
|
+
* the caller's own array. Any in-place mutation therefore edits process-wide state. One
|
|
1415
|
+
* such mutation shipped as a P1 (a resolver renamed `__mj_CreatedAt` to its GraphQL
|
|
1416
|
+
* transport alias in place, so every later read served rows `BaseEntity.SetMany`
|
|
1417
|
+
* rejects). Freezing makes that failure immediate and attributable — a `TypeError` at
|
|
1418
|
+
* the offending line — instead of silent corruption, and costs nothing per cache hit.
|
|
1419
|
+
*
|
|
1420
|
+
* On serializing providers this is a no-op: their stored data is already isolated, and
|
|
1421
|
+
* freezing would only immobilize the caller's own rows for no safety gain.
|
|
1422
|
+
*
|
|
1423
|
+
* @param payload - The envelope being handed to the storage provider. Frozen in place;
|
|
1424
|
+
* the same reference is returned for call-site convenience.
|
|
1425
|
+
*/
|
|
1426
|
+
/**
|
|
1427
|
+
* Whether the CURRENTLY-INSTALLED provider hands back live references.
|
|
1428
|
+
*
|
|
1429
|
+
* Prefers the active provider's own declaration, read live on each call — a property read,
|
|
1430
|
+
* so it costs nothing on the write path, and it stays correct no matter how many times the
|
|
1431
|
+
* provider is swapped or which code path does the swapping. `_sharesReferences` (resolved at
|
|
1432
|
+
* `Initialize`/`SetStorageProvider`) is the fallback for providers that declare nothing, where
|
|
1433
|
+
* the answer can only come from the async probe and therefore cannot be recomputed here.
|
|
1434
|
+
*
|
|
1435
|
+
* Belt-and-braces with the re-resolution in {@link SetStorageProvider}: that keeps the probed
|
|
1436
|
+
* value correct across swaps, and this keeps DECLARED providers correct even if some future
|
|
1437
|
+
* swap site forgets to re-resolve.
|
|
1438
|
+
*/
|
|
1439
|
+
activeProviderSharesReferences() {
|
|
1440
|
+
const declared = this._storageProvider?.SharesReferences;
|
|
1441
|
+
return typeof declared === 'boolean' ? declared : this._sharesReferences;
|
|
1442
|
+
}
|
|
1443
|
+
freezeRowDataIfProviderSharesReferences(payload) {
|
|
1444
|
+
if (!this.activeProviderSharesReferences()) {
|
|
1445
|
+
return payload;
|
|
1446
|
+
}
|
|
1447
|
+
try {
|
|
1448
|
+
return deepFreezeCacheValue(payload);
|
|
1449
|
+
}
|
|
1450
|
+
catch (e) {
|
|
1451
|
+
// The freeze is protective, never load-bearing — an exotic value Object.freeze
|
|
1452
|
+
// rejects (beyond the guarded binary kinds) must degrade to a stored write rather
|
|
1453
|
+
// than taking down the read path it defends.
|
|
1454
|
+
//
|
|
1455
|
+
// The payload is PARTIALLY frozen at this point and cannot be un-frozen: the walk
|
|
1456
|
+
// freezes parent-first, so everything visited before the throw is already immutable.
|
|
1457
|
+
// Say that plainly instead of claiming "unfrozen" — an operator debugging a
|
|
1458
|
+
// downstream TypeError needs to know the entry is a mix, not a clean opt-out.
|
|
1459
|
+
LogError(`LocalCacheManager: freeze-on-write failed partway; storing the entry with ` +
|
|
1460
|
+
`whatever was frozen before the failure (partial protection, not none). ${e}`);
|
|
1461
|
+
return payload;
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1263
1464
|
/**
|
|
1264
1465
|
* Stores a RunView result in the cache.
|
|
1265
1466
|
*
|
|
@@ -1276,8 +1477,11 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
1276
1477
|
* AllowCaching gating in multi-provider scenarios (parallel client connections to multiple
|
|
1277
1478
|
* servers). Falls back to `Metadata.Provider` (global default) when omitted, which is fine
|
|
1278
1479
|
* for single-provider apps but wrong when AllowCaching differs across servers.
|
|
1480
|
+
* @param ttlMs - Optional time-based expiry (required for external-data-source entities).
|
|
1481
|
+
* @param options - See {@link CacheWriteOptions}. Pass `{ ProviderInternalScaffolding: true }`
|
|
1482
|
+
* only for slots the writing provider is the sole consumer of.
|
|
1279
1483
|
*/
|
|
1280
|
-
async SetRunViewResult(fingerprint, params, results, maxUpdatedAt, aggregateResults, totalRowCount, provider, ttlMs) {
|
|
1484
|
+
async SetRunViewResult(fingerprint, params, results, maxUpdatedAt, aggregateResults, totalRowCount, provider, ttlMs, options) {
|
|
1281
1485
|
if (!this._storageProvider || !this._config.enabled)
|
|
1282
1486
|
return;
|
|
1283
1487
|
// Keyset (AfterKey) queries are inherently single-use — each call uses a different
|
|
@@ -1336,6 +1540,10 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
1336
1540
|
}
|
|
1337
1541
|
// Persist results, maxUpdatedAt, aggregateResults, totalRowCount, and schemaHash
|
|
1338
1542
|
const data = { results, maxUpdatedAt };
|
|
1543
|
+
if (options?.ProviderInternalScaffolding) {
|
|
1544
|
+
// Persisted so event-driven in-place maintenance carries the exemption forward.
|
|
1545
|
+
data.providerInternalScaffolding = true;
|
|
1546
|
+
}
|
|
1339
1547
|
if (aggregateResults && aggregateResults.length > 0) {
|
|
1340
1548
|
data.aggregateResults = aggregateResults;
|
|
1341
1549
|
}
|
|
@@ -1361,10 +1569,23 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
1361
1569
|
LogStatusEx({ message: `[CACHE-WRITE-GATE] Skipping cache write for "${params.EntityName || fingerprint.substring(0, 60)}" — estimated entry size ${sizeBytes} bytes exceeds per-entry cap (${this._config.maxEntryPercentOfCache}% of ${this._config.maxSizeBytes} byte budget)` });
|
|
1362
1570
|
return;
|
|
1363
1571
|
}
|
|
1364
|
-
//
|
|
1572
|
+
// The oversized gate above is the ONLY step that can decline this write, and it is
|
|
1573
|
+
// synchronous — so by here the row set is definitely becoming shared state, and it is
|
|
1574
|
+
// frozen with no intervening yield point. That ordering is load-bearing: the eviction
|
|
1575
|
+
// steps below are awaited, and callers hold this very array while they run (the
|
|
1576
|
+
// smart-cache stale leg does not await this method at all). Freezing after them leaves
|
|
1577
|
+
// a window in which shared rows are handed out still mutable — and `BaseEntity`
|
|
1578
|
+
// samples `Object.isFrozen` once at load, so a freeze arriving mid-construction makes
|
|
1579
|
+
// a later field READ throw. Declining writes still leave the caller's rows mutable,
|
|
1580
|
+
// because the decline happens before this point.
|
|
1581
|
+
if (!options?.ProviderInternalScaffolding) {
|
|
1582
|
+
this.freezeRowDataIfProviderSharesReferences(data);
|
|
1583
|
+
}
|
|
1584
|
+
// Per-entity memory limit: evict oldest entries for this entity if over budget.
|
|
1585
|
+
// Evicts OTHER entries only — it cannot cancel this write.
|
|
1365
1586
|
const entityName = params.EntityName || 'Unknown';
|
|
1366
1587
|
await this.enforcePerEntityMemoryLimit(entityName, sizeBytes);
|
|
1367
|
-
// Check if we need to evict entries (global budget)
|
|
1588
|
+
// Check if we need to evict entries (global budget). Also eviction-only.
|
|
1368
1589
|
await this.evictIfNeeded(sizeBytes);
|
|
1369
1590
|
try {
|
|
1370
1591
|
// Native object storage — IDB structured-clones, localStorage / Redis serialize internally.
|
|
@@ -1504,6 +1725,8 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
1504
1725
|
totalRowCount: parsed.totalRowCount,
|
|
1505
1726
|
// Surfaced so in-place maintenance can carry it forward on rewrite (B38).
|
|
1506
1727
|
schemaHash: parsed.schemaHash,
|
|
1728
|
+
// Same carry-forward rationale: a maintained scaffolding slot must stay exempt.
|
|
1729
|
+
providerInternalScaffolding: parsed.providerInternalScaffolding,
|
|
1507
1730
|
};
|
|
1508
1731
|
if (parsed.aggregateResults) {
|
|
1509
1732
|
result.aggregateResults = parsed.aggregateResults;
|
|
@@ -1717,7 +1940,8 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
1717
1940
|
// Upsert the entity (add or replace)
|
|
1718
1941
|
resultMap.set(keyStr, entityData);
|
|
1719
1942
|
const updatedResults = Array.from(resultMap.values());
|
|
1720
|
-
return await this.storeCachedResults(fingerprint, updatedResults, newMaxUpdatedAt, { totalRowCount: cached.totalRowCount, rowCount: cached.results.length, schemaHash: cached.schemaHash
|
|
1943
|
+
return await this.storeCachedResults(fingerprint, updatedResults, newMaxUpdatedAt, { totalRowCount: cached.totalRowCount, rowCount: cached.results.length, schemaHash: cached.schemaHash,
|
|
1944
|
+
providerInternalScaffolding: cached.providerInternalScaffolding });
|
|
1721
1945
|
}
|
|
1722
1946
|
catch (e) {
|
|
1723
1947
|
LogError(`LocalCacheManager.UpsertSingleEntity failed: ${e}`);
|
|
@@ -1759,7 +1983,8 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
1759
1983
|
}
|
|
1760
1984
|
resultMap.delete(keyStr);
|
|
1761
1985
|
const updatedResults = Array.from(resultMap.values());
|
|
1762
|
-
return await this.storeCachedResults(fingerprint, updatedResults, newMaxUpdatedAt, { totalRowCount: cached.totalRowCount, rowCount: cached.results.length, schemaHash: cached.schemaHash
|
|
1986
|
+
return await this.storeCachedResults(fingerprint, updatedResults, newMaxUpdatedAt, { totalRowCount: cached.totalRowCount, rowCount: cached.results.length, schemaHash: cached.schemaHash,
|
|
1987
|
+
providerInternalScaffolding: cached.providerInternalScaffolding });
|
|
1763
1988
|
}
|
|
1764
1989
|
catch (e) {
|
|
1765
1990
|
LogError(`LocalCacheManager.RemoveSingleEntity failed: ${e}`);
|
|
@@ -1800,6 +2025,12 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
1800
2025
|
if (prior?.schemaHash) {
|
|
1801
2026
|
data.schemaHash = prior.schemaHash;
|
|
1802
2027
|
}
|
|
2028
|
+
// Carry the freeze exemption forward too — a scaffolding slot that gets maintained in
|
|
2029
|
+
// place must not silently become frozen, or the owner that mutates those rows breaks on
|
|
2030
|
+
// the next read (for the metadata dataset that means booting with no metadata).
|
|
2031
|
+
if (prior?.providerInternalScaffolding) {
|
|
2032
|
+
data.providerInternalScaffolding = true;
|
|
2033
|
+
}
|
|
1803
2034
|
// Aggregates are deliberately NOT carried here — see hasAggregates(): an aggregate-bearing
|
|
1804
2035
|
// slot is invalidated on mutation rather than maintained, so this path never runs for one.
|
|
1805
2036
|
if (prior?.totalRowCount != null) {
|
|
@@ -1810,6 +2041,13 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
1810
2041
|
// value is the native object. This runs on every save/delete event per matching
|
|
1811
2042
|
// unfiltered fingerprint, so avoiding a full serialization here matters most.
|
|
1812
2043
|
const sizeBytes = this.estimateResultsSize(updatedResults);
|
|
2044
|
+
// Second write funnel — this path bypasses SetRunViewResult entirely, so it must
|
|
2045
|
+
// freeze too. Rows carried forward from the prior slot are already frozen (the
|
|
2046
|
+
// isFrozen short-circuit makes re-entry cheap); what this catches is the NEW array
|
|
2047
|
+
// and the freshly upserted row. Scaffolding slots stay exempt (see above).
|
|
2048
|
+
if (!prior?.providerInternalScaffolding) {
|
|
2049
|
+
this.freezeRowDataIfProviderSharesReferences(data);
|
|
2050
|
+
}
|
|
1813
2051
|
await this._storageProvider.SetItem(fingerprint, data, CacheCategory.RunViewCache);
|
|
1814
2052
|
const existingEntry = this._registry.get(fingerprint);
|
|
1815
2053
|
if (existingEntry) {
|
|
@@ -1911,7 +2149,14 @@ export class LocalCacheManager extends BaseSingleton {
|
|
|
1911
2149
|
LogStatusEx({ message: `[CACHE-WRITE-GATE] Skipping cache write for query "${queryName}" — estimated entry size ${sizeBytes} bytes exceeds per-entry cap (${this._config.maxEntryPercentOfCache}% of ${this._config.maxSizeBytes} byte budget)` });
|
|
1912
2150
|
return;
|
|
1913
2151
|
}
|
|
1914
|
-
//
|
|
2152
|
+
// Same reference-sharing exposure as the RunView path (GetRunQueryResult hands
|
|
2153
|
+
// `results` straight back out) — closed here rather than waiting for a mutator to
|
|
2154
|
+
// find it. Placed immediately after the only declining gate and BEFORE the awaited
|
|
2155
|
+
// eviction below, for the same reason as SetRunViewResult: callers of this method do
|
|
2156
|
+
// not always await it, so any yield point before the freeze is a window in which the
|
|
2157
|
+
// caller can still mutate the rows the cache is about to store.
|
|
2158
|
+
this.freezeRowDataIfProviderSharesReferences(data);
|
|
2159
|
+
// Check if we need to evict entries. Evicts OTHER entries only — cannot cancel this write.
|
|
1915
2160
|
await this.evictIfNeeded(sizeBytes);
|
|
1916
2161
|
const now = Date.now();
|
|
1917
2162
|
const expiresAt = ttlMs ? now + ttlMs : undefined;
|