@fjell/cache 4.6.22 → 4.7.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/CACHE_EVENTS.md +306 -0
- package/CACHE_IMPLEMENTATIONS.md +315 -0
- package/CONFIGURATION_GUIDE.md +167 -0
- package/CRITICAL_FIXES.md +68 -0
- package/MEMORY_LEAK_FIXES.md +270 -0
- package/README.md +513 -2
- package/dist/Aggregator.d.ts +27 -16
- package/dist/Cache.d.ts +59 -1
- package/dist/CacheContext.d.ts +35 -0
- package/dist/CacheMap.d.ts +132 -14
- package/dist/CacheStats.d.ts +51 -0
- package/dist/Instance.d.ts +4 -2
- package/dist/InstanceFactory.d.ts +3 -2
- package/dist/Operations.d.ts +21 -17
- package/dist/Options.d.ts +98 -0
- package/dist/browser/AsyncIndexDBCacheMap.d.ts +38 -0
- package/dist/browser/IndexDBCacheMap.d.ts +69 -0
- package/dist/browser/LocalStorageCacheMap.d.ts +59 -0
- package/dist/browser/SessionStorageCacheMap.d.ts +51 -0
- package/dist/events/CacheEventEmitter.d.ts +82 -0
- package/dist/events/CacheEventFactory.d.ts +121 -0
- package/dist/events/CacheEventTypes.d.ts +122 -0
- package/dist/events/index.d.ts +3 -0
- package/dist/eviction/EvictionManager.d.ts +57 -0
- package/dist/eviction/EvictionStrategy.d.ts +142 -0
- package/dist/eviction/EvictionStrategyConfig.d.ts +97 -0
- package/dist/eviction/EvictionStrategyFactory.d.ts +12 -0
- package/dist/eviction/EvictionStrategyValidation.d.ts +36 -0
- package/dist/eviction/index.d.ts +10 -0
- package/dist/eviction/strategies/ARCEvictionStrategy.d.ts +73 -0
- package/dist/eviction/strategies/FIFOEvictionStrategy.d.ts +12 -0
- package/dist/eviction/strategies/LFUEvictionStrategy.d.ts +38 -0
- package/dist/eviction/strategies/LRUEvictionStrategy.d.ts +12 -0
- package/dist/eviction/strategies/MRUEvictionStrategy.d.ts +12 -0
- package/dist/eviction/strategies/RandomEvictionStrategy.d.ts +12 -0
- package/dist/eviction/strategies/TwoQueueEvictionStrategy.d.ts +54 -0
- package/dist/index.d.ts +29 -6
- package/dist/index.js +5764 -435
- package/dist/index.js.map +4 -4
- package/dist/memory/EnhancedMemoryCacheMap.d.ts +81 -0
- package/dist/memory/MemoryCacheMap.d.ts +48 -0
- package/dist/normalization.d.ts +19 -0
- package/dist/ops/action.d.ts +2 -3
- package/dist/ops/all.d.ts +2 -3
- package/dist/ops/allAction.d.ts +2 -3
- package/dist/ops/allFacet.d.ts +2 -3
- package/dist/ops/create.d.ts +2 -3
- package/dist/ops/facet.d.ts +2 -3
- package/dist/ops/find.d.ts +2 -3
- package/dist/ops/findOne.d.ts +2 -3
- package/dist/ops/get.d.ts +3 -3
- package/dist/ops/one.d.ts +2 -3
- package/dist/ops/remove.d.ts +2 -3
- package/dist/ops/reset.d.ts +2 -1
- package/dist/ops/retrieve.d.ts +2 -3
- package/dist/ops/set.d.ts +2 -2
- package/dist/ops/update.d.ts +2 -3
- package/dist/ttl/TTLManager.d.ts +100 -0
- package/dist/ttl/index.d.ts +2 -0
- package/dist/utils/CacheSize.d.ts +30 -0
- package/fix-async-tests.js +116 -0
- package/package.json +16 -13
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { AllItemTypeArrays, ComKey, Item, ItemQuery, LocKeyArray, PriKey } from "@fjell/core";
|
|
2
|
+
import { CacheMap } from "../CacheMap";
|
|
3
|
+
import { CacheItemMetadata } from "../eviction/EvictionStrategy";
|
|
4
|
+
/**
|
|
5
|
+
* SessionStorage implementation of CacheMap for browser environments.
|
|
6
|
+
* Data persists only for the current browser tab/session.
|
|
7
|
+
*
|
|
8
|
+
* Note: SessionStorage has a ~5MB limit and stores strings only.
|
|
9
|
+
* Data is synchronous but is lost when the tab is closed.
|
|
10
|
+
*/
|
|
11
|
+
export declare class SessionStorageCacheMap<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> extends CacheMap<V, S, L1, L2, L3, L4, L5> {
|
|
12
|
+
readonly implementationType = "browser/sessionStorage";
|
|
13
|
+
private keyPrefix;
|
|
14
|
+
private normalizedHashFunction;
|
|
15
|
+
private readonly verificationHashFunction;
|
|
16
|
+
constructor(types: AllItemTypeArrays<S, L1, L2, L3, L4, L5>, keyPrefix?: string);
|
|
17
|
+
private getStorageKey;
|
|
18
|
+
private getAllStorageKeys;
|
|
19
|
+
private hasCollisionForHash;
|
|
20
|
+
get(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<V | null>;
|
|
21
|
+
set(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, value: V): void;
|
|
22
|
+
includesKey(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<boolean>;
|
|
23
|
+
delete(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): void;
|
|
24
|
+
allIn(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
|
|
25
|
+
contains(query: ItemQuery, locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<boolean>;
|
|
26
|
+
queryIn(query: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
|
|
27
|
+
clone(): Promise<SessionStorageCacheMap<V, S, L1, L2, L3, L4, L5>>;
|
|
28
|
+
keys(): (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[];
|
|
29
|
+
values(): Promise<V[]>;
|
|
30
|
+
clear(): void;
|
|
31
|
+
setQueryResult(queryHash: string, itemKeys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): void;
|
|
32
|
+
getQueryResult(queryHash: string): Promise<(ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[] | null>;
|
|
33
|
+
hasQueryResult(queryHash: string): boolean;
|
|
34
|
+
deleteQueryResult(queryHash: string): void;
|
|
35
|
+
invalidateItemKeys(keys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): void;
|
|
36
|
+
invalidateLocation(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<void>;
|
|
37
|
+
clearQueryResults(): void;
|
|
38
|
+
getMetadata(key: string): CacheItemMetadata | null;
|
|
39
|
+
setMetadata(key: string, metadata: CacheItemMetadata): void;
|
|
40
|
+
deleteMetadata(key: string): void;
|
|
41
|
+
getAllMetadata(): Map<string, CacheItemMetadata>;
|
|
42
|
+
clearMetadata(): void;
|
|
43
|
+
getCurrentSize(): {
|
|
44
|
+
itemCount: number;
|
|
45
|
+
sizeBytes: number;
|
|
46
|
+
};
|
|
47
|
+
getSizeLimits(): {
|
|
48
|
+
maxItems: number | null;
|
|
49
|
+
maxSizeBytes: number | null;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Item } from "@fjell/core";
|
|
2
|
+
import { AnyCacheEvent, CacheEventListener, CacheSubscription, CacheSubscriptionOptions } from "./CacheEventTypes";
|
|
3
|
+
/**
|
|
4
|
+
* Cache event emitter that manages subscriptions and event dispatching
|
|
5
|
+
*/
|
|
6
|
+
export declare class CacheEventEmitter<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> {
|
|
7
|
+
private subscriptions;
|
|
8
|
+
private nextSubscriptionId;
|
|
9
|
+
private isDestroyed;
|
|
10
|
+
private cleanupInterval;
|
|
11
|
+
private readonly CLEANUP_INTERVAL_MS;
|
|
12
|
+
private readonly MAX_INACTIVE_TIME_MS;
|
|
13
|
+
private readonly WEAK_REF_ENABLED;
|
|
14
|
+
constructor();
|
|
15
|
+
/**
|
|
16
|
+
* Start periodic cleanup of inactive subscriptions
|
|
17
|
+
*/
|
|
18
|
+
private startPeriodicCleanup;
|
|
19
|
+
/**
|
|
20
|
+
* Perform periodic cleanup of inactive subscriptions
|
|
21
|
+
*/
|
|
22
|
+
private performPeriodicCleanup;
|
|
23
|
+
/**
|
|
24
|
+
* Subscribe to cache events
|
|
25
|
+
*/
|
|
26
|
+
subscribe(listener: CacheEventListener<V, S, L1, L2, L3, L4, L5>, options?: CacheSubscriptionOptions<S, L1, L2, L3, L4, L5>): CacheSubscription;
|
|
27
|
+
/**
|
|
28
|
+
* Unsubscribe from events
|
|
29
|
+
*/
|
|
30
|
+
unsubscribe(subscriptionId: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Emit an event to all matching subscriptions
|
|
33
|
+
*/
|
|
34
|
+
emit(event: AnyCacheEvent<V, S, L1, L2, L3, L4, L5>): void;
|
|
35
|
+
/**
|
|
36
|
+
* Get count of active subscriptions
|
|
37
|
+
*/
|
|
38
|
+
getSubscriptionCount(): number;
|
|
39
|
+
/**
|
|
40
|
+
* Get subscription details (for debugging)
|
|
41
|
+
*/
|
|
42
|
+
getSubscriptions(): Array<{
|
|
43
|
+
id: string;
|
|
44
|
+
options: CacheSubscriptionOptions<S, L1, L2, L3, L4, L5>;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Destroy the event emitter and clean up all subscriptions
|
|
48
|
+
*/
|
|
49
|
+
destroy(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Check if an event should be emitted to a specific subscription
|
|
52
|
+
*/
|
|
53
|
+
private shouldEmitToSubscription;
|
|
54
|
+
/**
|
|
55
|
+
* Emit event to a specific subscription, handling debouncing
|
|
56
|
+
*/
|
|
57
|
+
private emitToSubscription;
|
|
58
|
+
/**
|
|
59
|
+
* Normalize a key for comparison
|
|
60
|
+
*/
|
|
61
|
+
private normalizeKey;
|
|
62
|
+
/**
|
|
63
|
+
* Normalize a location key for comparison
|
|
64
|
+
*/
|
|
65
|
+
private normalizeLocKey;
|
|
66
|
+
/**
|
|
67
|
+
* Check if two location arrays match
|
|
68
|
+
*/
|
|
69
|
+
private locationsMatch;
|
|
70
|
+
/**
|
|
71
|
+
* Check if a key matches location filters
|
|
72
|
+
*/
|
|
73
|
+
private keyMatchesLocations;
|
|
74
|
+
/**
|
|
75
|
+
* Check if two queries match (improved comparison)
|
|
76
|
+
*/
|
|
77
|
+
private queriesMatch;
|
|
78
|
+
/**
|
|
79
|
+
* Handle errors that occur in event listeners
|
|
80
|
+
*/
|
|
81
|
+
private handleListenerError;
|
|
82
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { ComKey, Item, ItemQuery, LocKeyArray, PriKey } from "@fjell/core";
|
|
2
|
+
import { CacheClearedEvent, ItemEvent, LocationInvalidatedEvent, QueryEvent, QueryInvalidatedEvent } from "./CacheEventTypes";
|
|
3
|
+
/**
|
|
4
|
+
* Factory functions for creating cache events
|
|
5
|
+
*/
|
|
6
|
+
export declare class CacheEventFactory {
|
|
7
|
+
private static lastTimestamp;
|
|
8
|
+
private static cleanupInterval;
|
|
9
|
+
private static instanceCount;
|
|
10
|
+
private static readonly CLEANUP_INTERVAL_MS;
|
|
11
|
+
private static readonly MAX_TIMESTAMP_AGE_MS;
|
|
12
|
+
/**
|
|
13
|
+
* Initialize cleanup mechanism when first instance is created
|
|
14
|
+
*/
|
|
15
|
+
private static initializeCleanup;
|
|
16
|
+
/**
|
|
17
|
+
* Cleanup mechanism when instance is destroyed
|
|
18
|
+
*/
|
|
19
|
+
static destroyInstance(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Start automatic cleanup timer
|
|
22
|
+
*/
|
|
23
|
+
private static startCleanupTimer;
|
|
24
|
+
/**
|
|
25
|
+
* Stop automatic cleanup timer
|
|
26
|
+
*/
|
|
27
|
+
private static stopCleanupTimer;
|
|
28
|
+
/**
|
|
29
|
+
* Perform periodic cleanup of stale timestamp state
|
|
30
|
+
*/
|
|
31
|
+
private static performCleanup;
|
|
32
|
+
/**
|
|
33
|
+
* Reset the timestamp state (useful for testing)
|
|
34
|
+
*/
|
|
35
|
+
static resetTimestamp(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Generate a unique timestamp that is always greater than the previous one
|
|
38
|
+
*/
|
|
39
|
+
private static generateTimestamp;
|
|
40
|
+
/**
|
|
41
|
+
* Extract affected locations from an item key
|
|
42
|
+
*/
|
|
43
|
+
private static extractAffectedLocations;
|
|
44
|
+
/**
|
|
45
|
+
* Create an item-related event
|
|
46
|
+
*/
|
|
47
|
+
static createItemEvent<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(type: 'item_created' | 'item_updated' | 'item_removed' | 'item_retrieved' | 'item_set', key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, item: V | null, options?: {
|
|
48
|
+
previousItem?: V | null | null;
|
|
49
|
+
source?: 'api' | 'cache' | 'operation';
|
|
50
|
+
affectedLocations?: LocKeyArray<L1, L2, L3, L4, L5> | [];
|
|
51
|
+
context?: {
|
|
52
|
+
operation?: string;
|
|
53
|
+
requestId?: string;
|
|
54
|
+
userId?: string;
|
|
55
|
+
};
|
|
56
|
+
}): ItemEvent<V, S, L1, L2, L3, L4, L5>;
|
|
57
|
+
/**
|
|
58
|
+
* Create a query event
|
|
59
|
+
*/
|
|
60
|
+
static createQueryEvent<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(query: ItemQuery, locations: LocKeyArray<L1, L2, L3, L4, L5> | [], items: V[], options?: {
|
|
61
|
+
source?: 'api' | 'cache' | 'operation';
|
|
62
|
+
context?: {
|
|
63
|
+
operation?: string;
|
|
64
|
+
requestId?: string;
|
|
65
|
+
userId?: string;
|
|
66
|
+
};
|
|
67
|
+
}): QueryEvent<V, S, L1, L2, L3, L4, L5>;
|
|
68
|
+
/**
|
|
69
|
+
* Create a cache cleared event
|
|
70
|
+
*/
|
|
71
|
+
static createCacheClearedEvent(itemsCleared: number, queryCacheCleared?: boolean, options?: {
|
|
72
|
+
source?: 'api' | 'cache' | 'operation';
|
|
73
|
+
context?: {
|
|
74
|
+
operation?: string;
|
|
75
|
+
requestId?: string;
|
|
76
|
+
userId?: string;
|
|
77
|
+
};
|
|
78
|
+
}): CacheClearedEvent;
|
|
79
|
+
/**
|
|
80
|
+
* Create a location invalidated event
|
|
81
|
+
*/
|
|
82
|
+
static createLocationInvalidatedEvent<S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(locations: LocKeyArray<L1, L2, L3, L4, L5> | [], affectedKeys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[], options?: {
|
|
83
|
+
source?: 'api' | 'cache' | 'operation';
|
|
84
|
+
context?: {
|
|
85
|
+
operation?: string;
|
|
86
|
+
requestId?: string;
|
|
87
|
+
userId?: string;
|
|
88
|
+
};
|
|
89
|
+
}): LocationInvalidatedEvent<S, L1, L2, L3, L4, L5>;
|
|
90
|
+
/**
|
|
91
|
+
* Create a query invalidated event
|
|
92
|
+
*/
|
|
93
|
+
static createQueryInvalidatedEvent(invalidatedQueries: string[], reason: 'manual' | 'item_changed' | 'location_changed' | 'ttl_expired', options?: {
|
|
94
|
+
source?: 'api' | 'cache' | 'operation';
|
|
95
|
+
context?: {
|
|
96
|
+
operation?: string;
|
|
97
|
+
requestId?: string;
|
|
98
|
+
userId?: string;
|
|
99
|
+
};
|
|
100
|
+
}): QueryInvalidatedEvent;
|
|
101
|
+
/**
|
|
102
|
+
* Create an item created event
|
|
103
|
+
*/
|
|
104
|
+
static itemCreated<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, item: V, source?: 'api' | 'cache' | 'operation'): ItemEvent<V, S, L1, L2, L3, L4, L5>;
|
|
105
|
+
/**
|
|
106
|
+
* Create an item updated event
|
|
107
|
+
*/
|
|
108
|
+
static itemUpdated<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, item: V, previousItem?: V | null, source?: 'api' | 'cache' | 'operation'): ItemEvent<V, S, L1, L2, L3, L4, L5>;
|
|
109
|
+
/**
|
|
110
|
+
* Create an item removed event
|
|
111
|
+
*/
|
|
112
|
+
static itemRemoved<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, previousItem?: V | null, source?: 'api' | 'cache' | 'operation'): ItemEvent<V, S, L1, L2, L3, L4, L5>;
|
|
113
|
+
/**
|
|
114
|
+
* Create an item retrieved event
|
|
115
|
+
*/
|
|
116
|
+
static itemRetrieved<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, item: V, source?: 'api' | 'cache' | 'operation'): ItemEvent<V, S, L1, L2, L3, L4, L5>;
|
|
117
|
+
/**
|
|
118
|
+
* Create an item set event (direct cache operation)
|
|
119
|
+
*/
|
|
120
|
+
static itemSet<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, item: V, previousItem?: V | null): ItemEvent<V, S, L1, L2, L3, L4, L5>;
|
|
121
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { ComKey, Item, ItemQuery, LocKeyArray, PriKey } from "@fjell/core";
|
|
2
|
+
/**
|
|
3
|
+
* Types of events that can be emitted by the cache system
|
|
4
|
+
*/
|
|
5
|
+
export type CacheEventType = 'item_created' | 'item_updated' | 'item_removed' | 'item_retrieved' | 'item_set' | 'items_queried' | 'cache_cleared' | 'location_invalidated' | 'query_invalidated';
|
|
6
|
+
/**
|
|
7
|
+
* Base interface for all cache events
|
|
8
|
+
*/
|
|
9
|
+
export interface CacheEvent {
|
|
10
|
+
/** Type of the event */
|
|
11
|
+
type: CacheEventType;
|
|
12
|
+
/** Timestamp when the event occurred */
|
|
13
|
+
timestamp: number;
|
|
14
|
+
/** Source of the event */
|
|
15
|
+
source: 'api' | 'cache' | 'operation';
|
|
16
|
+
/** Optional context about what triggered this event */
|
|
17
|
+
context?: {
|
|
18
|
+
operation?: string;
|
|
19
|
+
requestId?: string;
|
|
20
|
+
userId?: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Event emitted when a single item is affected
|
|
25
|
+
*/
|
|
26
|
+
export interface ItemEvent<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> extends CacheEvent {
|
|
27
|
+
type: 'item_created' | 'item_updated' | 'item_removed' | 'item_retrieved' | 'item_set';
|
|
28
|
+
/** The key of the affected item */
|
|
29
|
+
key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>;
|
|
30
|
+
/** The current item (null for 'item_removed') */
|
|
31
|
+
item: V | null;
|
|
32
|
+
/** The previous item before the change (for updates/removals) */
|
|
33
|
+
previousItem?: V | null;
|
|
34
|
+
/** Locations affected by this change */
|
|
35
|
+
affectedLocations?: LocKeyArray<L1, L2, L3, L4, L5> | [];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Event emitted when multiple items are affected by a query
|
|
39
|
+
*/
|
|
40
|
+
export interface QueryEvent<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> extends CacheEvent {
|
|
41
|
+
type: 'items_queried';
|
|
42
|
+
/** The query that was executed */
|
|
43
|
+
query: ItemQuery;
|
|
44
|
+
/** Locations where the query was executed */
|
|
45
|
+
locations: LocKeyArray<L1, L2, L3, L4, L5> | [];
|
|
46
|
+
/** Items returned by the query */
|
|
47
|
+
items: V[];
|
|
48
|
+
/** Keys of all items affected by this query */
|
|
49
|
+
affectedKeys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Event emitted when the entire cache is cleared
|
|
53
|
+
*/
|
|
54
|
+
export interface CacheClearedEvent extends CacheEvent {
|
|
55
|
+
type: 'cache_cleared';
|
|
56
|
+
/** Number of items that were cleared */
|
|
57
|
+
itemsCleared: number;
|
|
58
|
+
/** Whether query cache was also cleared */
|
|
59
|
+
queryCacheCleared: boolean;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Event emitted when specific locations are invalidated
|
|
63
|
+
*/
|
|
64
|
+
export interface LocationInvalidatedEvent<S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> extends CacheEvent {
|
|
65
|
+
type: 'location_invalidated';
|
|
66
|
+
/** Locations that were invalidated */
|
|
67
|
+
locations: LocKeyArray<L1, L2, L3, L4, L5> | [];
|
|
68
|
+
/** Keys of items that were affected by the invalidation */
|
|
69
|
+
affectedKeys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Event emitted when cached query results are invalidated
|
|
73
|
+
*/
|
|
74
|
+
export interface QueryInvalidatedEvent extends CacheEvent {
|
|
75
|
+
type: 'query_invalidated';
|
|
76
|
+
/** Queries that were invalidated (query hashes) */
|
|
77
|
+
invalidatedQueries: string[];
|
|
78
|
+
/** Reason for invalidation */
|
|
79
|
+
reason: 'manual' | 'item_changed' | 'location_changed' | 'ttl_expired';
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Union type of all possible cache events
|
|
83
|
+
*/
|
|
84
|
+
export type AnyCacheEvent<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> = ItemEvent<V, S, L1, L2, L3, L4, L5> | QueryEvent<V, S, L1, L2, L3, L4, L5> | CacheClearedEvent | LocationInvalidatedEvent<S, L1, L2, L3, L4, L5> | QueryInvalidatedEvent;
|
|
85
|
+
/**
|
|
86
|
+
* Function type for cache event listeners
|
|
87
|
+
*/
|
|
88
|
+
export type CacheEventListener<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> = (event: AnyCacheEvent<V, S, L1, L2, L3, L4, L5>) => void;
|
|
89
|
+
/**
|
|
90
|
+
* Options for subscribing to cache events
|
|
91
|
+
*/
|
|
92
|
+
export interface CacheSubscriptionOptions<S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> {
|
|
93
|
+
/** Only emit events for specific keys */
|
|
94
|
+
keys?: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[];
|
|
95
|
+
/** Only emit events for specific locations */
|
|
96
|
+
locations?: LocKeyArray<L1, L2, L3, L4, L5> | [];
|
|
97
|
+
/** Only emit events matching this query */
|
|
98
|
+
query?: ItemQuery;
|
|
99
|
+
/** Filter by event types */
|
|
100
|
+
eventTypes?: CacheEventType[];
|
|
101
|
+
/** Debounce events by this many milliseconds */
|
|
102
|
+
debounceMs?: number;
|
|
103
|
+
/** Whether to emit events for items that match the subscription criteria */
|
|
104
|
+
includeExistingItems?: boolean;
|
|
105
|
+
/** Optional error handler for listener errors */
|
|
106
|
+
onError?: (error: Error, event: any) => void;
|
|
107
|
+
/** Use weak references for the listener (default: true if WeakRef is available) */
|
|
108
|
+
useWeakRef?: boolean;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Represents an active subscription to cache events
|
|
112
|
+
*/
|
|
113
|
+
export interface CacheSubscription {
|
|
114
|
+
/** Unique identifier for this subscription */
|
|
115
|
+
id: string;
|
|
116
|
+
/** Unsubscribe from events */
|
|
117
|
+
unsubscribe: () => void;
|
|
118
|
+
/** Check if this subscription is still active */
|
|
119
|
+
isActive: () => boolean;
|
|
120
|
+
/** Get subscription options */
|
|
121
|
+
getOptions: () => CacheSubscriptionOptions<any, any, any, any, any, any>;
|
|
122
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { CacheMapMetadataProvider, EvictionStrategy } from './EvictionStrategy';
|
|
2
|
+
/**
|
|
3
|
+
* Manages eviction logic independently of CacheMap implementations.
|
|
4
|
+
* This class coordinates between eviction strategies and cache metadata.
|
|
5
|
+
*/
|
|
6
|
+
export declare class EvictionManager {
|
|
7
|
+
private evictionStrategy;
|
|
8
|
+
constructor(evictionStrategy?: EvictionStrategy);
|
|
9
|
+
/**
|
|
10
|
+
* Set or update the eviction strategy
|
|
11
|
+
* @param strategy - The eviction strategy to use
|
|
12
|
+
*/
|
|
13
|
+
setEvictionStrategy(strategy: EvictionStrategy | null): void;
|
|
14
|
+
/**
|
|
15
|
+
* Get the current eviction strategy name
|
|
16
|
+
* @returns Strategy name or null if no eviction
|
|
17
|
+
*/
|
|
18
|
+
getEvictionStrategyName(): string | null;
|
|
19
|
+
/**
|
|
20
|
+
* Handle item access - update metadata for eviction strategy
|
|
21
|
+
* @param key - Item key
|
|
22
|
+
* @param metadataProvider - Cache metadata provider
|
|
23
|
+
*/
|
|
24
|
+
onItemAccessed(key: string, metadataProvider: CacheMapMetadataProvider): void;
|
|
25
|
+
/**
|
|
26
|
+
* Handle item addition - update metadata and perform eviction if needed
|
|
27
|
+
* @param key - Item key
|
|
28
|
+
* @param value - Item value (for size estimation)
|
|
29
|
+
* @param metadataProvider - Cache metadata provider
|
|
30
|
+
* @returns Array of keys that were evicted
|
|
31
|
+
*/
|
|
32
|
+
onItemAdded<T>(key: string, value: T, metadataProvider: CacheMapMetadataProvider): string[];
|
|
33
|
+
/**
|
|
34
|
+
* Handle item removal - clean up metadata
|
|
35
|
+
* @param key - Item key
|
|
36
|
+
* @param metadataProvider - Cache metadata provider
|
|
37
|
+
*/
|
|
38
|
+
onItemRemoved(key: string, metadataProvider: CacheMapMetadataProvider): void;
|
|
39
|
+
/**
|
|
40
|
+
* Perform manual eviction check
|
|
41
|
+
* @param metadataProvider - Cache metadata provider
|
|
42
|
+
* @returns Array of keys that were evicted
|
|
43
|
+
*/
|
|
44
|
+
performEviction(metadataProvider: CacheMapMetadataProvider): string[];
|
|
45
|
+
/**
|
|
46
|
+
* Check if eviction is supported (i.e., strategy is set)
|
|
47
|
+
* @returns True if eviction is supported
|
|
48
|
+
*/
|
|
49
|
+
isEvictionSupported(): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Create eviction context from current cache state
|
|
52
|
+
* @param metadataProvider - Cache metadata provider
|
|
53
|
+
* @param newItemSize - Size of item being added (optional)
|
|
54
|
+
* @returns Eviction context
|
|
55
|
+
*/
|
|
56
|
+
private createEvictionContext;
|
|
57
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metadata for tracking cache item usage patterns
|
|
3
|
+
*/
|
|
4
|
+
export interface CacheItemMetadata {
|
|
5
|
+
/** When the item was first added to cache */
|
|
6
|
+
addedAt: number;
|
|
7
|
+
/** When the item was last accessed */
|
|
8
|
+
lastAccessedAt: number;
|
|
9
|
+
/** Number of times the item has been accessed */
|
|
10
|
+
accessCount: number;
|
|
11
|
+
/** Estimated size of the item in bytes */
|
|
12
|
+
estimatedSize: number;
|
|
13
|
+
/** Item key for identification */
|
|
14
|
+
key: string;
|
|
15
|
+
/** Frequency score with decay applied (for LFU with sketching) */
|
|
16
|
+
frequencyScore?: number;
|
|
17
|
+
/** Last time frequency was updated (for decay calculations) */
|
|
18
|
+
lastFrequencyUpdate?: number;
|
|
19
|
+
/** Raw frequency count before decay */
|
|
20
|
+
rawFrequency?: number;
|
|
21
|
+
/** Additional strategy-specific metadata */
|
|
22
|
+
strategyData?: {
|
|
23
|
+
[key: string]: any;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Interface for CacheMap implementations to support metadata storage
|
|
28
|
+
* This allows eviction strategies to store and retrieve metadata independently of the storage mechanism
|
|
29
|
+
*/
|
|
30
|
+
export interface CacheMapMetadataProvider {
|
|
31
|
+
/**
|
|
32
|
+
* Get metadata for a specific item
|
|
33
|
+
* @param key - Item key
|
|
34
|
+
* @returns Metadata if exists, null otherwise
|
|
35
|
+
*/
|
|
36
|
+
getMetadata(key: string): CacheItemMetadata | null;
|
|
37
|
+
/**
|
|
38
|
+
* Set metadata for a specific item
|
|
39
|
+
* @param key - Item key
|
|
40
|
+
* @param metadata - Metadata to store
|
|
41
|
+
*/
|
|
42
|
+
setMetadata(key: string, metadata: CacheItemMetadata): void;
|
|
43
|
+
/**
|
|
44
|
+
* Delete metadata for a specific item
|
|
45
|
+
* @param key - Item key
|
|
46
|
+
*/
|
|
47
|
+
deleteMetadata(key: string): void;
|
|
48
|
+
/**
|
|
49
|
+
* Get all metadata entries
|
|
50
|
+
* @returns Map of all metadata entries
|
|
51
|
+
*/
|
|
52
|
+
getAllMetadata(): Map<string, CacheItemMetadata>;
|
|
53
|
+
/**
|
|
54
|
+
* Clear all metadata
|
|
55
|
+
*/
|
|
56
|
+
clearMetadata(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Get current cache size information
|
|
59
|
+
* @returns Object with current size metrics
|
|
60
|
+
*/
|
|
61
|
+
getCurrentSize(): {
|
|
62
|
+
itemCount: number;
|
|
63
|
+
sizeBytes: number;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Get cache size limits
|
|
67
|
+
* @returns Object with size limits (null means unlimited)
|
|
68
|
+
*/
|
|
69
|
+
getSizeLimits(): {
|
|
70
|
+
maxItems: number | null;
|
|
71
|
+
maxSizeBytes: number | null;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Context provided to eviction strategies for decision making
|
|
76
|
+
*/
|
|
77
|
+
export interface EvictionContext {
|
|
78
|
+
/** Current cache size information */
|
|
79
|
+
currentSize: {
|
|
80
|
+
itemCount: number;
|
|
81
|
+
sizeBytes: number;
|
|
82
|
+
};
|
|
83
|
+
/** Cache size limits */
|
|
84
|
+
limits: {
|
|
85
|
+
maxItems: number | null;
|
|
86
|
+
maxSizeBytes: number | null;
|
|
87
|
+
};
|
|
88
|
+
/** Size of the item being added (for proactive eviction) */
|
|
89
|
+
newItemSize?: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Abstract base class for cache eviction strategies.
|
|
93
|
+
* Defines the core contract that all eviction policies must implement.
|
|
94
|
+
*
|
|
95
|
+
* Eviction strategies are now completely independent of CacheMap implementations
|
|
96
|
+
* and interact through the CacheMapMetadataProvider interface.
|
|
97
|
+
*/
|
|
98
|
+
export declare abstract class EvictionStrategy {
|
|
99
|
+
/**
|
|
100
|
+
* Select which items should be evicted based on the strategy and context
|
|
101
|
+
* @param metadataProvider - Provider for accessing cache metadata
|
|
102
|
+
* @param context - Current cache state and limits
|
|
103
|
+
* @returns Array of keys to evict (empty array if no eviction needed)
|
|
104
|
+
*/
|
|
105
|
+
abstract selectForEviction(metadataProvider: CacheMapMetadataProvider, context: EvictionContext): string[];
|
|
106
|
+
/**
|
|
107
|
+
* Update metadata when an item is accessed
|
|
108
|
+
* @param key - Item key
|
|
109
|
+
* @param metadataProvider - Provider for accessing cache metadata
|
|
110
|
+
*/
|
|
111
|
+
abstract onItemAccessed(key: string, metadataProvider: CacheMapMetadataProvider): void;
|
|
112
|
+
/**
|
|
113
|
+
* Update metadata when an item is added
|
|
114
|
+
* @param key - Item key
|
|
115
|
+
* @param estimatedSize - Estimated size of the item in bytes
|
|
116
|
+
* @param metadataProvider - Provider for accessing cache metadata
|
|
117
|
+
*/
|
|
118
|
+
abstract onItemAdded(key: string, estimatedSize: number, metadataProvider: CacheMapMetadataProvider): void;
|
|
119
|
+
/**
|
|
120
|
+
* Clean up when an item is removed
|
|
121
|
+
* @param key - Item key
|
|
122
|
+
* @param metadataProvider - Provider for accessing cache metadata
|
|
123
|
+
*/
|
|
124
|
+
abstract onItemRemoved(key: string, metadataProvider: CacheMapMetadataProvider): void;
|
|
125
|
+
/**
|
|
126
|
+
* Get the name/identifier of this eviction strategy
|
|
127
|
+
* @returns String identifier for the strategy
|
|
128
|
+
*/
|
|
129
|
+
abstract getStrategyName(): string;
|
|
130
|
+
/**
|
|
131
|
+
* Determine if eviction is needed based on current context
|
|
132
|
+
* @param context - Current cache state and limits
|
|
133
|
+
* @returns True if eviction should occur
|
|
134
|
+
*/
|
|
135
|
+
protected isEvictionNeeded(context: EvictionContext): boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Calculate how many items need to be evicted
|
|
138
|
+
* @param context - Current cache state and limits
|
|
139
|
+
* @returns Number of items that should be evicted
|
|
140
|
+
*/
|
|
141
|
+
protected calculateEvictionCount(context: EvictionContext): number;
|
|
142
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base configuration interface for eviction strategies
|
|
3
|
+
*/
|
|
4
|
+
export interface EvictionStrategyConfig {
|
|
5
|
+
/** Strategy type identifier */
|
|
6
|
+
readonly type: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Configuration for LFU eviction strategy with frequency sketching
|
|
10
|
+
*/
|
|
11
|
+
export interface LFUConfig extends EvictionStrategyConfig {
|
|
12
|
+
readonly type: 'lfu';
|
|
13
|
+
/** Decay factor for aging frequency counts (0.0 to 1.0, default: 0.1) */
|
|
14
|
+
decayFactor?: number;
|
|
15
|
+
/** Frequency decay interval in milliseconds (default: 60000) */
|
|
16
|
+
decayInterval?: number;
|
|
17
|
+
/** Width of the Count-Min Sketch (default: 1024) */
|
|
18
|
+
sketchWidth?: number;
|
|
19
|
+
/** Depth of the Count-Min Sketch (default: 4) */
|
|
20
|
+
sketchDepth?: number;
|
|
21
|
+
/** Whether to use probabilistic counting (default: true) */
|
|
22
|
+
useProbabilisticCounting?: boolean;
|
|
23
|
+
/** Minimum frequency threshold before decay (default: 1) */
|
|
24
|
+
minFrequencyThreshold?: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Configuration for LRU eviction strategy
|
|
28
|
+
*/
|
|
29
|
+
export interface LRUConfig extends EvictionStrategyConfig {
|
|
30
|
+
readonly type: 'lru';
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Configuration for FIFO eviction strategy
|
|
34
|
+
*/
|
|
35
|
+
export interface FIFOConfig extends EvictionStrategyConfig {
|
|
36
|
+
readonly type: 'fifo';
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Configuration for MRU eviction strategy
|
|
40
|
+
*/
|
|
41
|
+
export interface MRUConfig extends EvictionStrategyConfig {
|
|
42
|
+
readonly type: 'mru';
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Configuration for Random eviction strategy
|
|
46
|
+
*/
|
|
47
|
+
export interface RandomConfig extends EvictionStrategyConfig {
|
|
48
|
+
readonly type: 'random';
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Configuration for ARC eviction strategy
|
|
52
|
+
*/
|
|
53
|
+
export interface ARCConfig extends EvictionStrategyConfig {
|
|
54
|
+
readonly type: 'arc';
|
|
55
|
+
/** Maximum cache size for ARC calculations */
|
|
56
|
+
maxCacheSize?: number;
|
|
57
|
+
/** Frequency threshold for classifying items as "frequent" vs "recent" (default: 2) */
|
|
58
|
+
frequencyThreshold?: number;
|
|
59
|
+
/** Use enhanced frequency tracking with decay (default: true) */
|
|
60
|
+
useEnhancedFrequency?: boolean;
|
|
61
|
+
/** Decay factor for aging frequency scores (default: 0.05) */
|
|
62
|
+
frequencyDecayFactor?: number;
|
|
63
|
+
/** Decay interval for frequency scores (default: 600000 - 10 minutes) */
|
|
64
|
+
frequencyDecayInterval?: number;
|
|
65
|
+
/** Use frequency-weighted selection within T1/T2 lists (default: true) */
|
|
66
|
+
useFrequencyWeightedSelection?: boolean;
|
|
67
|
+
/** Adaptive learning rate for target size adjustments (default: 1.0) */
|
|
68
|
+
adaptiveLearningRate?: number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Configuration for 2Q eviction strategy
|
|
72
|
+
*/
|
|
73
|
+
export interface TwoQueueConfig extends EvictionStrategyConfig {
|
|
74
|
+
readonly type: '2q';
|
|
75
|
+
/** Maximum cache size for 2Q calculations */
|
|
76
|
+
maxCacheSize?: number;
|
|
77
|
+
/** Use frequency-based promotion from recent to hot queue (default: true) */
|
|
78
|
+
useFrequencyPromotion?: boolean;
|
|
79
|
+
/** Minimum access frequency required for promotion to hot queue (default: 2) */
|
|
80
|
+
promotionThreshold?: number;
|
|
81
|
+
/** Decay factor for aging frequency scores in hot queue (default: 0.05) */
|
|
82
|
+
hotQueueDecayFactor?: number;
|
|
83
|
+
/** Decay interval for hot queue frequency scores (default: 300000 - 5 minutes) */
|
|
84
|
+
hotQueueDecayInterval?: number;
|
|
85
|
+
/** Use frequency-weighted LRU in hot queue instead of pure LRU (default: true) */
|
|
86
|
+
useFrequencyWeightedLRU?: boolean;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Union type for all eviction strategy configurations
|
|
90
|
+
*/
|
|
91
|
+
export type EvictionStrategyConfigs = LFUConfig | LRUConfig | FIFOConfig | MRUConfig | RandomConfig | ARCConfig | TwoQueueConfig;
|
|
92
|
+
/**
|
|
93
|
+
* Default configuration values
|
|
94
|
+
*/
|
|
95
|
+
export declare const DEFAULT_LFU_CONFIG: LFUConfig;
|
|
96
|
+
export declare const DEFAULT_ARC_CONFIG: ARCConfig;
|
|
97
|
+
export declare const DEFAULT_TWO_QUEUE_CONFIG: TwoQueueConfig;
|