@fjell/cache 4.7.42 → 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
  }
@@ -191,6 +240,9 @@ var TwoLayerCacheMap = class _TwoLayerCacheMap extends CacheMap {
191
240
  * Determine if a query result is complete or partial based on query hash
192
241
  */
193
242
  determineQueryCompleteness(queryHash, itemKeys) {
243
+ if (queryHash.includes('"query":{}') || queryHash.includes('"query": {}')) {
244
+ return true;
245
+ }
194
246
  if (queryHash.includes("facet:") || queryHash.includes("filter:")) {
195
247
  return false;
196
248
  }
@@ -304,18 +356,40 @@ var TwoLayerCacheMap = class _TwoLayerCacheMap extends CacheMap {
304
356
  * Clean up expired queries
305
357
  */
306
358
  async cleanup() {
359
+ const startTime = Date.now();
307
360
  const now = /* @__PURE__ */ new Date();
308
361
  const expiredQueries = [];
362
+ logger.debug("TWO_LAYER: Starting query cleanup", {
363
+ totalQueries: this.queryMetadataMap.size,
364
+ now: now.toISOString()
365
+ });
309
366
  for (const [queryHash, metadata] of this.queryMetadataMap.entries()) {
310
367
  if (metadata.expiresAt < now) {
311
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
+ });
312
376
  }
313
377
  }
314
378
  for (const queryHash of expiredQueries) {
315
379
  await this.deleteQueryResult(queryHash);
316
380
  }
317
- if (this.options.debug && expiredQueries.length > 0) {
318
- 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
+ });
319
393
  }
320
394
  return expiredQueries.length;
321
395
  }
@@ -327,24 +401,68 @@ var TwoLayerCacheMap = class _TwoLayerCacheMap extends CacheMap {
327
401
  // The types are accessible through super.types
328
402
  // ===== MISSING ABSTRACT METHODS FROM CacheMap =====
329
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
+ });
330
409
  if ("invalidateItemKeys" in this.underlyingCache && typeof this.underlyingCache.invalidateItemKeys === "function") {
331
410
  await this.underlyingCache.invalidateItemKeys(keys);
332
411
  }
412
+ let totalInvalidatedQueries = 0;
333
413
  for (const key of keys) {
414
+ const beforeCount = this.queryMetadataMap.size;
334
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
+ }
335
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
+ });
336
432
  }
337
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
+ });
338
440
  if ("invalidateLocation" in this.underlyingCache && typeof this.underlyingCache.invalidateLocation === "function") {
339
441
  await this.underlyingCache.invalidateLocation(locations);
340
442
  }
341
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
+ });
342
450
  }
343
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
+ });
344
457
  if ("clearQueryResults" in this.underlyingCache && typeof this.underlyingCache.clearQueryResults === "function") {
345
458
  await this.underlyingCache.clearQueryResults();
346
459
  }
347
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
+ });
348
466
  }
