flongo 1.0.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cache/cacheConfig.d.ts +62 -0
- package/dist/cache/cacheConfig.js +239 -0
- package/dist/cache/cacheKeyGenerator.d.ts +30 -0
- package/dist/cache/cacheKeyGenerator.js +147 -0
- package/dist/cache/cacheStats.d.ts +69 -0
- package/dist/cache/cacheStats.js +227 -0
- package/dist/cache/cacheStore.d.ts +50 -0
- package/dist/cache/cacheStore.js +57 -0
- package/dist/cache/cacheStrategies.d.ts +61 -0
- package/dist/cache/cacheStrategies.js +229 -0
- package/dist/cache/index.d.ts +7 -0
- package/dist/cache/index.js +25 -0
- package/dist/cache/memoryCache.d.ts +39 -0
- package/dist/cache/memoryCache.js +295 -0
- package/dist/flongoQuery.d.ts +28 -0
- package/dist/flongoQuery.js +49 -5
- package/dist/index.d.ts +2 -1
- package/dist/index.js +18 -1
- package/dist/types.d.ts +17 -0
- package/package.json +1 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { InvalidationStrategy } from './cacheStrategies';
|
|
2
|
+
import { ICollectionQuery, Pagination } from '../types';
|
|
3
|
+
export interface WarmupQuery {
|
|
4
|
+
collection: string;
|
|
5
|
+
operation: string;
|
|
6
|
+
query?: ICollectionQuery;
|
|
7
|
+
pagination?: Pagination;
|
|
8
|
+
}
|
|
9
|
+
export interface CacheProviderConfig {
|
|
10
|
+
type: 'memory' | 'redis' | 'memcached' | 'custom';
|
|
11
|
+
connectionString?: string;
|
|
12
|
+
options?: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
export interface CacheConfig {
|
|
15
|
+
enabled: boolean;
|
|
16
|
+
provider: CacheProviderConfig;
|
|
17
|
+
maxEntries: number;
|
|
18
|
+
maxMemoryMB: number;
|
|
19
|
+
defaultTTL: number;
|
|
20
|
+
checkInterval: number;
|
|
21
|
+
enableStats: boolean;
|
|
22
|
+
invalidationStrategy: InvalidationStrategy;
|
|
23
|
+
customTTLs?: Record<string, number>;
|
|
24
|
+
warmupQueries?: WarmupQuery[];
|
|
25
|
+
debug?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare class CacheConfiguration {
|
|
28
|
+
private static defaultConfig;
|
|
29
|
+
private config;
|
|
30
|
+
constructor(config?: Partial<CacheConfig>);
|
|
31
|
+
private mergeConfig;
|
|
32
|
+
get enabled(): boolean;
|
|
33
|
+
get providerType(): string;
|
|
34
|
+
get providerOptions(): Record<string, unknown> | undefined;
|
|
35
|
+
get connectionString(): string | undefined;
|
|
36
|
+
get maxEntries(): number;
|
|
37
|
+
get maxMemoryMB(): number;
|
|
38
|
+
get defaultTTL(): number;
|
|
39
|
+
get checkInterval(): number;
|
|
40
|
+
get enableStats(): boolean;
|
|
41
|
+
get invalidationStrategy(): InvalidationStrategy;
|
|
42
|
+
get customTTLs(): Record<string, number> | undefined;
|
|
43
|
+
get warmupQueries(): WarmupQuery[] | undefined;
|
|
44
|
+
get debug(): boolean;
|
|
45
|
+
setEnabled(enabled: boolean): void;
|
|
46
|
+
setProvider(provider: CacheProviderConfig): void;
|
|
47
|
+
setMaxEntries(max: number): void;
|
|
48
|
+
setMaxMemoryMB(max: number): void;
|
|
49
|
+
setDefaultTTL(ttl: number): void;
|
|
50
|
+
setCheckInterval(interval: number): void;
|
|
51
|
+
setInvalidationStrategy(strategy: InvalidationStrategy): void;
|
|
52
|
+
setCustomTTL(pattern: string, ttl: number): void;
|
|
53
|
+
addWarmupQuery(query: WarmupQuery): void;
|
|
54
|
+
setDebug(debug: boolean): void;
|
|
55
|
+
toJSON(): CacheConfig;
|
|
56
|
+
static fromEnvironment(): CacheConfiguration;
|
|
57
|
+
validate(): string[];
|
|
58
|
+
}
|
|
59
|
+
export declare function createDefaultConfig(): CacheConfig;
|
|
60
|
+
export declare function createProductionConfig(): CacheConfig;
|
|
61
|
+
export declare function createDevelopmentConfig(): CacheConfig;
|
|
62
|
+
//# sourceMappingURL=cacheConfig.d.ts.map
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CacheConfiguration = void 0;
|
|
4
|
+
exports.createDefaultConfig = createDefaultConfig;
|
|
5
|
+
exports.createProductionConfig = createProductionConfig;
|
|
6
|
+
exports.createDevelopmentConfig = createDevelopmentConfig;
|
|
7
|
+
const cacheStrategies_1 = require("./cacheStrategies");
|
|
8
|
+
class CacheConfiguration {
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.config = this.mergeConfig(config);
|
|
11
|
+
}
|
|
12
|
+
mergeConfig(userConfig) {
|
|
13
|
+
if (!userConfig) {
|
|
14
|
+
return { ...CacheConfiguration.defaultConfig };
|
|
15
|
+
}
|
|
16
|
+
const merged = {
|
|
17
|
+
...CacheConfiguration.defaultConfig,
|
|
18
|
+
...userConfig
|
|
19
|
+
};
|
|
20
|
+
if (userConfig.provider) {
|
|
21
|
+
merged.provider = {
|
|
22
|
+
...CacheConfiguration.defaultConfig.provider,
|
|
23
|
+
...userConfig.provider
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
if (userConfig.customTTLs) {
|
|
27
|
+
merged.customTTLs = { ...userConfig.customTTLs };
|
|
28
|
+
}
|
|
29
|
+
if (userConfig.warmupQueries) {
|
|
30
|
+
merged.warmupQueries = [...userConfig.warmupQueries];
|
|
31
|
+
}
|
|
32
|
+
return merged;
|
|
33
|
+
}
|
|
34
|
+
get enabled() {
|
|
35
|
+
return this.config.enabled;
|
|
36
|
+
}
|
|
37
|
+
get providerType() {
|
|
38
|
+
return this.config.provider.type;
|
|
39
|
+
}
|
|
40
|
+
get providerOptions() {
|
|
41
|
+
return this.config.provider.options;
|
|
42
|
+
}
|
|
43
|
+
get connectionString() {
|
|
44
|
+
return this.config.provider.connectionString;
|
|
45
|
+
}
|
|
46
|
+
get maxEntries() {
|
|
47
|
+
return this.config.maxEntries;
|
|
48
|
+
}
|
|
49
|
+
get maxMemoryMB() {
|
|
50
|
+
return this.config.maxMemoryMB;
|
|
51
|
+
}
|
|
52
|
+
get defaultTTL() {
|
|
53
|
+
return this.config.defaultTTL;
|
|
54
|
+
}
|
|
55
|
+
get checkInterval() {
|
|
56
|
+
return this.config.checkInterval;
|
|
57
|
+
}
|
|
58
|
+
get enableStats() {
|
|
59
|
+
return this.config.enableStats;
|
|
60
|
+
}
|
|
61
|
+
get invalidationStrategy() {
|
|
62
|
+
return this.config.invalidationStrategy;
|
|
63
|
+
}
|
|
64
|
+
get customTTLs() {
|
|
65
|
+
return this.config.customTTLs;
|
|
66
|
+
}
|
|
67
|
+
get warmupQueries() {
|
|
68
|
+
return this.config.warmupQueries;
|
|
69
|
+
}
|
|
70
|
+
get debug() {
|
|
71
|
+
return this.config.debug || false;
|
|
72
|
+
}
|
|
73
|
+
setEnabled(enabled) {
|
|
74
|
+
this.config.enabled = enabled;
|
|
75
|
+
}
|
|
76
|
+
setProvider(provider) {
|
|
77
|
+
this.config.provider = provider;
|
|
78
|
+
}
|
|
79
|
+
setMaxEntries(max) {
|
|
80
|
+
if (max <= 0) {
|
|
81
|
+
throw new Error('maxEntries must be greater than 0');
|
|
82
|
+
}
|
|
83
|
+
this.config.maxEntries = max;
|
|
84
|
+
}
|
|
85
|
+
setMaxMemoryMB(max) {
|
|
86
|
+
if (max <= 0) {
|
|
87
|
+
throw new Error('maxMemoryMB must be greater than 0');
|
|
88
|
+
}
|
|
89
|
+
this.config.maxMemoryMB = max;
|
|
90
|
+
}
|
|
91
|
+
setDefaultTTL(ttl) {
|
|
92
|
+
if (ttl < 0) {
|
|
93
|
+
throw new Error('defaultTTL must be non-negative');
|
|
94
|
+
}
|
|
95
|
+
this.config.defaultTTL = ttl;
|
|
96
|
+
}
|
|
97
|
+
setCheckInterval(interval) {
|
|
98
|
+
if (interval < 0) {
|
|
99
|
+
throw new Error('checkInterval must be non-negative');
|
|
100
|
+
}
|
|
101
|
+
this.config.checkInterval = interval;
|
|
102
|
+
}
|
|
103
|
+
setInvalidationStrategy(strategy) {
|
|
104
|
+
this.config.invalidationStrategy = strategy;
|
|
105
|
+
}
|
|
106
|
+
setCustomTTL(pattern, ttl) {
|
|
107
|
+
if (!this.config.customTTLs) {
|
|
108
|
+
this.config.customTTLs = {};
|
|
109
|
+
}
|
|
110
|
+
this.config.customTTLs[pattern] = ttl;
|
|
111
|
+
}
|
|
112
|
+
addWarmupQuery(query) {
|
|
113
|
+
if (!this.config.warmupQueries) {
|
|
114
|
+
this.config.warmupQueries = [];
|
|
115
|
+
}
|
|
116
|
+
this.config.warmupQueries.push(query);
|
|
117
|
+
}
|
|
118
|
+
setDebug(debug) {
|
|
119
|
+
this.config.debug = debug;
|
|
120
|
+
}
|
|
121
|
+
toJSON() {
|
|
122
|
+
return { ...this.config };
|
|
123
|
+
}
|
|
124
|
+
static fromEnvironment() {
|
|
125
|
+
const config = {};
|
|
126
|
+
if (process.env.FLONGO_CACHE_ENABLED) {
|
|
127
|
+
config.enabled = process.env.FLONGO_CACHE_ENABLED === 'true';
|
|
128
|
+
}
|
|
129
|
+
if (process.env.FLONGO_CACHE_PROVIDER) {
|
|
130
|
+
config.provider = {
|
|
131
|
+
type: process.env.FLONGO_CACHE_PROVIDER
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
if (process.env.FLONGO_CACHE_CONNECTION) {
|
|
135
|
+
if (!config.provider) {
|
|
136
|
+
config.provider = { type: 'redis' };
|
|
137
|
+
}
|
|
138
|
+
config.provider.connectionString = process.env.FLONGO_CACHE_CONNECTION;
|
|
139
|
+
}
|
|
140
|
+
if (process.env.FLONGO_CACHE_MAX_ENTRIES) {
|
|
141
|
+
config.maxEntries = parseInt(process.env.FLONGO_CACHE_MAX_ENTRIES, 10);
|
|
142
|
+
}
|
|
143
|
+
if (process.env.FLONGO_CACHE_MAX_MEMORY_MB) {
|
|
144
|
+
config.maxMemoryMB = parseInt(process.env.FLONGO_CACHE_MAX_MEMORY_MB, 10);
|
|
145
|
+
}
|
|
146
|
+
if (process.env.FLONGO_CACHE_DEFAULT_TTL) {
|
|
147
|
+
config.defaultTTL = parseInt(process.env.FLONGO_CACHE_DEFAULT_TTL, 10);
|
|
148
|
+
}
|
|
149
|
+
if (process.env.FLONGO_CACHE_CHECK_INTERVAL) {
|
|
150
|
+
config.checkInterval = parseInt(process.env.FLONGO_CACHE_CHECK_INTERVAL, 10);
|
|
151
|
+
}
|
|
152
|
+
if (process.env.FLONGO_CACHE_ENABLE_STATS) {
|
|
153
|
+
config.enableStats = process.env.FLONGO_CACHE_ENABLE_STATS === 'true';
|
|
154
|
+
}
|
|
155
|
+
if (process.env.FLONGO_CACHE_INVALIDATION_STRATEGY) {
|
|
156
|
+
config.invalidationStrategy = process.env.FLONGO_CACHE_INVALIDATION_STRATEGY;
|
|
157
|
+
}
|
|
158
|
+
if (process.env.FLONGO_CACHE_DEBUG) {
|
|
159
|
+
config.debug = process.env.FLONGO_CACHE_DEBUG === 'true';
|
|
160
|
+
}
|
|
161
|
+
return new CacheConfiguration(config);
|
|
162
|
+
}
|
|
163
|
+
validate() {
|
|
164
|
+
const errors = [];
|
|
165
|
+
if (this.config.maxEntries <= 0) {
|
|
166
|
+
errors.push('maxEntries must be greater than 0');
|
|
167
|
+
}
|
|
168
|
+
if (this.config.maxMemoryMB <= 0) {
|
|
169
|
+
errors.push('maxMemoryMB must be greater than 0');
|
|
170
|
+
}
|
|
171
|
+
if (this.config.defaultTTL < 0) {
|
|
172
|
+
errors.push('defaultTTL must be non-negative');
|
|
173
|
+
}
|
|
174
|
+
if (this.config.checkInterval < 0) {
|
|
175
|
+
errors.push('checkInterval must be non-negative');
|
|
176
|
+
}
|
|
177
|
+
const validProviders = ['memory', 'redis', 'memcached', 'custom'];
|
|
178
|
+
if (!validProviders.includes(this.config.provider.type)) {
|
|
179
|
+
errors.push(`Invalid provider type: ${this.config.provider.type}`);
|
|
180
|
+
}
|
|
181
|
+
if (this.config.provider.type === 'redis' || this.config.provider.type === 'memcached') {
|
|
182
|
+
if (!this.config.provider.connectionString) {
|
|
183
|
+
errors.push(`Connection string required for ${this.config.provider.type} provider`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const validStrategies = Object.values(cacheStrategies_1.InvalidationStrategy);
|
|
187
|
+
if (!validStrategies.includes(this.config.invalidationStrategy)) {
|
|
188
|
+
errors.push(`Invalid invalidation strategy: ${this.config.invalidationStrategy}`);
|
|
189
|
+
}
|
|
190
|
+
return errors;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
exports.CacheConfiguration = CacheConfiguration;
|
|
194
|
+
CacheConfiguration.defaultConfig = {
|
|
195
|
+
enabled: false,
|
|
196
|
+
provider: {
|
|
197
|
+
type: 'memory'
|
|
198
|
+
},
|
|
199
|
+
maxEntries: 10000,
|
|
200
|
+
maxMemoryMB: 100,
|
|
201
|
+
defaultTTL: 300,
|
|
202
|
+
checkInterval: 60,
|
|
203
|
+
enableStats: true,
|
|
204
|
+
invalidationStrategy: cacheStrategies_1.InvalidationStrategy.Smart,
|
|
205
|
+
debug: false
|
|
206
|
+
};
|
|
207
|
+
function createDefaultConfig() {
|
|
208
|
+
return new CacheConfiguration().toJSON();
|
|
209
|
+
}
|
|
210
|
+
function createProductionConfig() {
|
|
211
|
+
return new CacheConfiguration({
|
|
212
|
+
enabled: true,
|
|
213
|
+
provider: {
|
|
214
|
+
type: 'memory'
|
|
215
|
+
},
|
|
216
|
+
maxEntries: 50000,
|
|
217
|
+
maxMemoryMB: 500,
|
|
218
|
+
defaultTTL: 600,
|
|
219
|
+
checkInterval: 120,
|
|
220
|
+
enableStats: true,
|
|
221
|
+
invalidationStrategy: cacheStrategies_1.InvalidationStrategy.Smart
|
|
222
|
+
}).toJSON();
|
|
223
|
+
}
|
|
224
|
+
function createDevelopmentConfig() {
|
|
225
|
+
return new CacheConfiguration({
|
|
226
|
+
enabled: true,
|
|
227
|
+
provider: {
|
|
228
|
+
type: 'memory'
|
|
229
|
+
},
|
|
230
|
+
maxEntries: 1000,
|
|
231
|
+
maxMemoryMB: 50,
|
|
232
|
+
defaultTTL: 60,
|
|
233
|
+
checkInterval: 30,
|
|
234
|
+
enableStats: true,
|
|
235
|
+
invalidationStrategy: cacheStrategies_1.InvalidationStrategy.Smart,
|
|
236
|
+
debug: true
|
|
237
|
+
}).toJSON();
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=cacheConfig.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ICollectionQuery, Pagination } from '../types';
|
|
2
|
+
export interface CacheKeyOptions {
|
|
3
|
+
collection: string;
|
|
4
|
+
operation: string;
|
|
5
|
+
query?: ICollectionQuery;
|
|
6
|
+
id?: string;
|
|
7
|
+
pagination?: Pagination;
|
|
8
|
+
additionalParams?: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
export declare class CacheKeyGenerator {
|
|
11
|
+
private static readonly SEPARATOR;
|
|
12
|
+
private static readonly NULL_VALUE;
|
|
13
|
+
private static readonly UNDEFINED_VALUE;
|
|
14
|
+
static generate(options: CacheKeyOptions): string;
|
|
15
|
+
static generatePattern(collection: string, operation?: string): string;
|
|
16
|
+
private static hashQuery;
|
|
17
|
+
private static normalizeQuery;
|
|
18
|
+
private static normalizeValue;
|
|
19
|
+
private static hashObject;
|
|
20
|
+
private static hash;
|
|
21
|
+
static parseKey(key: string): {
|
|
22
|
+
collection?: string;
|
|
23
|
+
operation?: string;
|
|
24
|
+
identifier?: string;
|
|
25
|
+
};
|
|
26
|
+
static isFlongoKey(key: string): boolean;
|
|
27
|
+
static getCollectionFromKey(key: string): string | undefined;
|
|
28
|
+
static getOperationFromKey(key: string): string | undefined;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=cacheKeyGenerator.d.ts.map
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CacheKeyGenerator = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const types_1 = require("../types");
|
|
6
|
+
class CacheKeyGenerator {
|
|
7
|
+
static generate(options) {
|
|
8
|
+
const parts = [
|
|
9
|
+
'flongo',
|
|
10
|
+
options.collection,
|
|
11
|
+
options.operation
|
|
12
|
+
];
|
|
13
|
+
if (options.id) {
|
|
14
|
+
parts.push(options.id);
|
|
15
|
+
return parts.join(this.SEPARATOR);
|
|
16
|
+
}
|
|
17
|
+
if (options.query) {
|
|
18
|
+
const queryHash = this.hashQuery(options.query);
|
|
19
|
+
parts.push(queryHash);
|
|
20
|
+
}
|
|
21
|
+
if (options.pagination) {
|
|
22
|
+
parts.push(`p${options.pagination.offset}-${options.pagination.count}`);
|
|
23
|
+
}
|
|
24
|
+
if (options.additionalParams) {
|
|
25
|
+
const paramsHash = this.hashObject(options.additionalParams);
|
|
26
|
+
parts.push(paramsHash);
|
|
27
|
+
}
|
|
28
|
+
return parts.join(this.SEPARATOR);
|
|
29
|
+
}
|
|
30
|
+
static generatePattern(collection, operation) {
|
|
31
|
+
const parts = ['flongo', collection];
|
|
32
|
+
if (operation) {
|
|
33
|
+
parts.push(operation);
|
|
34
|
+
}
|
|
35
|
+
return parts.join(this.SEPARATOR) + '*';
|
|
36
|
+
}
|
|
37
|
+
static hashQuery(query) {
|
|
38
|
+
const normalized = this.normalizeQuery(query);
|
|
39
|
+
return this.hash(JSON.stringify(normalized));
|
|
40
|
+
}
|
|
41
|
+
static normalizeQuery(query) {
|
|
42
|
+
const normalized = {};
|
|
43
|
+
if (query.expressions && query.expressions.length > 0) {
|
|
44
|
+
normalized.expressions = query.expressions
|
|
45
|
+
.map(exp => ({
|
|
46
|
+
op: exp.op || '==',
|
|
47
|
+
key: exp.key,
|
|
48
|
+
val: this.normalizeValue(exp.val)
|
|
49
|
+
}))
|
|
50
|
+
.sort((a, b) => {
|
|
51
|
+
const keyCompare = a.key.localeCompare(b.key);
|
|
52
|
+
if (keyCompare !== 0)
|
|
53
|
+
return keyCompare;
|
|
54
|
+
const opCompare = a.op.localeCompare(b.op);
|
|
55
|
+
if (opCompare !== 0)
|
|
56
|
+
return opCompare;
|
|
57
|
+
return String(a.val).localeCompare(String(b.val));
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (query.ranges && query.ranges.length > 0) {
|
|
61
|
+
normalized.ranges = query.ranges
|
|
62
|
+
.map(range => ({
|
|
63
|
+
key: range.key,
|
|
64
|
+
start: this.normalizeValue(range.start),
|
|
65
|
+
end: this.normalizeValue(range.end)
|
|
66
|
+
}))
|
|
67
|
+
.sort((a, b) => a.key.localeCompare(b.key));
|
|
68
|
+
}
|
|
69
|
+
if (query.orderField) {
|
|
70
|
+
normalized.order = {
|
|
71
|
+
field: query.orderField,
|
|
72
|
+
direction: query.orderDirection || types_1.SortDirection.Ascending
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (query.orQueries && query.orQueries.length > 0) {
|
|
76
|
+
normalized.or = query.orQueries
|
|
77
|
+
.map(q => this.normalizeQuery(q))
|
|
78
|
+
.sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
|
|
79
|
+
}
|
|
80
|
+
if (query.andQueries && query.andQueries.length > 0) {
|
|
81
|
+
normalized.and = query.andQueries
|
|
82
|
+
.map(q => this.normalizeQuery(q))
|
|
83
|
+
.sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
|
|
84
|
+
}
|
|
85
|
+
return normalized;
|
|
86
|
+
}
|
|
87
|
+
static normalizeValue(value) {
|
|
88
|
+
if (value === null) {
|
|
89
|
+
return this.NULL_VALUE;
|
|
90
|
+
}
|
|
91
|
+
if (value === undefined) {
|
|
92
|
+
return this.UNDEFINED_VALUE;
|
|
93
|
+
}
|
|
94
|
+
if (value instanceof Date) {
|
|
95
|
+
return value.toISOString();
|
|
96
|
+
}
|
|
97
|
+
if (typeof value === 'object' && value !== null) {
|
|
98
|
+
if (Array.isArray(value)) {
|
|
99
|
+
return value.map(v => this.normalizeValue(v)).sort();
|
|
100
|
+
}
|
|
101
|
+
const normalized = {};
|
|
102
|
+
const keys = Object.keys(value).sort();
|
|
103
|
+
for (const key of keys) {
|
|
104
|
+
normalized[key] = this.normalizeValue(value[key]);
|
|
105
|
+
}
|
|
106
|
+
return normalized;
|
|
107
|
+
}
|
|
108
|
+
return value;
|
|
109
|
+
}
|
|
110
|
+
static hashObject(obj) {
|
|
111
|
+
const normalized = this.normalizeValue(obj);
|
|
112
|
+
return this.hash(JSON.stringify(normalized));
|
|
113
|
+
}
|
|
114
|
+
static hash(input) {
|
|
115
|
+
return (0, crypto_1.createHash)('sha256')
|
|
116
|
+
.update(input)
|
|
117
|
+
.digest('hex')
|
|
118
|
+
.substring(0, 16);
|
|
119
|
+
}
|
|
120
|
+
static parseKey(key) {
|
|
121
|
+
const parts = key.split(this.SEPARATOR);
|
|
122
|
+
if (parts[0] !== 'flongo') {
|
|
123
|
+
return {};
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
collection: parts[1],
|
|
127
|
+
operation: parts[2],
|
|
128
|
+
identifier: parts.slice(3).join(this.SEPARATOR)
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
static isFlongoKey(key) {
|
|
132
|
+
return key.startsWith('flongo' + this.SEPARATOR);
|
|
133
|
+
}
|
|
134
|
+
static getCollectionFromKey(key) {
|
|
135
|
+
const parsed = this.parseKey(key);
|
|
136
|
+
return parsed.collection;
|
|
137
|
+
}
|
|
138
|
+
static getOperationFromKey(key) {
|
|
139
|
+
const parsed = this.parseKey(key);
|
|
140
|
+
return parsed.operation;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.CacheKeyGenerator = CacheKeyGenerator;
|
|
144
|
+
CacheKeyGenerator.SEPARATOR = ':';
|
|
145
|
+
CacheKeyGenerator.NULL_VALUE = '__null__';
|
|
146
|
+
CacheKeyGenerator.UNDEFINED_VALUE = '__undefined__';
|
|
147
|
+
//# sourceMappingURL=cacheKeyGenerator.js.map
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { CacheStats } from './cacheStore';
|
|
2
|
+
export interface DetailedCacheStats extends CacheStats {
|
|
3
|
+
hitRate: number;
|
|
4
|
+
missRate: number;
|
|
5
|
+
evictionRate: number;
|
|
6
|
+
averageAccessTime?: number;
|
|
7
|
+
totalRequests: number;
|
|
8
|
+
uptime: number;
|
|
9
|
+
lastReset: number;
|
|
10
|
+
}
|
|
11
|
+
export interface CacheMetrics {
|
|
12
|
+
operationCounts: Map<string, number>;
|
|
13
|
+
operationLatencies: Map<string, number[]>;
|
|
14
|
+
collectionStats: Map<string, CacheStats>;
|
|
15
|
+
keyAccessCounts: Map<string, number>;
|
|
16
|
+
memoryUsageOverTime: Array<{
|
|
17
|
+
timestamp: number;
|
|
18
|
+
usage: number;
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
21
|
+
export declare class CacheStatsCollector {
|
|
22
|
+
private startTime;
|
|
23
|
+
private lastResetTime;
|
|
24
|
+
private metrics;
|
|
25
|
+
private maxHistorySize;
|
|
26
|
+
constructor(maxHistorySize?: number);
|
|
27
|
+
recordOperation(operation: string, latencyMs: number): void;
|
|
28
|
+
recordKeyAccess(key: string): void;
|
|
29
|
+
recordMemoryUsage(usageBytes: number): void;
|
|
30
|
+
updateCollectionStats(collection: string, stats: Partial<CacheStats>): void;
|
|
31
|
+
getDetailedStats(baseStats: CacheStats): DetailedCacheStats;
|
|
32
|
+
getOperationStats(): Map<string, {
|
|
33
|
+
count: number;
|
|
34
|
+
averageLatency: number;
|
|
35
|
+
p50: number;
|
|
36
|
+
p95: number;
|
|
37
|
+
p99: number;
|
|
38
|
+
}>;
|
|
39
|
+
getTopKeys(limit?: number): Array<{
|
|
40
|
+
key: string;
|
|
41
|
+
count: number;
|
|
42
|
+
}>;
|
|
43
|
+
getMemoryTrend(): Array<{
|
|
44
|
+
timestamp: number;
|
|
45
|
+
usage: number;
|
|
46
|
+
}>;
|
|
47
|
+
getCollectionStats(): Map<string, CacheStats>;
|
|
48
|
+
reset(): void;
|
|
49
|
+
private calculateAverage;
|
|
50
|
+
private calculatePercentile;
|
|
51
|
+
private calculateAverageLatency;
|
|
52
|
+
toJSON(): object;
|
|
53
|
+
}
|
|
54
|
+
export declare class CacheMonitor {
|
|
55
|
+
private collectors;
|
|
56
|
+
private globalCollector;
|
|
57
|
+
private intervalId?;
|
|
58
|
+
constructor();
|
|
59
|
+
getCollector(name: string): CacheStatsCollector;
|
|
60
|
+
getGlobalCollector(): CacheStatsCollector;
|
|
61
|
+
startMonitoring(intervalMs?: number, callback?: (stats: any) => void): void;
|
|
62
|
+
stopMonitoring(): void;
|
|
63
|
+
getSnapshot(): object;
|
|
64
|
+
reset(): void;
|
|
65
|
+
destroy(): void;
|
|
66
|
+
}
|
|
67
|
+
export declare function getGlobalCacheMonitor(): CacheMonitor;
|
|
68
|
+
export declare function resetGlobalCacheMonitor(): void;
|
|
69
|
+
//# sourceMappingURL=cacheStats.d.ts.map
|