@fjell/cache 4.7.43 → 4.7.44

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/index.js CHANGED
@@ -94,48 +94,78 @@ var TwoLayerCacheMap = class _TwoLayerCacheMap extends CacheMap {
94
94
  * Set a query result with rich metadata for two-layer architecture
95
95
  */
96
96
  async setQueryResult(queryHash, itemKeys) {
97
+ logger.debug("QUERY_CACHE: TwoLayerCacheMap.setQueryResult() called", {
98
+ queryHash,
99
+ itemKeyCount: itemKeys.length,
100
+ itemKeys: itemKeys.map((k) => JSON.stringify(k))
101
+ });
97
102
  await this.underlyingCache.setQueryResult(queryHash, itemKeys);
103
+ logger.debug("QUERY_CACHE: Stored query result in underlying cache", { queryHash });
98
104
  const now = /* @__PURE__ */ new Date();
99
105
  const isComplete = this.determineQueryCompleteness(queryHash, itemKeys);
100
106
  const ttlSeconds = isComplete ? this.options.queryTTL : this.options.facetTTL;
107
+ const expiresAt = new Date(now.getTime() + ttlSeconds * 1e3);
101
108
  const metadata = {
102
109
  queryType: this.extractQueryType(queryHash),
103
110
  isComplete,
104
111
  createdAt: now,
105
- expiresAt: new Date(now.getTime() + ttlSeconds * 1e3),
112
+ expiresAt,
106
113
  filter: this.extractFilter(queryHash),
107
114
  params: this.extractParams(queryHash)
108
115
  };
109
116
  this.queryMetadataMap.set(queryHash, metadata);
110
- if (this.options.debug) {
111
- logger.debug("Set query result with metadata", {
112
- queryHash,
113
- itemCount: itemKeys.length,
114
- isComplete,
115
- ttlSeconds,
116
- expiresAt: metadata.expiresAt.toISOString()
117
- });
118
- }
117
+ logger.debug("QUERY_CACHE: Set query result with metadata", {
118
+ queryHash,
119
+ itemCount: itemKeys.length,
120
+ isComplete,
121
+ ttlSeconds,
122
+ queryType: metadata.queryType,
123
+ createdAt: metadata.createdAt.toISOString(),
124
+ expiresAt: metadata.expiresAt.toISOString(),
125
+ filter: metadata.filter,
126
+ params: metadata.params
127
+ });
119
128
  }
120
129
  /**
121
130
  * Get a query result with expiration checking
122
131
  */
123
132
  async getQueryResult(queryHash) {
133
+ logger.debug("QUERY_CACHE: TwoLayerCacheMap.getQueryResult() called", { queryHash });
124
134
  const metadata = this.queryMetadataMap.get(queryHash);
125
- if (metadata && metadata.expiresAt < /* @__PURE__ */ new Date()) {
126
- await this.deleteQueryResult(queryHash);
127
- if (this.options.debug) {
128
- logger.debug("Query result expired and removed", { queryHash });
135
+ if (metadata) {
136
+ const now = /* @__PURE__ */ new Date();
137
+ const isExpired = metadata.expiresAt < now;
138
+ logger.debug("QUERY_CACHE: Query metadata found", {
139
+ queryHash,
140
+ isExpired,
141
+ expiresAt: metadata.expiresAt.toISOString(),
142
+ now: now.toISOString(),
143
+ isComplete: metadata.isComplete,
144
+ queryType: metadata.queryType
145
+ });
146
+ if (isExpired) {
147
+ logger.debug("QUERY_CACHE: Query result EXPIRED, removing", {
148
+ queryHash,
149
+ expiresAt: metadata.expiresAt.toISOString(),
150
+ now: now.toISOString()
151
+ });
152
+ await this.deleteQueryResult(queryHash);
153
+ return null;
129
154
  }
130
- return null;
155
+ } else {
156
+ logger.debug("QUERY_CACHE: No metadata found for query hash", { queryHash });
131
157
  }
158
+ logger.debug("QUERY_CACHE: Fetching query result from underlying cache", { queryHash });
132
159
  const result = await this.underlyingCache.getQueryResult(queryHash);
133
- if (result && this.options.debug) {
134
- logger.debug("Query result cache hit", {
160
+ if (result) {
161
+ logger.debug("QUERY_CACHE: Query result retrieved from underlying cache", {
135
162
  queryHash,
136
163
  itemCount: result.length,
137
- isComplete: metadata?.isComplete
164
+ isComplete: metadata?.isComplete,
165
+ itemKeys: result.map((k) => JSON.stringify(k))
138
166
  });
167
+ } else {
168
+ logger.debug("QUERY_CACHE: No query result found in underlying cache", { queryHash });
139
169
  }
140
170
  return result;
141
171
  }
@@ -150,25 +180,44 @@ var TwoLayerCacheMap = class _TwoLayerCacheMap extends CacheMap {
150
180
  * Delete a query result and its metadata
151
181
  */
152
182
  async deleteQueryResult(queryHash) {
183
+ logger.debug("QUERY_CACHE: TwoLayerCacheMap.deleteQueryResult() called", { queryHash });
184
+ const hadMetadata = this.queryMetadataMap.has(queryHash);
185
+ const metadata = this.queryMetadataMap.get(queryHash);
153
186
  await this.underlyingCache.deleteQueryResult(queryHash);
154
187
  this.queryMetadataMap.delete(queryHash);
155
- if (this.options.debug) {
156
- logger.debug("Deleted query result", { queryHash });
157
- }
188
+ logger.debug("QUERY_CACHE: Deleted query result", {
189
+ queryHash,
190
+ hadMetadata,
191
+ wasComplete: metadata?.isComplete,
192
+ queryType: metadata?.queryType
193
+ });
158
194
  }
159
195
  // ===== QUERY INVALIDATION (CRITICAL FOR TWO-LAYER ARCHITECTURE) =====
160
196
  /**
161
197
  * Invalidate queries that are affected by item changes
162
198
  */
163
199
  async invalidateQueriesForItem(itemKey) {
200
+ logger.debug("QUERY_CACHE: Invalidating queries for item change", {
201
+ itemKey: JSON.stringify(itemKey)
202
+ });
164
203
  const affectedQueries = await this.findQueriesContainingItem(itemKey);
204
+ logger.debug("QUERY_CACHE: Found queries containing item", {
205
+ itemKey: JSON.stringify(itemKey),
206
+ affectedQueryCount: affectedQueries.length,
207
+ affectedQueries
208
+ });
165
209
  for (const queryHash of affectedQueries) {
166
210
  await this.deleteQueryResult(queryHash);
167
211
  }
168
- if (this.options.debug && affectedQueries.length > 0) {
169
- logger.debug("Invalidated queries for item change", {
212
+ if (affectedQueries.length > 0) {
213
+ logger.debug("QUERY_CACHE: Invalidated queries for item change", {
170
214
  itemKey: JSON.stringify(itemKey),
171
- queriesInvalidated: affectedQueries.length
215
+ queriesInvalidated: affectedQueries.length,
216
+ queryHashes: affectedQueries
217
+ });
218
+ } else {
219
+ logger.debug("QUERY_CACHE: No queries found containing item", {
220
+ itemKey: JSON.stringify(itemKey)
172
221
  });
173
222
  }
174
223
  }
@@ -307,18 +356,40 @@ var TwoLayerCacheMap = class _TwoLayerCacheMap extends CacheMap {
307
356
  * Clean up expired queries
308
357
  */
309
358
  async cleanup() {
359
+ const startTime = Date.now();
310
360
  const now = /* @__PURE__ */ new Date();
311
361
  const expiredQueries = [];
362
+ logger.debug("TWO_LAYER: Starting query cleanup", {
363
+ totalQueries: this.queryMetadataMap.size,
364
+ now: now.toISOString()
365
+ });
312
366
  for (const [queryHash, metadata] of this.queryMetadataMap.entries()) {
313
367
  if (metadata.expiresAt < now) {
314
368
  expiredQueries.push(queryHash);
369
+ logger.debug("TWO_LAYER: Found expired query", {
370
+ queryHash,
371
+ queryType: metadata.queryType,
372
+ isComplete: metadata.isComplete,
373
+ expiresAt: metadata.expiresAt.toISOString(),
374
+ expiredByMs: now.getTime() - metadata.expiresAt.getTime()
375
+ });
315
376
  }
316
377
  }
317
378
  for (const queryHash of expiredQueries) {
318
379
  await this.deleteQueryResult(queryHash);
319
380
  }
320
- if (this.options.debug && expiredQueries.length > 0) {
321
- logger.debug("Cleaned up expired queries", { count: expiredQueries.length });
381
+ const duration = Date.now() - startTime;
382
+ if (expiredQueries.length > 0) {
383
+ logger.debug("TWO_LAYER: Query cleanup completed", {
384
+ expiredCount: expiredQueries.length,
385
+ totalQueries: this.queryMetadataMap.size,
386
+ duration
387
+ });
388
+ } else {
389
+ logger.debug("TWO_LAYER: Query cleanup - no expired queries", {
390
+ totalQueries: this.queryMetadataMap.size,
391
+ duration
392
+ });
322
393
  }
323
394
  return expiredQueries.length;
324
395
  }
@@ -330,24 +401,68 @@ var TwoLayerCacheMap = class _TwoLayerCacheMap extends CacheMap {
330
401
  // The types are accessible through super.types
331
402
  // ===== MISSING ABSTRACT METHODS FROM CacheMap =====
332
403
  async invalidateItemKeys(keys) {
404
+ const startTime = Date.now();
405
+ logger.debug("TWO_LAYER: Invalidating item keys", {
406
+ keyCount: keys.length,
407
+ keys: keys.map((k) => JSON.stringify(k))
408
+ });
333
409
  if ("invalidateItemKeys" in this.underlyingCache && typeof this.underlyingCache.invalidateItemKeys === "function") {
334
410
  await this.underlyingCache.invalidateItemKeys(keys);
335
411
  }
412
+ let totalInvalidatedQueries = 0;
336
413
  for (const key of keys) {
414
+ const beforeCount = this.queryMetadataMap.size;
337
415
  await this.invalidateQueriesForItem(key);
416
+ const afterCount = this.queryMetadataMap.size;
417
+ const invalidated = beforeCount - afterCount;
418
+ totalInvalidatedQueries += invalidated;
419
+ if (invalidated > 0) {
420
+ logger.debug("TWO_LAYER: Invalidated queries for item", {
421
+ key: JSON.stringify(key),
422
+ queriesInvalidated: invalidated
423
+ });
424
+ }
338
425
  }
426
+ const duration = Date.now() - startTime;
427
+ logger.debug("TWO_LAYER: Item key invalidation completed", {
428
+ keyCount: keys.length,
429
+ totalQueriesInvalidated: totalInvalidatedQueries,
430
+ duration
431
+ });
339
432
  }
340
433
  async invalidateLocation(locations) {
434
+ const startTime = Date.now();
435
+ const queryCountBefore = this.queryMetadataMap.size;
436
+ logger.debug("TWO_LAYER: Invalidating location", {
437
+ locations: JSON.stringify(locations),
438
+ queryCountBefore
439
+ });
341
440
  if ("invalidateLocation" in this.underlyingCache && typeof this.underlyingCache.invalidateLocation === "function") {
342
441
  await this.underlyingCache.invalidateLocation(locations);
343
442
  }
344
443
  this.queryMetadataMap.clear();
444
+ const duration = Date.now() - startTime;
445
+ logger.debug("TWO_LAYER: Location invalidation completed", {
446
+ locations: JSON.stringify(locations),
447
+ queriesCleared: queryCountBefore,
448
+ duration
449
+ });
345
450
  }
346
451
  async clearQueryResults() {
452
+ const startTime = Date.now();
453
+ const queryCountBefore = this.queryMetadataMap.size;
454
+ logger.debug("TWO_LAYER: Clearing all query results", {
455
+ queryCountBefore
456
+ });
347
457
  if ("clearQueryResults" in this.underlyingCache && typeof this.underlyingCache.clearQueryResults === "function") {
348
458
  await this.underlyingCache.clearQueryResults();
349
459
  }
350
460
  this.queryMetadataMap.clear();
461
+ const duration = Date.now() - startTime;
462
+ logger.debug("TWO_LAYER: Cleared all query results", {
463
+ queriesCleared: queryCountBefore,
464
+ duration
465
+ });
351
466
  }
352
467
  /**
353
468
  * Check if two-layer mode is enabled
@@ -702,66 +817,151 @@ async function executeAllLogic(query, locations, context) {
702
817
  }
703
818
  }
704
819
  const queryHash = createQueryHash(pkType, query, locations);
705
- logger2.debug("Generated query hash for all", { queryHash });
820
+ logger2.debug("QUERY_CACHE: Generated query hash for all()", {
821
+ queryHash,
822
+ query: JSON.stringify(query),
823
+ locations: JSON.stringify(locations),
824
+ pkType
825
+ });
826
+ logger2.debug("QUERY_CACHE: Checking query cache for hash", { queryHash });
706
827
  const cachedItemKeys = await cacheMap.getQueryResult(queryHash);
707
828
  if (cachedItemKeys) {
708
- logger2.debug("Using cached query results", { cachedKeyCount: cachedItemKeys.length });
829
+ logger2.debug("QUERY_CACHE: Cache HIT - Found cached query result", {
830
+ queryHash,
831
+ cachedKeyCount: cachedItemKeys.length,
832
+ itemKeys: cachedItemKeys.map((k) => JSON.stringify(k))
833
+ });
709
834
  const cachedItems = [];
710
835
  let allItemsAvailable = true;
836
+ const missingKeys = [];
711
837
  for (const itemKey of cachedItemKeys) {
712
838
  const item = await cacheMap.get(itemKey);
713
839
  if (item) {
714
840
  cachedItems.push(item);
841
+ logger2.debug("QUERY_CACHE: Retrieved cached item", {
842
+ itemKey: JSON.stringify(itemKey),
843
+ itemKeyStr: JSON.stringify(item.key)
844
+ });
715
845
  } else {
716
846
  allItemsAvailable = false;
847
+ missingKeys.push(itemKey);
848
+ logger2.debug("QUERY_CACHE: Cached item MISSING from item cache", {
849
+ itemKey: JSON.stringify(itemKey),
850
+ queryHash
851
+ });
717
852
  break;
718
853
  }
719
854
  }
720
855
  if (allItemsAvailable) {
856
+ logger2.debug("QUERY_CACHE: All cached items available, returning from cache", {
857
+ queryHash,
858
+ itemCount: cachedItems.length
859
+ });
721
860
  return cachedItems;
722
861
  } else {
723
- logger2.debug("Some cached items missing, invalidating query cache");
862
+ logger2.debug("QUERY_CACHE: Some cached items missing, invalidating query cache", {
863
+ queryHash,
864
+ missingKeys: missingKeys.map((k) => JSON.stringify(k)),
865
+ foundCount: cachedItems.length,
866
+ expectedCount: cachedItemKeys.length
867
+ });
724
868
  cacheMap.deleteQueryResult(queryHash);
725
869
  }
870
+ } else {
871
+ logger2.debug("QUERY_CACHE: Cache MISS - No cached query result found", { queryHash });
726
872
  }
873
+ logger2.debug("QUERY_CACHE: Attempting direct cache query using queryIn()", {
874
+ queryHash,
875
+ query: JSON.stringify(query),
876
+ locations: JSON.stringify(locations)
877
+ });
727
878
  try {
728
879
  const directCachedItems = await cacheMap.queryIn(query, locations);
729
880
  if (directCachedItems && directCachedItems.length > 0) {
730
- logger2.debug("Found items directly in cache, skipping API call", { itemCount: directCachedItems.length });
881
+ logger2.debug("QUERY_CACHE: Direct cache query SUCCESS - Found items in item cache", {
882
+ queryHash,
883
+ itemCount: directCachedItems.length,
884
+ itemKeys: directCachedItems.map((item) => JSON.stringify(item.key))
885
+ });
731
886
  const itemKeys = directCachedItems.map((item) => item.key);
732
887
  await cacheMap.setQueryResult(queryHash, itemKeys);
733
- logger2.debug("Cached query result from direct cache hit", { queryHash, itemKeyCount: itemKeys.length });
888
+ logger2.debug("QUERY_CACHE: Stored query result from direct cache hit", {
889
+ queryHash,
890
+ itemKeyCount: itemKeys.length,
891
+ itemKeys: itemKeys.map((k) => JSON.stringify(k))
892
+ });
734
893
  return directCachedItems;
894
+ } else {
895
+ logger2.debug("QUERY_CACHE: Direct cache query returned no items", { queryHash });
735
896
  }
736
897
  } catch (error) {
737
- logger2.debug("Error querying cache directly, proceeding to API", { error });
898
+ logger2.debug("QUERY_CACHE: Error querying cache directly, proceeding to API", {
899
+ queryHash,
900
+ error: error instanceof Error ? error.message : String(error)
901
+ });
738
902
  }
903
+ logger2.debug("QUERY_CACHE: Fetching from API (cache miss or invalid)", {
904
+ queryHash,
905
+ query: JSON.stringify(query),
906
+ locations: JSON.stringify(locations)
907
+ });
739
908
  let ret = [];
740
909
  try {
741
910
  ret = await api.all(query, locations);
911
+ logger2.debug("QUERY_CACHE: API response received", {
912
+ queryHash,
913
+ itemCount: ret.length,
914
+ itemKeys: ret.map((item) => JSON.stringify(item.key))
915
+ });
916
+ logger2.debug("QUERY_CACHE: Storing items in item cache", {
917
+ queryHash,
918
+ itemCount: ret.length
919
+ });
742
920
  for (const v of ret) {
743
921
  await cacheMap.set(v.key, v);
922
+ logger2.debug("QUERY_CACHE: Stored item in cache", {
923
+ itemKey: JSON.stringify(v.key),
924
+ queryHash
925
+ });
744
926
  const keyStr = JSON.stringify(v.key);
745
927
  ttlManager.onItemAdded(keyStr, cacheMap);
746
928
  const evictedKeys = await context.evictionManager.onItemAdded(keyStr, v, cacheMap);
747
929
  for (const evictedKey of evictedKeys) {
748
930
  const parsedKey = JSON.parse(evictedKey);
749
931
  await cacheMap.delete(parsedKey);
932
+ logger2.debug("QUERY_CACHE: Evicted item due to cache limits", {
933
+ evictedKey,
934
+ queryHash
935
+ });
750
936
  }
751
937
  }
752
938
  const itemKeys = ret.map((item) => item.key);
753
- cacheMap.setQueryResult(queryHash, itemKeys);
754
- logger2.debug("Cached query result", { queryHash, itemKeyCount: itemKeys.length });
939
+ await cacheMap.setQueryResult(queryHash, itemKeys);
940
+ logger2.debug("QUERY_CACHE: Stored query result in query cache", {
941
+ queryHash,
942
+ itemKeyCount: itemKeys.length,
943
+ itemKeys: itemKeys.map((k) => JSON.stringify(k))
944
+ });
755
945
  const event = CacheEventFactory.createQueryEvent(query, locations, ret);
756
946
  context.eventEmitter.emit(event);
947
+ logger2.debug("QUERY_CACHE: Emitted query event", { queryHash });
757
948
  } catch (e) {
758
949
  if (e instanceof NotFoundError) {
759
- cacheMap.setQueryResult(queryHash, []);
760
- logger2.debug("Cached empty query result for not found", { queryHash });
950
+ logger2.debug("QUERY_CACHE: API returned NotFoundError, caching empty result", { queryHash });
951
+ await cacheMap.setQueryResult(queryHash, []);
952
+ logger2.debug("QUERY_CACHE: Cached empty query result for not found", { queryHash });
761
953
  } else {
954
+ logger2.debug("QUERY_CACHE: API error occurred", {
955
+ queryHash,
956
+ error: e instanceof Error ? e.message : String(e)
957
+ });
762
958
  throw e;
763
959
  }
764
960
  }
961
+ logger2.debug("QUERY_CACHE: all() operation completed", {
962
+ queryHash,
963
+ resultCount: ret.length
964
+ });
765
965
  return ret;
766
966
  }
767
967
 
@@ -964,37 +1164,93 @@ async function executeOneLogic(query, locations, context) {
964
1164
  }
965
1165
  }
966
1166
  const queryHash = createQueryHash(pkType, query, locations);
967
- logger3.debug("Generated query hash for one", { queryHash });
1167
+ logger3.debug("QUERY_CACHE: Generated query hash for one()", {
1168
+ queryHash,
1169
+ query: JSON.stringify(query),
1170
+ locations: JSON.stringify(locations),
1171
+ pkType
1172
+ });
1173
+ logger3.debug("QUERY_CACHE: Checking query cache for hash", { queryHash });
968
1174
  const cachedItemKeys = await cacheMap.getQueryResult(queryHash);
969
1175
  if (cachedItemKeys) {
970
- logger3.debug("Using cached query results", { cachedKeyCount: cachedItemKeys.length });
1176
+ logger3.debug("QUERY_CACHE: Cache HIT - Found cached query result", {
1177
+ queryHash,
1178
+ cachedKeyCount: cachedItemKeys.length,
1179
+ itemKeys: cachedItemKeys.map((k) => JSON.stringify(k))
1180
+ });
971
1181
  if (cachedItemKeys.length === 0) {
1182
+ logger3.debug("QUERY_CACHE: Cached empty result (not found)", { queryHash });
972
1183
  return null;
973
1184
  }
974
- const item = await cacheMap.get(cachedItemKeys[0]);
1185
+ const itemKey = cachedItemKeys[0];
1186
+ logger3.debug("QUERY_CACHE: Retrieving first cached item", {
1187
+ queryHash,
1188
+ itemKey: JSON.stringify(itemKey)
1189
+ });
1190
+ const item = await cacheMap.get(itemKey);
975
1191
  if (item) {
1192
+ logger3.debug("QUERY_CACHE: Retrieved cached item successfully", {
1193
+ queryHash,
1194
+ itemKey: JSON.stringify(itemKey),
1195
+ itemKeyStr: JSON.stringify(item.key)
1196
+ });
976
1197
  return item;
977
1198
  } else {
978
- logger3.debug("Cached item missing, invalidating query cache");
1199
+ logger3.debug("QUERY_CACHE: Cached item MISSING from item cache, invalidating query cache", {
1200
+ queryHash,
1201
+ itemKey: JSON.stringify(itemKey)
1202
+ });
979
1203
  cacheMap.deleteQueryResult(queryHash);
980
1204
  }
1205
+ } else {
1206
+ logger3.debug("QUERY_CACHE: Cache MISS - No cached query result found", { queryHash });
981
1207
  }
1208
+ logger3.debug("QUERY_CACHE: Attempting direct cache query using queryIn()", {
1209
+ queryHash,
1210
+ query: JSON.stringify(query),
1211
+ locations: JSON.stringify(locations)
1212
+ });
982
1213
  try {
983
1214
  const directCachedItems = await cacheMap.queryIn(query, locations);
984
1215
  if (directCachedItems && directCachedItems.length > 0) {
985
- logger3.debug("Found item directly in cache, skipping API call");
1216
+ logger3.debug("QUERY_CACHE: Direct cache query SUCCESS - Found item in item cache", {
1217
+ queryHash,
1218
+ itemCount: directCachedItems.length,
1219
+ itemKeys: directCachedItems.map((item) => JSON.stringify(item.key))
1220
+ });
986
1221
  const foundItem = directCachedItems[0];
987
1222
  await cacheMap.setQueryResult(queryHash, [foundItem.key]);
988
- logger3.debug("Cached query result from direct cache hit", { queryHash, itemKey: foundItem.key });
1223
+ logger3.debug("QUERY_CACHE: Stored query result from direct cache hit", {
1224
+ queryHash,
1225
+ itemKey: JSON.stringify(foundItem.key)
1226
+ });
989
1227
  return foundItem;
1228
+ } else {
1229
+ logger3.debug("QUERY_CACHE: Direct cache query returned no items", { queryHash });
990
1230
  }
991
1231
  } catch (error) {
992
- logger3.debug("Error querying cache directly, proceeding to API", { error });
1232
+ logger3.debug("QUERY_CACHE: Error querying cache directly, proceeding to API", {
1233
+ queryHash,
1234
+ error: error instanceof Error ? error.message : String(error)
1235
+ });
993
1236
  }
1237
+ logger3.debug("QUERY_CACHE: Fetching from API (cache miss or invalid)", {
1238
+ queryHash,
1239
+ query: JSON.stringify(query),
1240
+ locations: JSON.stringify(locations)
1241
+ });
994
1242
  let retItem = null;
995
1243
  try {
996
1244
  retItem = await api.one(query, locations);
997
1245
  if (retItem) {
1246
+ logger3.debug("QUERY_CACHE: API response received", {
1247
+ queryHash,
1248
+ itemKey: JSON.stringify(retItem.key)
1249
+ });
1250
+ logger3.debug("QUERY_CACHE: Storing item in item cache", {
1251
+ queryHash,
1252
+ itemKey: JSON.stringify(retItem.key)
1253
+ });
998
1254
  await cacheMap.set(retItem.key, retItem);
999
1255
  const keyStr = JSON.stringify(retItem.key);
1000
1256
  const metadata = await cacheMap.getMetadata(keyStr);
@@ -1014,21 +1270,38 @@ async function executeOneLogic(query, locations, context) {
1014
1270
  for (const evictedKey of evictedKeys) {
1015
1271
  const parsedKey = JSON.parse(evictedKey);
1016
1272
  await cacheMap.delete(parsedKey);
1273
+ logger3.debug("QUERY_CACHE: Evicted item due to cache limits", {
1274
+ evictedKey,
1275
+ queryHash
1276
+ });
1017
1277
  }
1018
1278
  await cacheMap.setQueryResult(queryHash, [retItem.key]);
1019
- logger3.debug("Cached query result", { queryHash, itemKey: retItem.key });
1279
+ logger3.debug("QUERY_CACHE: Stored query result in query cache", {
1280
+ queryHash,
1281
+ itemKey: JSON.stringify(retItem.key)
1282
+ });
1020
1283
  } else {
1284
+ logger3.debug("QUERY_CACHE: API returned null, caching empty result", { queryHash });
1021
1285
  await cacheMap.setQueryResult(queryHash, []);
1022
- logger3.debug("Cached empty query result", { queryHash });
1286
+ logger3.debug("QUERY_CACHE: Cached empty query result", { queryHash });
1023
1287
  }
1024
1288
  } catch (e) {
1025
1289
  if (e instanceof NotFoundError2) {
1026
- cacheMap.setQueryResult(queryHash, []);
1027
- logger3.debug("Cached empty query result for not found", { queryHash });
1290
+ logger3.debug("QUERY_CACHE: API returned NotFoundError, caching empty result", { queryHash });
1291
+ await cacheMap.setQueryResult(queryHash, []);
1292
+ logger3.debug("QUERY_CACHE: Cached empty query result for not found", { queryHash });
1028
1293
  } else {
1294
+ logger3.debug("QUERY_CACHE: API error occurred", {
1295
+ queryHash,
1296
+ error: e instanceof Error ? e.message : String(e)
1297
+ });
1029
1298
  throw e;
1030
1299
  }
1031
1300
  }
1301
+ logger3.debug("QUERY_CACHE: one() operation completed", {
1302
+ queryHash,
1303
+ result: retItem ? JSON.stringify(retItem.key) : null
1304
+ });
1032
1305
  return retItem || null;
1033
1306
  }
1034
1307
 
@@ -1110,68 +1383,128 @@ var get = async (key, context) => {
1110
1383
  return [context, result];
1111
1384
  };
1112
1385
  async function executeGetLogic(key, context) {
1386
+ const startTime = Date.now();
1113
1387
  const { api, cacheMap, pkType, ttlManager, statsManager } = context;
1388
+ const keyStr = JSON.stringify(key);
1389
+ logger5.debug("CACHE_OP: get() started", {
1390
+ key: keyStr,
1391
+ ttlEnabled: ttlManager.isTTLEnabled(),
1392
+ defaultTTL: ttlManager.getDefaultTTL(),
1393
+ cacheType: cacheMap.implementationType
1394
+ });
1114
1395
  statsManager.incrementRequests();
1115
1396
  if (!isValidItemKey(key)) {
1116
- logger5.error("Key for Get is not a valid ItemKey: %j", key);
1397
+ logger5.error("CACHE_OP: Invalid key for get", { key: keyStr });
1117
1398
  throw new Error("Key for Get is not a valid ItemKey");
1118
1399
  }
1119
1400
  if (context.options?.bypassCache) {
1120
- logger5.debug("Cache bypass enabled, fetching directly from API", { key });
1401
+ logger5.debug("CACHE_OP: Cache bypass enabled, fetching directly from API", { key: keyStr });
1121
1402
  statsManager.incrementMisses();
1122
1403
  try {
1404
+ const apiStartTime = Date.now();
1123
1405
  const ret2 = await api.get(key);
1406
+ const apiDuration = Date.now() - apiStartTime;
1124
1407
  if (ret2) {
1125
- logger5.debug("API response received (not cached due to bypass)", { key });
1408
+ logger5.debug("CACHE_OP: API response received (bypass mode, not cached)", {
1409
+ key: keyStr,
1410
+ apiDuration,
1411
+ totalDuration: Date.now() - startTime
1412
+ });
1126
1413
  return ret2;
1127
1414
  } else {
1128
- logger5.debug("API returned null", { key });
1415
+ logger5.debug("CACHE_OP: API returned null (bypass mode)", {
1416
+ key: keyStr,
1417
+ apiDuration
1418
+ });
1129
1419
  return null;
1130
1420
  }
1131
1421
  } catch (error) {
1132
- logger5.error("API request failed", { key, error });
1422
+ logger5.error("CACHE_OP: API request failed in bypass mode", {
1423
+ key: keyStr,
1424
+ duration: Date.now() - startTime,
1425
+ error
1426
+ });
1133
1427
  throw error;
1134
1428
  }
1135
1429
  }
1136
1430
  if (ttlManager.isTTLEnabled()) {
1137
- const keyStr2 = JSON.stringify(key);
1431
+ const cacheCheckStart = Date.now();
1138
1432
  const cachedItem = await cacheMap.get(key);
1433
+ const cacheCheckDuration = Date.now() - cacheCheckStart;
1139
1434
  if (cachedItem) {
1140
- const isValid = await ttlManager.validateItem(keyStr2, cacheMap);
1435
+ logger5.debug("CACHE_OP: Item found in cache, checking TTL validity", {
1436
+ key: keyStr,
1437
+ cacheCheckDuration,
1438
+ defaultTTL: ttlManager.getDefaultTTL()
1439
+ });
1440
+ const ttlCheckStart = Date.now();
1441
+ const isValid = await ttlManager.validateItem(keyStr, cacheMap);
1442
+ const ttlCheckDuration = Date.now() - ttlCheckStart;
1141
1443
  if (isValid) {
1142
- logger5.debug("Cache hit with valid TTL", { key, defaultTTL: ttlManager.getDefaultTTL() });
1444
+ const totalDuration = Date.now() - startTime;
1445
+ logger5.debug("CACHE_OP: Cache HIT with valid TTL", {
1446
+ key: keyStr,
1447
+ cacheCheckDuration,
1448
+ ttlCheckDuration,
1449
+ totalDuration,
1450
+ defaultTTL: ttlManager.getDefaultTTL()
1451
+ });
1143
1452
  statsManager.incrementHits();
1144
1453
  return cachedItem;
1145
1454
  } else {
1146
- logger5.debug("Cache item expired, removing", { key });
1455
+ logger5.debug("CACHE_OP: Cache item EXPIRED, removing from cache", {
1456
+ key: keyStr,
1457
+ cacheCheckDuration,
1458
+ ttlCheckDuration
1459
+ });
1147
1460
  cacheMap.delete(key);
1148
1461
  statsManager.incrementMisses();
1149
1462
  }
1150
1463
  } else {
1464
+ logger5.debug("CACHE_OP: Cache MISS (no item found)", {
1465
+ key: keyStr,
1466
+ cacheCheckDuration
1467
+ });
1151
1468
  statsManager.incrementMisses();
1152
1469
  }
1153
- logger5.debug("Cache miss or expired", { key, defaultTTL: ttlManager.getDefaultTTL() });
1470
+ logger5.debug("CACHE_OP: Proceeding to API fetch (TTL-enabled cache miss or expired)", {
1471
+ key: keyStr,
1472
+ defaultTTL: ttlManager.getDefaultTTL()
1473
+ });
1154
1474
  } else {
1475
+ const cacheCheckStart = Date.now();
1155
1476
  const cachedItem = await cacheMap.get(key);
1477
+ const cacheCheckDuration = Date.now() - cacheCheckStart;
1156
1478
  if (cachedItem) {
1157
- logger5.debug("Cache hit (TTL disabled)", { key });
1479
+ const totalDuration = Date.now() - startTime;
1480
+ logger5.debug("CACHE_OP: Cache HIT (TTL disabled)", {
1481
+ key: keyStr,
1482
+ cacheCheckDuration,
1483
+ totalDuration
1484
+ });
1158
1485
  statsManager.incrementHits();
1159
1486
  return cachedItem;
1160
1487
  } else {
1488
+ logger5.debug("CACHE_OP: Cache MISS (TTL disabled)", {
1489
+ key: keyStr,
1490
+ cacheCheckDuration
1491
+ });
1161
1492
  statsManager.incrementMisses();
1162
1493
  }
1163
1494
  }
1164
1495
  let ret;
1165
- const keyStr = keyToString(key);
1496
+ const requestKeyStr = keyToString(key);
1166
1497
  try {
1167
- const requestEntry = inFlightRequests.get(keyStr);
1498
+ const requestEntry = inFlightRequests.get(requestKeyStr);
1168
1499
  let apiRequest;
1500
+ const apiStartTime = Date.now();
1169
1501
  if (!requestEntry) {
1502
+ logger5.debug("CACHE_OP: Creating new API request", { key: keyStr });
1170
1503
  apiRequest = api.get(key);
1171
1504
  if (apiRequest && typeof apiRequest.then === "function") {
1172
1505
  const timestamp = Date.now();
1173
- inFlightRequests.set(keyStr, { promise: apiRequest, timestamp });
1174
- const cleanup = () => inFlightRequests.delete(keyStr);
1506
+ inFlightRequests.set(requestKeyStr, { promise: apiRequest, timestamp });
1507
+ const cleanup = () => inFlightRequests.delete(requestKeyStr);
1175
1508
  if (typeof apiRequest.finally === "function") {
1176
1509
  apiRequest.finally(cleanup);
1177
1510
  } else {
@@ -1179,37 +1512,90 @@ async function executeGetLogic(key, context) {
1179
1512
  }
1180
1513
  }
1181
1514
  } else {
1182
- logger5.debug("Using in-flight request for key", { key });
1515
+ logger5.debug("CACHE_OP: Using existing in-flight request", {
1516
+ key: keyStr,
1517
+ requestAge: Date.now() - requestEntry.timestamp
1518
+ });
1183
1519
  apiRequest = requestEntry.promise;
1184
1520
  }
1185
1521
  ret = await apiRequest;
1522
+ const apiDuration = Date.now() - apiStartTime;
1186
1523
  if (ret) {
1524
+ logger5.debug("CACHE_OP: API request successful, caching result", {
1525
+ key: keyStr,
1526
+ apiDuration,
1527
+ itemKeyMatches: JSON.stringify(ret.key) === keyStr
1528
+ });
1529
+ const cacheSetStart = Date.now();
1187
1530
  await cacheMap.set(ret.key, ret);
1188
- const keyStr2 = JSON.stringify(ret.key);
1189
- const metadata = await cacheMap.getMetadata(keyStr2);
1531
+ const cacheSetDuration = Date.now() - cacheSetStart;
1532
+ const itemKeyStr = JSON.stringify(ret.key);
1533
+ const metadataStart = Date.now();
1534
+ const metadata = await cacheMap.getMetadata(itemKeyStr);
1190
1535
  if (!metadata) {
1191
1536
  const now = Date.now();
1537
+ const estimatedSize = estimateValueSize(ret);
1192
1538
  const baseMetadata = {
1193
- key: keyStr2,
1539
+ key: itemKeyStr,
1194
1540
  addedAt: now,
1195
1541
  lastAccessedAt: now,
1196
1542
  accessCount: 1,
1197
- estimatedSize: estimateValueSize(ret)
1543
+ estimatedSize
1198
1544
  };
1199
- await cacheMap.setMetadata(keyStr2, baseMetadata);
1545
+ await cacheMap.setMetadata(itemKeyStr, baseMetadata);
1546
+ logger5.debug("CACHE_OP: Created base metadata for cached item", {
1547
+ key: itemKeyStr,
1548
+ estimatedSize
1549
+ });
1200
1550
  }
1201
- const evictedKeys = await context.evictionManager.onItemAdded(keyStr2, ret, cacheMap);
1202
- await ttlManager.onItemAdded(keyStr2, cacheMap);
1551
+ const metadataDuration = Date.now() - metadataStart;
1552
+ const evictionStart = Date.now();
1553
+ const evictedKeys = await context.evictionManager.onItemAdded(itemKeyStr, ret, cacheMap);
1554
+ const evictionDuration = Date.now() - evictionStart;
1555
+ if (evictedKeys.length > 0) {
1556
+ logger5.debug("CACHE_OP: Eviction triggered by new item", {
1557
+ key: itemKeyStr,
1558
+ evictedCount: evictedKeys.length,
1559
+ evictedKeys
1560
+ });
1561
+ }
1562
+ const ttlStart = Date.now();
1563
+ await ttlManager.onItemAdded(itemKeyStr, cacheMap);
1564
+ const ttlDuration = Date.now() - ttlStart;
1203
1565
  for (const evictedKey of evictedKeys) {
1204
1566
  const parsedKey = JSON.parse(evictedKey);
1205
1567
  await cacheMap.delete(parsedKey);
1568
+ logger5.debug("CACHE_OP: Removed evicted item", { evictedKey });
1206
1569
  }
1207
1570
  const event = CacheEventFactory.itemRetrieved(ret.key, ret, "api");
1208
1571
  context.eventEmitter.emit(event);
1572
+ const totalDuration = Date.now() - startTime;
1573
+ logger5.debug("CACHE_OP: get() completed successfully (cache miss)", {
1574
+ key: keyStr,
1575
+ apiDuration,
1576
+ cacheSetDuration,
1577
+ metadataDuration,
1578
+ evictionDuration,
1579
+ ttlDuration,
1580
+ totalDuration,
1581
+ evictedCount: evictedKeys.length
1582
+ });
1583
+ } else {
1584
+ logger5.debug("CACHE_OP: API returned null", {
1585
+ key: keyStr,
1586
+ apiDuration,
1587
+ totalDuration: Date.now() - startTime
1588
+ });
1209
1589
  }
1210
1590
  } catch (e) {
1211
- inFlightRequests.delete(keyStr);
1212
- logger5.error("Error getting item for key", { key, message: e.message, stack: e.stack });
1591
+ inFlightRequests.delete(requestKeyStr);
1592
+ const duration = Date.now() - startTime;
1593
+ logger5.error("CACHE_OP: Error in get() operation", {
1594
+ key: keyStr,
1595
+ duration,
1596
+ message: e.message,
1597
+ stack: e.stack
1598
+ });
1213
1599
  throw e;
1214
1600
  }
1215
1601
  return ret || null;
@@ -1221,43 +1607,88 @@ import {
1221
1607
  } from "@fjell/core";
1222
1608
  var logger6 = logger_default.get("retrieve");
1223
1609
  var retrieve = async (key, context) => {
1610
+ const startTime = Date.now();
1224
1611
  const { cacheMap, pkType, statsManager } = context;
1612
+ const keyStr = JSON.stringify(key);
1225
1613
  logger6.default("retrieve", { key });
1614
+ logger6.debug("CACHE_OP: retrieve() started", {
1615
+ key: keyStr,
1616
+ cacheType: cacheMap.implementationType,
1617
+ bypassEnabled: !!context.options?.bypassCache
1618
+ });
1226
1619
  statsManager.incrementRequests();
1227
1620
  if (!isValidItemKey2(key)) {
1228
- logger6.error("Key for Retrieve is not a valid ItemKey: %j", key);
1621
+ logger6.error("CACHE_OP: Invalid key for retrieve", { key: keyStr });
1229
1622
  throw new Error("Key for Retrieve is not a valid ItemKey");
1230
1623
  }
1231
1624
  if (context.options?.bypassCache) {
1232
- logger6.debug("Cache bypass enabled, fetching directly from API", { key });
1625
+ logger6.debug("CACHE_OP: Cache bypass enabled, fetching directly from API", { key: keyStr });
1233
1626
  statsManager.incrementMisses();
1234
1627
  try {
1628
+ const apiStartTime = Date.now();
1235
1629
  const { api } = context;
1236
1630
  const retrieved2 = await api.get(key);
1631
+ const apiDuration = Date.now() - apiStartTime;
1237
1632
  if (retrieved2) {
1238
- logger6.debug("API response received (not cached due to bypass)", { key });
1633
+ logger6.debug("CACHE_OP: API response received (bypass mode)", {
1634
+ key: keyStr,
1635
+ apiDuration,
1636
+ hasValue: true
1637
+ });
1239
1638
  return [null, retrieved2];
1240
1639
  } else {
1241
- logger6.debug("API returned null", { key });
1640
+ logger6.debug("CACHE_OP: API returned null (bypass mode)", {
1641
+ key: keyStr,
1642
+ apiDuration
1643
+ });
1242
1644
  return [null, null];
1243
1645
  }
1244
1646
  } catch (error) {
1245
- logger6.error("API request failed", { key, error });
1647
+ const duration = Date.now() - startTime;
1648
+ logger6.error("CACHE_OP: API request failed in bypass mode", {
1649
+ key: keyStr,
1650
+ duration,
1651
+ error
1652
+ });
1246
1653
  throw error;
1247
1654
  }
1248
1655
  }
1249
1656
  const containsItemKey = await cacheMap.includesKey(key);
1657
+ logger6.debug("CACHE_OP: Cache key check completed", {
1658
+ key: keyStr,
1659
+ exists: containsItemKey
1660
+ });
1250
1661
  let retrieved;
1251
1662
  let contextToReturn;
1252
1663
  if (containsItemKey) {
1253
1664
  logger6.default("Looking for Object in Cache", key);
1665
+ logger6.debug("CACHE_OP: Cache HIT - retrieving from cache", { key: keyStr });
1666
+ const getStartTime = Date.now();
1254
1667
  retrieved = await cacheMap.get(key);
1668
+ const getDuration = Date.now() - getStartTime;
1255
1669
  contextToReturn = null;
1256
1670
  statsManager.incrementHits();
1671
+ const totalDuration = Date.now() - startTime;
1672
+ logger6.debug("CACHE_OP: retrieve() completed (cache hit)", {
1673
+ key: keyStr,
1674
+ getDuration,
1675
+ totalDuration,
1676
+ hasValue: !!retrieved
1677
+ });
1257
1678
  } else {
1258
1679
  logger6.default("Object Not Found in Cache, Retrieving from Server API", { key });
1680
+ logger6.debug("CACHE_OP: Cache MISS - fetching from API", { key: keyStr });
1259
1681
  statsManager.incrementMisses();
1682
+ const apiStartTime = Date.now();
1260
1683
  [contextToReturn, retrieved] = await get(key, context);
1684
+ const apiDuration = Date.now() - apiStartTime;
1685
+ const totalDuration = Date.now() - startTime;
1686
+ logger6.debug("CACHE_OP: retrieve() completed (cache miss)", {
1687
+ key: keyStr,
1688
+ apiDuration,
1689
+ totalDuration,
1690
+ hasValue: !!retrieved
1691
+ });
1261
1692
  }
1262
1693
  const retValue = [
1263
1694
  contextToReturn,
@@ -1752,44 +2183,107 @@ async function executeFindLogic(finder, params, locations, context) {
1752
2183
  }
1753
2184
  }
1754
2185
  const queryHash = createFinderHash(finder, params, locations);
1755
- logger14.debug("Generated query hash for find", { queryHash, finder, params, locations });
2186
+ logger14.debug("QUERY_CACHE: Generated query hash for find()", {
2187
+ queryHash,
2188
+ finder,
2189
+ params: JSON.stringify(params),
2190
+ locations: JSON.stringify(locations)
2191
+ });
2192
+ logger14.debug("QUERY_CACHE: Checking query cache for hash", { queryHash });
1756
2193
  const cachedItemKeys = await cacheMap.getQueryResult(queryHash);
1757
2194
  if (cachedItemKeys) {
1758
- logger14.debug("Using cached query results", { cachedKeyCount: cachedItemKeys.length, queryHash });
2195
+ logger14.debug("QUERY_CACHE: Cache HIT - Found cached query result", {
2196
+ queryHash,
2197
+ cachedKeyCount: cachedItemKeys.length,
2198
+ itemKeys: cachedItemKeys.map((k) => JSON.stringify(k))
2199
+ });
1759
2200
  const cachedItems = [];
1760
2201
  let allItemsAvailable = true;
2202
+ const missingKeys = [];
1761
2203
  for (const itemKey of cachedItemKeys) {
1762
2204
  const item = await cacheMap.get(itemKey);
1763
2205
  if (item) {
1764
2206
  cachedItems.push(item);
2207
+ logger14.debug("QUERY_CACHE: Retrieved cached item", {
2208
+ itemKey: JSON.stringify(itemKey),
2209
+ itemKeyStr: JSON.stringify(item.key)
2210
+ });
1765
2211
  } else {
1766
2212
  allItemsAvailable = false;
2213
+ missingKeys.push(itemKey);
2214
+ logger14.debug("QUERY_CACHE: Cached item MISSING from item cache", {
2215
+ itemKey: JSON.stringify(itemKey),
2216
+ queryHash
2217
+ });
1767
2218
  break;
1768
2219
  }
1769
2220
  }
1770
2221
  if (allItemsAvailable) {
2222
+ logger14.debug("QUERY_CACHE: All cached items available, returning from cache", {
2223
+ queryHash,
2224
+ itemCount: cachedItems.length
2225
+ });
1771
2226
  return cachedItems;
1772
2227
  } else {
1773
- logger14.debug("Some cached items missing, invalidating query cache");
2228
+ logger14.debug("QUERY_CACHE: Some cached items missing, invalidating query cache", {
2229
+ queryHash,
2230
+ missingKeys: missingKeys.map((k) => JSON.stringify(k)),
2231
+ foundCount: cachedItems.length,
2232
+ expectedCount: cachedItemKeys.length
2233
+ });
1774
2234
  cacheMap.deleteQueryResult(queryHash);
1775
2235
  }
2236
+ } else {
2237
+ logger14.debug("QUERY_CACHE: Cache MISS - No cached query result found", { queryHash });
1776
2238
  }
2239
+ logger14.debug("QUERY_CACHE: Fetching from API (cache miss or invalid)", {
2240
+ queryHash,
2241
+ finder,
2242
+ params: JSON.stringify(params),
2243
+ locations: JSON.stringify(locations)
2244
+ });
1777
2245
  const ret = await api.find(finder, params, locations);
2246
+ logger14.debug("QUERY_CACHE: API response received", {
2247
+ queryHash,
2248
+ itemCount: ret.length,
2249
+ itemKeys: ret.map((item) => JSON.stringify(item.key))
2250
+ });
2251
+ logger14.debug("QUERY_CACHE: Storing items in item cache", {
2252
+ queryHash,
2253
+ itemCount: ret.length
2254
+ });
1778
2255
  for (const v of ret) {
1779
2256
  await cacheMap.set(v.key, v);
2257
+ logger14.debug("QUERY_CACHE: Stored item in cache", {
2258
+ itemKey: JSON.stringify(v.key),
2259
+ queryHash
2260
+ });
1780
2261
  const keyStr = JSON.stringify(v.key);
1781
2262
  ttlManager.onItemAdded(keyStr, cacheMap);
1782
2263
  const evictedKeys = await context.evictionManager.onItemAdded(keyStr, v, cacheMap);
1783
2264
  for (const evictedKey of evictedKeys) {
1784
2265
  const parsedKey = JSON.parse(evictedKey);
1785
2266
  await cacheMap.delete(parsedKey);
2267
+ logger14.debug("QUERY_CACHE: Evicted item due to cache limits", {
2268
+ evictedKey,
2269
+ queryHash
2270
+ });
1786
2271
  }
1787
2272
  }
1788
2273
  const itemKeys = ret.map((item) => item.key);
1789
- cacheMap.setQueryResult(queryHash, itemKeys);
1790
- logger14.debug("Cached query result", { queryHash, itemKeyCount: itemKeys.length });
2274
+ await cacheMap.setQueryResult(queryHash, itemKeys);
2275
+ logger14.debug("QUERY_CACHE: Stored query result in query cache", {
2276
+ queryHash,
2277
+ itemKeyCount: itemKeys.length,
2278
+ itemKeys: itemKeys.map((k) => JSON.stringify(k))
2279
+ });
1791
2280
  const event = CacheEventFactory.createQueryEvent(params, locations, ret);
1792
2281
  eventEmitter.emit(event);
2282
+ logger14.debug("QUERY_CACHE: Emitted query event", { queryHash });
2283
+ logger14.debug("QUERY_CACHE: find() operation completed", {
2284
+ queryHash,
2285
+ resultCount: ret.length
2286
+ });
1793
2287
  return ret;
1794
2288
  }
1795
2289
 
@@ -1827,34 +2321,86 @@ async function executeFindOneLogic(finder, finderParams, locations, context) {
1827
2321
  }
1828
2322
  }
1829
2323
  const queryHash = createFinderHash(finder, finderParams, locations);
1830
- logger15.debug("Generated query hash for findOne", { queryHash });
2324
+ logger15.debug("QUERY_CACHE: Generated query hash for findOne()", {
2325
+ queryHash,
2326
+ finder,
2327
+ finderParams: JSON.stringify(finderParams),
2328
+ locations: JSON.stringify(locations)
2329
+ });
2330
+ logger15.debug("QUERY_CACHE: Checking query cache for hash", { queryHash });
1831
2331
  const cachedItemKeys = await cacheMap.getQueryResult(queryHash);
1832
2332
  if (cachedItemKeys && cachedItemKeys.length > 0) {
1833
- logger15.debug("Using cached query results", { cachedKeyCount: cachedItemKeys.length });
1834
- const item = await cacheMap.get(cachedItemKeys[0]);
2333
+ logger15.debug("QUERY_CACHE: Cache HIT - Found cached query result", {
2334
+ queryHash,
2335
+ cachedKeyCount: cachedItemKeys.length,
2336
+ itemKeys: cachedItemKeys.map((k) => JSON.stringify(k))
2337
+ });
2338
+ const itemKey = cachedItemKeys[0];
2339
+ logger15.debug("QUERY_CACHE: Retrieving first cached item", {
2340
+ queryHash,
2341
+ itemKey: JSON.stringify(itemKey)
2342
+ });
2343
+ const item = await cacheMap.get(itemKey);
1835
2344
  if (item) {
2345
+ logger15.debug("QUERY_CACHE: Retrieved cached item successfully", {
2346
+ queryHash,
2347
+ itemKey: JSON.stringify(itemKey),
2348
+ itemKeyStr: JSON.stringify(item.key)
2349
+ });
1836
2350
  return item;
1837
2351
  } else {
1838
- logger15.debug("Cached item missing, invalidating query cache");
2352
+ logger15.debug("QUERY_CACHE: Cached item MISSING from item cache, invalidating query cache", {
2353
+ queryHash,
2354
+ itemKey: JSON.stringify(itemKey)
2355
+ });
1839
2356
  cacheMap.deleteQueryResult(queryHash);
1840
2357
  }
2358
+ } else {
2359
+ logger15.debug("QUERY_CACHE: Cache MISS - No cached query result found", { queryHash });
1841
2360
  }
2361
+ logger15.debug("QUERY_CACHE: Fetching from API (cache miss or invalid)", {
2362
+ queryHash,
2363
+ finder,
2364
+ finderParams: JSON.stringify(finderParams),
2365
+ locations: JSON.stringify(locations)
2366
+ });
1842
2367
  const ret = await api.findOne(finder, finderParams, locations);
1843
2368
  if (ret === null) {
2369
+ logger15.debug("QUERY_CACHE: API returned null, throwing error", { queryHash, finder });
1844
2370
  throw new Error(`findOne returned null for finder: ${finder}`);
1845
2371
  }
1846
- cacheMap.set(ret.key, ret);
2372
+ logger15.debug("QUERY_CACHE: API response received", {
2373
+ queryHash,
2374
+ itemKey: JSON.stringify(ret.key)
2375
+ });
2376
+ logger15.debug("QUERY_CACHE: Storing item in item cache", {
2377
+ queryHash,
2378
+ itemKey: JSON.stringify(ret.key)
2379
+ });
2380
+ await cacheMap.set(ret.key, ret);
1847
2381
  const keyStr = JSON.stringify(ret.key);
1848
2382
  ttlManager.onItemAdded(keyStr, cacheMap);
1849
2383
  const evictedKeys = await context.evictionManager.onItemAdded(keyStr, ret, cacheMap);
1850
2384
  for (const evictedKey of evictedKeys) {
1851
2385
  const parsedKey = JSON.parse(evictedKey);
1852
2386
  await cacheMap.delete(parsedKey);
2387
+ logger15.debug("QUERY_CACHE: Evicted item due to cache limits", {
2388
+ evictedKey,
2389
+ queryHash
2390
+ });
1853
2391
  }
1854
- cacheMap.setQueryResult(queryHash, [ret.key]);
1855
- logger15.debug("Cached query result", { queryHash, itemKey: ret.key });
2392
+ await cacheMap.setQueryResult(queryHash, [ret.key]);
2393
+ logger15.debug("QUERY_CACHE: Stored query result in query cache", {
2394
+ queryHash,
2395
+ itemKey: JSON.stringify(ret.key)
2396
+ });
1856
2397
  const event = CacheEventFactory.createQueryEvent(finderParams, locations, [ret]);
1857
2398
  eventEmitter.emit(event);
2399
+ logger15.debug("QUERY_CACHE: Emitted query event", { queryHash });
2400
+ logger15.debug("QUERY_CACHE: findOne() operation completed", {
2401
+ queryHash,
2402
+ itemKey: JSON.stringify(ret.key)
2403
+ });
1858
2404
  return ret;
1859
2405
  }
1860
2406
 
@@ -1912,39 +2458,93 @@ var normalizeKey = (key) => {
1912
2458
  return key;
1913
2459
  };
1914
2460
  var set = async (key, v, context) => {
2461
+ const startTime = Date.now();
1915
2462
  const { cacheMap, pkType, ttlManager, evictionManager, eventEmitter } = context;
2463
+ const keyStr = JSON.stringify(key);
1916
2464
  logger16.default("set", { key, v });
2465
+ logger16.debug("CACHE_OP: set() started", {
2466
+ key: keyStr,
2467
+ cacheType: cacheMap.implementationType
2468
+ });
1917
2469
  if (!isValidItemKey6(key)) {
1918
- logger16.error("Key for Set is not a valid ItemKey: %j", key);
2470
+ logger16.error("CACHE_OP: Invalid key for set", { key: keyStr });
1919
2471
  throw new Error("Key for Set is not a valid ItemKey");
1920
2472
  }
1921
2473
  if (!isItemKeyEqualNormalized(key, v.key)) {
1922
- logger16.error("Key does not match item key: %j != %j", key, v.key);
2474
+ logger16.error("CACHE_OP: Key mismatch in set", {
2475
+ providedKey: keyStr,
2476
+ itemKey: JSON.stringify(v.key)
2477
+ });
1923
2478
  throw new Error("Key does not match item key");
1924
2479
  }
2480
+ const checkStartTime = Date.now();
1925
2481
  const previousItem = await cacheMap.get(key);
2482
+ const checkDuration = Date.now() - checkStartTime;
2483
+ logger16.debug("CACHE_OP: Previous item check", {
2484
+ key: keyStr,
2485
+ hadPreviousItem: !!previousItem,
2486
+ checkDuration
2487
+ });
2488
+ const setStartTime = Date.now();
1926
2489
  await cacheMap.set(key, v);
1927
- const keyStr = JSON.stringify(key);
2490
+ const setDuration = Date.now() - setStartTime;
2491
+ const metadataStartTime = Date.now();
1928
2492
  const metadata = await cacheMap.getMetadata(keyStr);
1929
2493
  if (!metadata) {
1930
2494
  const now = Date.now();
2495
+ const estimatedSize = estimateValueSize(v);
1931
2496
  const baseMetadata = {
1932
2497
  key: keyStr,
1933
2498
  addedAt: now,
1934
2499
  lastAccessedAt: now,
1935
2500
  accessCount: 1,
1936
- estimatedSize: estimateValueSize(v)
2501
+ estimatedSize
1937
2502
  };
1938
2503
  await cacheMap.setMetadata(keyStr, baseMetadata);
2504
+ logger16.debug("CACHE_OP: Created base metadata", {
2505
+ key: keyStr,
2506
+ estimatedSize
2507
+ });
2508
+ } else {
2509
+ logger16.debug("CACHE_OP: Metadata already exists", {
2510
+ key: keyStr,
2511
+ addedAt: new Date(metadata.addedAt).toISOString(),
2512
+ accessCount: metadata.accessCount
2513
+ });
1939
2514
  }
2515
+ const metadataDuration = Date.now() - metadataStartTime;
2516
+ const ttlStartTime = Date.now();
1940
2517
  await ttlManager.onItemAdded(keyStr, cacheMap);
2518
+ const ttlDuration = Date.now() - ttlStartTime;
2519
+ const evictionStartTime = Date.now();
1941
2520
  const evictedKeys = await evictionManager.onItemAdded(keyStr, v, cacheMap);
2521
+ const evictionDuration = Date.now() - evictionStartTime;
2522
+ if (evictedKeys.length > 0) {
2523
+ logger16.debug("CACHE_OP: Eviction triggered by set", {
2524
+ key: keyStr,
2525
+ evictedCount: evictedKeys.length,
2526
+ evictedKeys
2527
+ });
2528
+ }
1942
2529
  for (const evictedKey of evictedKeys) {
1943
2530
  const parsedKey = JSON.parse(evictedKey);
1944
2531
  await cacheMap.delete(parsedKey);
2532
+ logger16.debug("CACHE_OP: Removed evicted item", { evictedKey });
1945
2533
  }
1946
2534
  const event = CacheEventFactory.itemSet(key, v, previousItem);
1947
2535
  eventEmitter.emit(event);
2536
+ const totalDuration = Date.now() - startTime;
2537
+ logger16.debug("CACHE_OP: set() completed", {
2538
+ key: keyStr,
2539
+ checkDuration,
2540
+ setDuration,
2541
+ metadataDuration,
2542
+ ttlDuration,
2543
+ evictionDuration,
2544
+ totalDuration,
2545
+ evictedCount: evictedKeys.length,
2546
+ wasUpdate: !!previousItem
2547
+ });
1948
2548
  return [context, v];
1949
2549
  };
1950
2550
 
@@ -5122,9 +5722,17 @@ var EvictionManager = class {
5122
5722
  return;
5123
5723
  }
5124
5724
  try {
5725
+ logger24.debug("EVICTION: Item accessed, updating metadata", {
5726
+ key,
5727
+ strategy: this.evictionStrategy.getStrategyName()
5728
+ });
5125
5729
  await this.evictionStrategy.onItemAccessed(key, metadataProvider);
5126
5730
  } catch (error) {
5127
- logger24.error("Error in eviction strategy onItemAccessed", { key, error });
5731
+ logger24.error("EVICTION: Error in eviction strategy onItemAccessed", {
5732
+ key,
5733
+ error,
5734
+ strategy: this.evictionStrategy?.getStrategyName()
5735
+ });
5128
5736
  }
5129
5737
  }
5130
5738
  /**
@@ -5135,28 +5743,81 @@ var EvictionManager = class {
5135
5743
  * @returns Array of keys that were evicted
5136
5744
  */
5137
5745
  async onItemAdded(key, value, metadataProvider) {
5746
+ const startTime = Date.now();
5138
5747
  const evictedKeys = [];
5139
5748
  if (!this.evictionStrategy) {
5749
+ logger24.debug("EVICTION: No eviction strategy configured", { key });
5140
5750
  return evictedKeys;
5141
5751
  }
5142
5752
  try {
5143
5753
  const estimatedSize = estimateValueSize(value);
5754
+ logger24.debug("EVICTION: Item addition started", {
5755
+ key,
5756
+ estimatedSize,
5757
+ strategy: this.evictionStrategy.getStrategyName()
5758
+ });
5759
+ const contextStartTime = Date.now();
5144
5760
  const context = await this.createEvictionContext(metadataProvider, estimatedSize);
5761
+ const contextDuration = Date.now() - contextStartTime;
5762
+ logger24.debug("EVICTION: Current cache state", {
5763
+ key,
5764
+ currentItemCount: context.currentSize.itemCount,
5765
+ currentSizeBytes: context.currentSize.sizeBytes,
5766
+ maxItems: context.limits.maxItems,
5767
+ maxSizeBytes: context.limits.maxSizeBytes,
5768
+ newItemSize: estimatedSize,
5769
+ contextDuration
5770
+ });
5771
+ const selectionStartTime = Date.now();
5145
5772
  const keysToEvict = await this.evictionStrategy.selectForEviction(metadataProvider, context);
5773
+ const selectionDuration = Date.now() - selectionStartTime;
5774
+ if (keysToEvict.length > 0) {
5775
+ logger24.debug("EVICTION: Items selected for eviction", {
5776
+ key,
5777
+ evictCount: keysToEvict.length,
5778
+ keysToEvict,
5779
+ selectionDuration,
5780
+ strategy: this.evictionStrategy.getStrategyName()
5781
+ });
5782
+ }
5783
+ const removalStartTime = Date.now();
5146
5784
  for (const evictKey of keysToEvict) {
5147
5785
  await this.evictionStrategy.onItemRemoved(evictKey, metadataProvider);
5148
5786
  evictedKeys.push(evictKey);
5787
+ logger24.debug("EVICTION: Marked item for eviction", {
5788
+ evictedKey: evictKey,
5789
+ newKey: key
5790
+ });
5149
5791
  }
5792
+ const removalDuration = Date.now() - removalStartTime;
5793
+ const addMetadataStart = Date.now();
5150
5794
  await this.evictionStrategy.onItemAdded(key, estimatedSize, metadataProvider);
5795
+ const addMetadataDuration = Date.now() - addMetadataStart;
5796
+ const totalDuration = Date.now() - startTime;
5151
5797
  if (evictedKeys.length > 0) {
5152
- logger24.debug("Items evicted during addition", {
5798
+ logger24.debug("EVICTION: Eviction completed", {
5153
5799
  newKey: key,
5800
+ evictedCount: evictedKeys.length,
5154
5801
  evictedKeys,
5155
- strategy: this.evictionStrategy.getStrategyName()
5802
+ strategy: this.evictionStrategy.getStrategyName(),
5803
+ selectionDuration,
5804
+ removalDuration,
5805
+ addMetadataDuration,
5806
+ totalDuration
5807
+ });
5808
+ } else {
5809
+ logger24.debug("EVICTION: No eviction needed", {
5810
+ newKey: key,
5811
+ estimatedSize,
5812
+ totalDuration
5156
5813
  });
5157
5814
  }
5158
5815
  } catch (error) {
5159
- logger24.error("Error in eviction strategy onItemAdded", { key, error });
5816
+ logger24.error("EVICTION: Error in eviction strategy onItemAdded", {
5817
+ key,
5818
+ error,
5819
+ strategy: this.evictionStrategy?.getStrategyName()
5820
+ });
5160
5821
  }
5161
5822
  return evictedKeys;
5162
5823
  }
@@ -5181,25 +5842,47 @@ var EvictionManager = class {
5181
5842
  * @returns Array of keys that were evicted
5182
5843
  */
5183
5844
  async performEviction(metadataProvider) {
5845
+ const startTime = Date.now();
5184
5846
  const evictedKeys = [];
5185
5847
  if (!this.evictionStrategy) {
5848
+ logger24.debug("EVICTION: No eviction strategy configured for manual eviction");
5186
5849
  return evictedKeys;
5187
5850
  }
5188
5851
  try {
5852
+ logger24.debug("EVICTION: Manual eviction started", {
5853
+ strategy: this.evictionStrategy.getStrategyName()
5854
+ });
5189
5855
  const context = await this.createEvictionContext(metadataProvider);
5856
+ logger24.debug("EVICTION: Manual eviction - current cache state", {
5857
+ currentItemCount: context.currentSize.itemCount,
5858
+ currentSizeBytes: context.currentSize.sizeBytes,
5859
+ maxItems: context.limits.maxItems,
5860
+ maxSizeBytes: context.limits.maxSizeBytes
5861
+ });
5190
5862
  const keysToEvict = await this.evictionStrategy.selectForEviction(metadataProvider, context);
5191
5863
  for (const evictKey of keysToEvict) {
5192
5864
  await this.evictionStrategy.onItemRemoved(evictKey, metadataProvider);
5193
5865
  evictedKeys.push(evictKey);
5194
5866
  }
5867
+ const duration = Date.now() - startTime;
5195
5868
  if (evictedKeys.length > 0) {
5196
- logger24.debug("Manual eviction performed", {
5869
+ logger24.debug("EVICTION: Manual eviction completed", {
5870
+ evictedCount: evictedKeys.length,
5197
5871
  evictedKeys,
5198
- strategy: this.evictionStrategy.getStrategyName()
5872
+ strategy: this.evictionStrategy.getStrategyName(),
5873
+ duration
5874
+ });
5875
+ } else {
5876
+ logger24.debug("EVICTION: Manual eviction - no items to evict", {
5877
+ strategy: this.evictionStrategy.getStrategyName(),
5878
+ duration
5199
5879
  });
5200
5880
  }
5201
5881
  } catch (error) {
5202
- logger24.error("Error in manual eviction", { error });
5882
+ logger24.error("EVICTION: Error in manual eviction", {
5883
+ error,
5884
+ strategy: this.evictionStrategy?.getStrategyName()
5885
+ });
5203
5886
  }
5204
5887
  return evictedKeys;
5205
5888
  }
@@ -6628,7 +7311,7 @@ var TTLManager = class {
6628
7311
  metadata
6629
7312
  });
6630
7313
  if (!metadata) {
6631
- logger25.warning("TTL_DEBUG: No metadata found for item when setting TTL", {
7314
+ logger25.debug("TTL_DEBUG: No metadata found for item when setting TTL", {
6632
7315
  key,
6633
7316
  metadataProviderType: metadataProvider?.constructor?.name,
6634
7317
  metadataProviderMethods: metadataProvider ? Object.getOwnPropertyNames(Object.getPrototypeOf(metadataProvider)) : null
@@ -6668,12 +7351,28 @@ var TTLManager = class {
6668
7351
  async isExpired(key, metadataProvider) {
6669
7352
  const metadata = await metadataProvider.getMetadata(key);
6670
7353
  if (!metadata || !metadata.expiresAt) {
7354
+ logger25.debug("TTL_CHECK: No TTL set for item", { key, hasMetadata: !!metadata });
6671
7355
  return false;
6672
7356
  }
6673
7357
  const now = Date.now();
6674
7358
  const expired = now >= metadata.expiresAt;
7359
+ const remainingMs = metadata.expiresAt - now;
6675
7360
  if (expired) {
6676
- logger25.trace("Item expired", { key, expiresAt: metadata.expiresAt, now });
7361
+ logger25.debug("TTL_CHECK: Item EXPIRED", {
7362
+ key,
7363
+ expiresAt: new Date(metadata.expiresAt).toISOString(),
7364
+ now: new Date(now).toISOString(),
7365
+ expiredByMs: now - metadata.expiresAt,
7366
+ ttl: metadata.ttl
7367
+ });
7368
+ } else {
7369
+ logger25.debug("TTL_CHECK: Item still valid", {
7370
+ key,
7371
+ expiresAt: new Date(metadata.expiresAt).toISOString(),
7372
+ remainingMs,
7373
+ remainingSec: Math.floor(remainingMs / 1e3),
7374
+ ttl: metadata.ttl
7375
+ });
6677
7376
  }
6678
7377
  return expired;
6679
7378
  }
@@ -6683,9 +7382,22 @@ var TTLManager = class {
6683
7382
  */
6684
7383
  async validateItem(key, metadataProvider) {
6685
7384
  if (!this.config.validateOnAccess) {
7385
+ logger25.debug("TTL_VALIDATE: Validation disabled, skipping check", { key });
6686
7386
  return true;
6687
7387
  }
6688
- return !await this.isExpired(key, metadataProvider);
7388
+ logger25.debug("TTL_VALIDATE: Validating item", {
7389
+ key,
7390
+ ttlEnabled: this.isTTLEnabled(),
7391
+ defaultTTL: this.config.defaultTTL
7392
+ });
7393
+ const isExpired = await this.isExpired(key, metadataProvider);
7394
+ const isValid = !isExpired;
7395
+ logger25.debug("TTL_VALIDATE: Validation result", {
7396
+ key,
7397
+ isValid,
7398
+ isExpired
7399
+ });
7400
+ return isValid;
6689
7401
  }
6690
7402
  /**
6691
7403
  * Get TTL information for an item
@@ -6710,17 +7422,44 @@ var TTLManager = class {
6710
7422
  * Find all expired items
6711
7423
  */
6712
7424
  async findExpiredItems(metadataProvider) {
7425
+ const startTime = Date.now();
6713
7426
  const expiredKeys = [];
6714
7427
  const allMetadata = await metadataProvider.getAllMetadata();
6715
7428
  const now = Date.now();
7429
+ logger25.debug("TTL_CLEANUP: Scanning for expired items", {
7430
+ totalItems: allMetadata.size,
7431
+ now: new Date(now).toISOString()
7432
+ });
7433
+ let itemsWithTTL = 0;
6716
7434
  for (const [key, metadata] of allMetadata) {
6717
7435
  const ttlMetadata = metadata;
6718
- if (ttlMetadata.expiresAt && now >= ttlMetadata.expiresAt) {
6719
- expiredKeys.push(key);
7436
+ if (ttlMetadata.expiresAt) {
7437
+ itemsWithTTL++;
7438
+ if (now >= ttlMetadata.expiresAt) {
7439
+ expiredKeys.push(key);
7440
+ logger25.debug("TTL_CLEANUP: Found expired item", {
7441
+ key,
7442
+ expiresAt: new Date(ttlMetadata.expiresAt).toISOString(),
7443
+ expiredByMs: now - ttlMetadata.expiresAt
7444
+ });
7445
+ }
6720
7446
  }
6721
7447
  }
7448
+ const duration = Date.now() - startTime;
6722
7449
  if (expiredKeys.length > 0) {
6723
- logger25.debug("Found expired items", { count: expiredKeys.length, keys: expiredKeys });
7450
+ logger25.debug("TTL_CLEANUP: Expired items found", {
7451
+ expiredCount: expiredKeys.length,
7452
+ totalItems: allMetadata.size,
7453
+ itemsWithTTL,
7454
+ keys: expiredKeys,
7455
+ duration
7456
+ });
7457
+ } else {
7458
+ logger25.debug("TTL_CLEANUP: No expired items found", {
7459
+ totalItems: allMetadata.size,
7460
+ itemsWithTTL,
7461
+ duration
7462
+ });
6724
7463
  }
6725
7464
  return expiredKeys;
6726
7465
  }