349
467
  /**
350
468
  * Check if two-layer mode is enabled
@@ -699,66 +817,151 @@ async function executeAllLogic(query, locations, context) {
699
817
  }
700
818
  }
701
819
  const queryHash = createQueryHash(pkType, query, locations);
702
- 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 });
703
827
  const cachedItemKeys = await cacheMap.getQueryResult(queryHash);
704
828
  if (cachedItemKeys) {
705
- 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
+ });
706
834
  const cachedItems = [];
707
835
  let allItemsAvailable = true;
836
+ const missingKeys = [];
708
837
  for (const itemKey of cachedItemKeys) {
709
838
  const item = await cacheMap.get(itemKey);
710
839
  if (item) {
711
840
  cachedItems.push(item);
841
+ logger2.debug("QUERY_CACHE: Retrieved cached item", {
842
+ itemKey: JSON.stringify(itemKey),
843
+ itemKeyStr: JSON.stringify(item.key)
844
+ });
712
845
  } else {
713
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
+ });
714
852
  break;
715
853
  }
716
854
  }
717
855
  if (allItemsAvailable) {
856
+ logger2.debug("QUERY_CACHE: All cached items available, returning from cache", {
857
+ queryHash,
858
+ itemCount: cachedItems.length
859
+ });
718
860
  return cachedItems;
719
861
  } else {
720
- 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
+ });
721
868
  cacheMap.deleteQueryResult(queryHash);
722
869
  }
870
+ } else {
871
+ logger2.debug("QUERY_CACHE: Cache MISS - No cached query result found", { queryHash });
723
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
+ });
724
878
  try {
725
879
  const directCachedItems = await cacheMap.queryIn(query, locations);
726
880
  if (directCachedItems && directCachedItems.length > 0) {
727
- 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
+ });
728
886
  const itemKeys = directCachedItems.map((item) => item.key);
729
887
  await cacheMap.setQueryResult(queryHash, itemKeys);
730
- 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
+ });
731
893
  return directCachedItems;
894
+ } else {
895
+ logger2.debug("QUERY_CACHE: Direct cache query returned no items", { queryHash });
732
896
  }
733
897
  } catch (error) {
734
- 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
+ });
735
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
+ });
736
908
  let ret = [];
737
909
  try {
738
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
+ });
739
920
  for (const v of ret) {
740
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
+ });
741
926
  const keyStr = JSON.stringify(v.key);
742
927
  ttlManager.onItemAdded(keyStr, cacheMap);
743
928
  const evictedKeys = await context.evictionManager.onItemAdded(keyStr, v, cacheMap);
744
929
  for (const evictedKey of evictedKeys) {
745
930
  const parsedKey = JSON.parse(evictedKey);
746
931
  await cacheMap.delete(parsedKey);
932
+ logger2.debug("QUERY_CACHE: Evicted item due to cache limits", {
933
+ evictedKey,
934
+ queryHash
935
+ });
747
936
  }
748
937
  }
749
938
  const itemKeys = ret.map((item) => item.key);
750
- cacheMap.setQueryResult(queryHash, itemKeys);
751
- 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
+ });
752
945
  const event = CacheEventFactory.createQueryEvent(query, locations, ret);
753
946
  context.eventEmitter.emit(event);
947
+ logger2.debug("QUERY_CACHE: Emitted query event", { queryHash });
754
948
  } catch (e) {
755
949
  if (e instanceof NotFoundError) {
756
- cacheMap.setQueryResult(queryHash, []);
757
- 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 });
758
953
  } else {
954
+ logger2.debug("QUERY_CACHE: API error occurred", {
955
+ queryHash,
956
+ error: e instanceof Error ? e.message : String(e)
957
+ });
759
958
  throw e;
760
959
  }
761
960
  }
961
+ logger2.debug("QUERY_CACHE: all() operation completed", {
962
+ queryHash,
963
+ resultCount: ret.length
964
+ });
762
965
  return ret;
763
966
  }
764
967
 
@@ -961,37 +1164,93 @@ async function executeOneLogic(query, locations, context) {
961
1164
  }
962
1165
  }
963
1166
  const queryHash = createQueryHash(pkType, query, locations);
964
- 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 });
965
1174
  const cachedItemKeys = await cacheMap.getQueryResult(queryHash);
966
1175
  if (cachedItemKeys) {
967
- 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
+ });
968
1181
  if (cachedItemKeys.length === 0) {
1182
+ logger3.debug("QUERY_CACHE: Cached empty result (not found)", { queryHash });
969
1183
  return null;
970
1184
  }
971
- 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);
972
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
+ });
973
1197
  return item;
974
1198
  } else {
975
- 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
+ });
976
1203
  cacheMap.deleteQueryResult(queryHash);
977
1204
  }
1205
+ } else {
1206
+ logger3.debug("QUERY_CACHE: Cache MISS - No cached query result found", { queryHash });
978
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
+ });
979
1213
  try {
980
1214
  const directCachedItems = await cacheMap.queryIn(query, locations);
981
1215
  if (directCachedItems && directCachedItems.length > 0) {
982
- 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
+ });
983
1221
  const foundItem = directCachedItems[0];
984
1222
  await cacheMap.setQueryResult(queryHash, [foundItem.key]);
985
- 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
+ });
986
1227
  return foundItem;
1228
+ } else {
1229
+ logger3.debug("QUERY_CACHE: Direct cache query returned no items", { queryHash });
987
1230
  }
988
1231
  } catch (error) {
989
- 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
+ });
990
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
+ });
991
1242
  let retItem = null;
992
1243
  try {
993
1244
  retItem = await api.one(query, locations);
994
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
+ });
995
1254
  await cacheMap.set(retItem.key, retItem);
996
1255
  const keyStr = JSON.stringify(retItem.key);
997
1256
  const metadata = await cacheMap.getMetadata(keyStr);
@@ -1011,21 +1270,38 @@ async function executeOneLogic(query, locations, context) {
1011
1270
  for (const evictedKey of evictedKeys) {
1012
1271
  const parsedKey = JSON.parse(evictedKey);
1013
1272
  await cacheMap.delete(parsedKey);
1273
+ logger3.debug("QUERY_CACHE: Evicted item due to cache limits", {
1274
+ evictedKey,
1275
+ queryHash
1276
+ });
1014
1277
  }
1015
1278
  await cacheMap.setQueryResult(queryHash, [retItem.key]);
1016
- 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
+ });
1017
1283
  } else {
1284
+ logger3.debug("QUERY_CACHE: API returned null, caching empty result", { queryHash });
1018
1285
  await cacheMap.setQueryResult(queryHash, []);
1019
- logger3.debug("Cached empty query result", { queryHash });
1286
+ logger3.debug("QUERY_CACHE: Cached empty query result", { queryHash });
1020
1287
  }
1021
1288
  } catch (e) {
1022
1289
  if (e instanceof NotFoundError2) {
1023
- cacheMap.setQueryResult(queryHash, []);
1024
- 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 });
1025
1293
  } else {
1294
+ logger3.debug("QUERY_CACHE: API error occurred", {
1295
+ queryHash,
1296
+ error: e instanceof Error ? e.message : String(e)
1297
+ });
1026
1298
  throw e;
1027
1299
  }
1028
1300
  }
1301
+ logger3.debug("QUERY_CACHE: one() operation completed", {
1302
+ queryHash,
1303
+ result: retItem ? JSON.stringify(retItem.key) : null
1304
+ });
1029
1305
  return retItem || null;
1030
1306
  }
1031
1307
 
@@ -1107,68 +1383,128 @@ var get = async (key, context) => {
1107
1383
  return [context, result];
1108
1384
  };
1109
1385
  async function executeGetLogic(key, context) {
1386
+ const startTime = Date.now();
1110
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
+ });
1111
1395
  statsManager.incrementRequests();
1112
1396
  if (!isValidItemKey(key)) {
1113
- logger5.error("Key for Get is not a valid ItemKey: %j", key);
1397
+ logger5.error("CACHE_OP: Invalid key for get", { key: keyStr });
1114
1398
  throw new Error("Key for Get is not a valid ItemKey");
1115
1399
  }
1116
1400
  if (context.options?.bypassCache) {
1117
- logger5.debug("Cache bypass enabled, fetching directly from API", { key });
1401
+ logger5.debug("CACHE_OP: Cache bypass enabled, fetching directly from API", { key: keyStr });
1118
1402
  statsManager.incrementMisses();
1119
1403
  try {
1404
+ const apiStartTime = Date.now();
1120
1405
  const ret2 = await api.get(key);
1406
+ const apiDuration = Date.now() - apiStartTime;
1121
1407
  if (ret2) {
1122
- 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
+ });
1123
1413
  return ret2;
1124
1414
  } else {
1125
- logger5.debug("API returned null", { key });
1415
+ logger5.debug("CACHE_OP: API returned null (bypass mode)", {
1416
+ key: keyStr,
1417
+ apiDuration
1418
+ });
1126
1419
  return null;
1127
1420
  }
1128
1421
  } catch (error) {
1129
- 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
+ });
1130
1427
  throw error;
1131
1428
  }
1132
1429
  }
1133
1430
  if (ttlManager.isTTLEnabled()) {
1134
- const keyStr2 = JSON.stringify(key);
1431
+ const cacheCheckStart = Date.now();
1135
1432
  const cachedItem = await cacheMap.get(key);
1433
+ const cacheCheckDuration = Date.now() - cacheCheckStart;
1136
1434
  if (cachedItem) {
1137
- 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;
1138
1443
  if (isValid) {
1139
- 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
+ });
1140
1452
  statsManager.incrementHits();
1141
1453
  return cachedItem;
1142
1454
  } else {
1143
- 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
+ });
1144
1460
  cacheMap.delete(key);
1145
1461
  statsManager.incrementMisses();
1146
1462
  }
1147
1463
  } else {
1464
+ logger5.debug("CACHE_OP: Cache MISS (no item found)", {
1465
+ key: keyStr,
1466
+ cacheCheckDuration
1467
+ });
1148
1468
  statsManager.incrementMisses();
1149
1469
  }
1150
- 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
+ });
1151
1474
  } else {
1475
+ const cacheCheckStart = Date.now();
1152
1476
  const cachedItem = await cacheMap.get(key);
1477
+ const cacheCheckDuration = Date.now() - cacheCheckStart;
1153
1478
  if (cachedItem) {
1154
- 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
+ });
1155
1485
  statsManager.incrementHits();
1156
1486
  return cachedItem;
1157
1487
  } else {
1488
+ logger5.debug("CACHE_OP: Cache MISS (TTL disabled)", {
1489
+ key: keyStr,
1490
+ cacheCheckDuration
1491
+ });
1158
1492
  statsManager.incrementMisses();
1159
1493
  }
1160
1494
  }
1161
1495
  let ret;
1162
- const keyStr = keyToString(key);
1496
+ const requestKeyStr = keyToString(key);
1163
1497
  try {
1164
- const requestEntry = inFlightRequests.get(keyStr);
1498
+ const requestEntry = inFlightRequests.get(requestKeyStr);
1165
1499
  let apiRequest;
1500
+ const apiStartTime = Date.now();
1166
1501
  if (!requestEntry) {
1502
+ logger5.debug("CACHE_OP: Creating new API request", { key: keyStr });
1167
1503
  apiRequest = api.get(key);
1168
1504
  if (apiRequest && typeof apiRequest.then === "function") {
1169
1505
  const timestamp = Date.now();
1170
- inFlightRequests.set(keyStr, { promise: apiRequest, timestamp });
1171
- const cleanup = () => inFlightRequests.delete(keyStr);
1506
+ inFlightRequests.set(requestKeyStr, { promise: apiRequest, timestamp });
1507
+ const cleanup = () => inFlightRequests.delete(requestKeyStr);
1172
1508
  if (typeof apiRequest.finally === "function") {
1173
1509
  apiRequest.finally(cleanup);
1174
1510
  } else {
@@ -1176,37 +1512,90 @@ async function executeGetLogic(key, context) {
1176
1512
  }
1177
1513
  }
1178
1514
  } else {
1179
- 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
+ });
1180
1519
  apiRequest = requestEntry.promise;
1181
1520
  }
1182
1521
  ret = await apiRequest;
1522
+ const apiDuration = Date.now() - apiStartTime;
1183
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();
1184
1530
  await cacheMap.set(ret.key, ret);
1185
- const keyStr2 = JSON.stringify(ret.key);
1186
- 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);
1187
1535
  if (!metadata) {
1188
1536
  const now = Date.now();
1537
+ const estimatedSize = estimateValueSize(ret);
1189
1538
  const baseMetadata = {
1190
- key: keyStr2,
1539
+ key: itemKeyStr,
1191
1540
  addedAt: now,
1192
1541
  lastAccessedAt: now,
1193
1542
  accessCount: 1,
1194
- estimatedSize: estimateValueSize(ret)
1543
+ estimatedSize
1195
1544
  };
1196
- 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
+ });
1550
+ }
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
+ });
1197
1561
  }
1198
- const evictedKeys = await context.evictionManager.onItemAdded(keyStr2, ret, cacheMap);
1199
- await ttlManager.onItemAdded(keyStr2, cacheMap);
1562
+ const ttlStart = Date.now();
1563
+ await ttlManager.onItemAdded(itemKeyStr, cacheMap);
1564
+ const ttlDuration = Date.now() - ttlStart;
1200
1565
  for (const evictedKey of evictedKeys) {
1201
1566
  const parsedKey = JSON.parse(evictedKey);
1202
1567
  await cacheMap.delete(parsedKey);
1568
+ logger5.debug("CACHE_OP: Removed evicted item", { evictedKey });
1203
1569
  }
1204
1570
  const event = CacheEventFactory.itemRetrieved(ret.key, ret, "api");
1205
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
+ });
1206
1589
  }
1207
1590
  } catch (e) {
1208
- inFlightRequests.delete(keyStr);
1209
- 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
+ });
1210
1599
  throw e;
1211
1600
  }
1212
1601
  return ret || null;
@@ -1218,43 +1607,88 @@ import {
1218
1607
  } from "@fjell/core";
1219
1608
  var logger6 = logger_default.get("retrieve");
1220
1609
  var retrieve = async (key, context) => {
1610
+ const startTime = Date.now();
1221
1611
  const { cacheMap, pkType, statsManager } = context;
1612
+ const keyStr = JSON.stringify(key);
1222
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
+ });
1223
1619
  statsManager.incrementRequests();
1224
1620
  if (!isValidItemKey2(key)) {
1225
- logger6.error("Key for Retrieve is not a valid ItemKey: %j", key);
1621
+ logger6.error("CACHE_OP: Invalid key for retrieve", { key: keyStr });
1226
1622
  throw new Error("Key for Retrieve is not a valid ItemKey");
1227
1623
  }
1228
1624
  if (context.options?.bypassCache) {
1229
- logger6.debug("Cache bypass enabled, fetching directly from API", { key });
1625
+ logger6.debug("CACHE_OP: Cache bypass enabled, fetching directly from API", { key: keyStr });
1230
1626
  statsManager.incrementMisses();
1231
1627
  try {
1628
+ const apiStartTime = Date.now();
1232
1629
  const { api } = context;
1233
1630
  const retrieved2 = await api.get(key);
1631
+ const apiDuration = Date.now() - apiStartTime;
1234
1632
  if (retrieved2) {
1235
- 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
+ });
1236
1638
  return [null, retrieved2];
1237
1639
  } else {
1238
- logger6.debug("API returned null", { key });
1640
+ logger6.debug("CACHE_OP: API returned null (bypass mode)", {
1641
+ key: keyStr,
1642
+ apiDuration
1643
+ });
1239
1644
  return [null, null];
1240
1645
  }
1241
1646
  } catch (error) {
1242
- 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
+ });
1243
1653
  throw error;
1244
1654
  }
1245
1655
  }
1246
1656
  const containsItemKey = await cacheMap.includesKey(key);
1657
+ logger6.debug("CACHE_OP: Cache key check completed", {
1658
+ key: keyStr,
1659
+ exists: containsItemKey
1660
+ });
1247
1661
  let retrieved;
1248
1662
  let contextToReturn;
1249
1663
  if (containsItemKey) {
1250
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();
1251
1667
  retrieved = await cacheMap.get(key);
1668
+ const getDuration = Date.now() - getStartTime;
1252
1669
  contextToReturn = null;
1253
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
+ });
1254
1678
  } else {
1255
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 });
1256
1681
  statsManager.incrementMisses();
1682
+ const apiStartTime = Date.now();
1257
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
+ });
1258
1692
  }
1259
1693
  const retValue = [
1260
1694
  contextToReturn,
@@ -1749,44 +2183,107 @@ async function executeFindLogic(finder, params, locations, context) {
1749
2183
  }
1750
2184
  }
1751
2185
  const queryHash = createFinderHash(finder, params, locations);
1752
- 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 });
1753
2193
  const cachedItemKeys = await cacheMap.getQueryResult(queryHash);
1754
2194
  if (cachedItemKeys) {
1755
- 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
+ });
1756
2200
  const cachedItems = [];
1757
2201
  let allItemsAvailable = true;
2202
+ const missingKeys = [];
1758
2203
  for (const itemKey of cachedItemKeys) {
1759
2204
  const item = await cacheMap.get(itemKey);
1760
2205
  if (item) {
1761
2206
  cachedItems.push(item);
2207
+ logger14.debug("QUERY_CACHE: Retrieved cached item", {
2208
+ itemKey: JSON.stringify(itemKey),
2209
+ itemKeyStr: JSON.stringify(item.key)
2210
+ });
1762
2211
  } else {
1763
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
+ });
1764
2218
  break;
1765
2219
  }
1766
2220
  }
1767
2221
  if (allItemsAvailable) {
2222
+ logger14.debug("QUERY_CACHE: All cached items available, returning from cache", {
2223
+ queryHash,
2224
+ itemCount: cachedItems.length
2225
+ });
1768
2226
  return cachedItems;
1769
2227
  } else {
1770
- 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
+ });
1771
2234
  cacheMap.deleteQueryResult(queryHash);
1772
2235
  }
2236
+ } else {
2237
+ logger14.debug("QUERY_CACHE: Cache MISS - No cached query result found", { queryHash });
1773
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
+ });
1774
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
+ });
1775
2255
  for (const v of ret) {
1776
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
+ });
1777
2261
  const keyStr = JSON.stringify(v.key);
1778
2262
  ttlManager.onItemAdded(keyStr, cacheMap);
1779
2263
  const evictedKeys = await context.evictionManager.onItemAdded(keyStr, v, cacheMap);
1780
2264
  for (const evictedKey of evictedKeys) {
1781
2265
  const parsedKey = JSON.parse(evictedKey);
1782
2266
  await cacheMap.delete(parsedKey);
2267
+ logger14.debug("QUERY_CACHE: Evicted item due to cache limits", {
2268
+ evictedKey,
2269
+ queryHash
2270
+ });
1783
2271
  }
1784
2272
  }
1785
2273
  const itemKeys = ret.map((item) => item.key);
1786
- cacheMap.setQueryResult(queryHash, itemKeys);
1787
- 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
+ });
1788
2280
  const event = CacheEventFactory.createQueryEvent(params, locations, ret);
1789
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
+ });
1790
2287
  return ret;
1791
2288
  }
1792
2289
 
@@ -1824,34 +2321,86 @@ async function executeFindOneLogic(finder, finderParams, locations, context) {
1824
2321
  }
1825
2322
  }
1826
2323
  const queryHash = createFinderHash(finder, finderParams, locations);
1827
- 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 });
1828
2331
  const cachedItemKeys = await cacheMap.getQueryResult(queryHash);
1829
2332
  if (cachedItemKeys && cachedItemKeys.length > 0) {
1830
- logger15.debug("Using cached query results", { cachedKeyCount: cachedItemKeys.length });
1831
- 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);
1832
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
+ });
1833
2350
  return item;
1834
2351
  } else {
1835
- 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
+ });
1836
2356
  cacheMap.deleteQueryResult(queryHash);
1837
2357
  }
2358
+ } else {
2359
+ logger15.debug("QUERY_CACHE: Cache MISS - No cached query result found", { queryHash });
1838
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
+ });
1839
2367
  const ret = await api.findOne(finder, finderParams, locations);
1840
2368
  if (ret === null) {
2369
+ logger15.debug("QUERY_CACHE: API returned null, throwing error", { queryHash, finder });
1841
2370
  throw new Error(`findOne returned null for finder: ${finder}`);
1842
2371
  }
1843
- 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);
1844
2381
  const keyStr = JSON.stringify(ret.key);
1845
2382
  ttlManager.onItemAdded(keyStr, cacheMap);
1846
2383
  const evictedKeys = await context.evictionManager.onItemAdded(keyStr, ret, cacheMap);
1847
2384
  for (const evictedKey of evictedKeys) {
1848
2385
  const parsedKey = JSON.parse(evictedKey);
1849
2386
  await cacheMap.delete(parsedKey);
2387
+ logger15.debug("QUERY_CACHE: Evicted item due to cache limits", {
2388
+ evictedKey,
2389
+ queryHash
2390
+ });
1850
2391
  }
1851
- cacheMap.setQueryResult(queryHash, [ret.key]);
1852
- 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
+ });
1853
2397
  const event = CacheEventFactory.createQueryEvent(finderParams, locations, [ret]);
1854
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
+ });
1855
2404
  return ret;
1856
2405
  }
1857
2406
 
@@ -1909,39 +2458,93 @@ var normalizeKey = (key) => {
1909
2458
  return key;
1910
2459
  };
1911
2460
  var set = async (key, v, context) => {
2461
+ const startTime = Date.now();
1912
2462
  const { cacheMap, pkType, ttlManager, evictionManager, eventEmitter } = context;
2463
+ const keyStr = JSON.stringify(key);
1913
2464
  logger16.default("set", { key, v });
2465
+ logger16.debug("CACHE_OP: set() started", {
2466
+ key: keyStr,
2467
+ cacheType: cacheMap.implementationType
2468
+ });
1914
2469
  if (!isValidItemKey6(key)) {
1915
- logger16.error("Key for Set is not a valid ItemKey: %j", key);
2470
+ logger16.error("CACHE_OP: Invalid key for set", { key: keyStr });
1916
2471
  throw new Error("Key for Set is not a valid ItemKey");
1917
2472
  }
1918
2473
  if (!isItemKeyEqualNormalized(key, v.key)) {
1919
- 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
+ });
1920
2478
  throw new Error("Key does not match item key");
1921
2479
  }
2480
+ const checkStartTime = Date.now();
1922
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();
1923
2489
  await cacheMap.set(key, v);
1924
- const keyStr = JSON.stringify(key);
2490
+ const setDuration = Date.now() - setStartTime;
2491
+ const metadataStartTime = Date.now();
1925
2492
  const metadata = await cacheMap.getMetadata(keyStr);
1926
2493
  if (!metadata) {
1927
2494
  const now = Date.now();
2495
+ const estimatedSize = estimateValueSize(v);
1928
2496
  const baseMetadata = {
1929
2497
  key: keyStr,
1930
2498
  addedAt: now,
1931
2499
  lastAccessedAt: now,
1932
2500
  accessCount: 1,
1933
- estimatedSize: estimateValueSize(v)
2501
+ estimatedSize
1934
2502
  };
1935
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
+ });
1936
2514
  }
2515
+ const metadataDuration = Date.now() - metadataStartTime;
2516
+ const ttlStartTime = Date.now();
1937
2517
  await ttlManager.onItemAdded(keyStr, cacheMap);
2518
+ const ttlDuration = Date.now() - ttlStartTime;
2519
+ const evictionStartTime = Date.now();
1938
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
+ }
1939
2529
  for (const evictedKey of evictedKeys) {
1940
2530
  const parsedKey = JSON.parse(evictedKey);
1941
2531
  await cacheMap.delete(parsedKey);
2532
+ logger16.debug("CACHE_OP: Removed evicted item", { evictedKey });
1942
2533
  }
1943
2534
  const event = CacheEventFactory.itemSet(key, v, previousItem);
1944
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
+ });
1945
2548
  return [context, v];
1946
2549
  };
1947
2550
 
@@ -5119,9 +5722,17 @@ var EvictionManager = class {
5119
5722
  return;
5120
5723
  }
5121
5724
  try {
5725
+ logger24.debug("EVICTION: Item accessed, updating metadata", {
5726
+ key,
5727
+ strategy: this.evictionStrategy.getStrategyName()
5728
+ });
5122
5729
  await this.evictionStrategy.onItemAccessed(key, metadataProvider);
5123
5730
  } catch (error) {
5124
- 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
+ });
5125
5736
  }
5126
5737
  }
5127
5738
  /**
@@ -5132,28 +5743,81 @@ var EvictionManager = class {
5132
5743
  * @returns Array of keys that were evicted
5133
5744
  */
5134
5745
  async onItemAdded(key, value, metadataProvider) {
5746
+ const startTime = Date.now();
5135
5747
  const evictedKeys = [];
5136
5748
  if (!this.evictionStrategy) {
5749
+ logger24.debug("EVICTION: No eviction strategy configured", { key });
5137
5750
  return evictedKeys;
5138
5751
  }
5139
5752
  try {
5140
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();
5141
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();
5142
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();
5143
5784
  for (const evictKey of keysToEvict) {
5144
5785
  await this.evictionStrategy.onItemRemoved(evictKey, metadataProvider);
5145
5786
  evictedKeys.push(evictKey);
5787
+ logger24.debug("EVICTION: Marked item for eviction", {
5788
+ evictedKey: evictKey,
5789
+ newKey: key
5790
+ });
5146
5791
  }
5792
+ const removalDuration = Date.now() - removalStartTime;
5793
+ const addMetadataStart = Date.now();
5147
5794
  await this.evictionStrategy.onItemAdded(key, estimatedSize, metadataProvider);
5795
+ const addMetadataDuration = Date.now() - addMetadataStart;
5796
+ const totalDuration = Date.now() - startTime;
5148
5797
  if (evictedKeys.length > 0) {
5149
- logger24.debug("Items evicted during addition", {
5798
+ logger24.debug("EVICTION: Eviction completed", {
5150
5799
  newKey: key,
5800
+ evictedCount: evictedKeys.length,
5151
5801
  evictedKeys,
5152
- 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
5153
5813
  });
5154
5814
  }
5155
5815
  } catch (error) {
5156
- 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
+ });
5157
5821
  }
5158
5822
  return evictedKeys;
5159
5823
  }
@@ -5178,25 +5842,47 @@ var EvictionManager = class {
5178
5842
  * @returns Array of keys that were evicted
5179
5843
  */
5180
5844
  async performEviction(metadataProvider) {
5845
+ const startTime = Date.now();
5181
5846
  const evictedKeys = [];
5182
5847
  if (!this.evictionStrategy) {
5848
+ logger24.debug("EVICTION: No eviction strategy configured for manual eviction");
5183
5849
  return evictedKeys;
5184
5850
  }
5185
5851
  try {
5852
+ logger24.debug("EVICTION: Manual eviction started", {
5853
+ strategy: this.evictionStrategy.getStrategyName()
5854
+ });
5186
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
+ });
5187
5862
  const keysToEvict = await this.evictionStrategy.selectForEviction(metadataProvider, context);
5188
5863
  for (const evictKey of keysToEvict) {
5189
5864
  await this.evictionStrategy.onItemRemoved(evictKey, metadataProvider);
5190
5865
  evictedKeys.push(evictKey);
5191
5866
  }
5867
+ const duration = Date.now() - startTime;
5192
5868
  if (evictedKeys.length > 0) {
5193
- logger24.debug("Manual eviction performed", {
5869
+ logger24.debug("EVICTION: Manual eviction completed", {
5870
+ evictedCount: evictedKeys.length,
5194
5871
  evictedKeys,
5195
- 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
5196
5879
  });
5197
5880
  }
5198
5881
  } catch (error) {
5199
- logger24.error("Error in manual eviction", { error });
5882
+ logger24.error("EVICTION: Error in manual eviction", {
5883
+ error,
5884
+ strategy: this.evictionStrategy?.getStrategyName()
5885
+ });
5200
5886
  }
5201
5887
  return evictedKeys;
5202
5888
  }
@@ -6625,7 +7311,7 @@ var TTLManager = class {
6625
7311
  metadata
6626
7312
  });
6627
7313
  if (!metadata) {
6628
- 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", {
6629
7315
  key,
6630
7316
  metadataProviderType: metadataProvider?.constructor?.name,
6631
7317
  metadataProviderMethods: metadataProvider ? Object.getOwnPropertyNames(Object.getPrototypeOf(metadataProvider)) : null
@@ -6665,12 +7351,28 @@ var TTLManager = class {
6665
7351
  async isExpired(key, metadataProvider) {
6666
7352
  const metadata = await metadataProvider.getMetadata(key);
6667
7353
  if (!metadata || !metadata.expiresAt) {
7354
+ logger25.debug("TTL_CHECK: No TTL set for item", { key, hasMetadata: !!metadata });
6668
7355
  return false;
6669
7356
  }
6670
7357
  const now = Date.now();
6671
7358
  const expired = now >= metadata.expiresAt;
7359
+ const remainingMs = metadata.expiresAt - now;
6672
7360
  if (expired) {
6673
- 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
+ });
6674
7376
  }
6675
7377
  return expired;
6676
7378
  }
@@ -6680,9 +7382,22 @@ var TTLManager = class {
6680
7382
  */
6681
7383
  async validateItem(key, metadataProvider) {
6682
7384
  if (!this.config.validateOnAccess) {
7385
+ logger25.debug("TTL_VALIDATE: Validation disabled, skipping check", { key });
6683
7386
  return true;
6684
7387
  }
6685
- 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;
6686
7401
  }
6687
7402
  /**
6688
7403
  * Get TTL information for an item
@@ -6707,17 +7422,44 @@ var TTLManager = class {
6707
7422
  * Find all expired items
6708
7423
  */
6709
7424
  async findExpiredItems(metadataProvider) {
7425
+ const startTime = Date.now();
6710
7426
  const expiredKeys = [];
6711
7427
  const allMetadata = await metadataProvider.getAllMetadata();
6712
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;
6713
7434
  for (const [key, metadata] of allMetadata) {
6714
7435
  const ttlMetadata = metadata;
6715
- if (ttlMetadata.expiresAt && now >= ttlMetadata.expiresAt) {
6716
- 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
+ }
6717
7446
  }
6718
7447
  }
7448
+ const duration = Date.now() - startTime;
6719
7449
  if (expiredKeys.length > 0) {
6720
- 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
+ });
6721
7463
  }
6722
7464
  return expiredKeys;
6723
7465
  }