@fjell/cache 4.7.43 → 4.7.45

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,159 @@ 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
  }
727
- try {
728
- const directCachedItems = await cacheMap.queryIn(query, locations);
729
- if (directCachedItems && directCachedItems.length > 0) {
730
- logger2.debug("Found items directly in cache, skipping API call", { itemCount: directCachedItems.length });
731
- const itemKeys = directCachedItems.map((item) => item.key);
732
- await cacheMap.setQueryResult(queryHash, itemKeys);
733
- logger2.debug("Cached query result from direct cache hit", { queryHash, itemKeyCount: itemKeys.length });
734
- return directCachedItems;
873
+ const isEmptyQuery = Object.keys(query).length === 0 || (Object.keys(query).length === 1 && "limit" in query || "offset" in query);
874
+ if (!isEmptyQuery) {
875
+ logger2.debug("QUERY_CACHE: Attempting direct cache query using queryIn() for filtered query", {
876
+ queryHash,
877
+ query: JSON.stringify(query),
878
+ locations: JSON.stringify(locations)
879
+ });
880
+ try {
881
+ const directCachedItems = await cacheMap.queryIn(query, locations);
882
+ if (directCachedItems && directCachedItems.length > 0) {
883
+ logger2.debug("QUERY_CACHE: Direct cache query SUCCESS - Found items in item cache", {
884
+ queryHash,
885
+ itemCount: directCachedItems.length,
886
+ itemKeys: directCachedItems.map((item) => JSON.stringify(item.key))
887
+ });
888
+ const itemKeys = directCachedItems.map((item) => item.key);
889
+ await cacheMap.setQueryResult(queryHash, itemKeys);
890
+ logger2.debug("QUERY_CACHE: Stored query result from direct cache hit", {
891
+ queryHash,
892
+ itemKeyCount: itemKeys.length,
893
+ itemKeys: itemKeys.map((k) => JSON.stringify(k))
894
+ });
895
+ return directCachedItems;
896
+ } else {
897
+ logger2.debug("QUERY_CACHE: Direct cache query returned no items", { queryHash });
898
+ }
899
+ } catch (error) {
900
+ logger2.debug("QUERY_CACHE: Error querying cache directly, proceeding to API", {
901
+ queryHash,
902
+ error: error instanceof Error ? error.message : String(error)
903
+ });
735
904
  }
736
- } catch (error) {
737
- logger2.debug("Error querying cache directly, proceeding to API", { error });
905
+ } else {
906
+ logger2.debug("QUERY_CACHE: Skipping direct cache query for empty/all query - cannot trust completeness", {
907
+ queryHash,
908
+ query: JSON.stringify(query)
909
+ });
738
910
  }
911
+ logger2.debug("QUERY_CACHE: Fetching from API (cache miss or invalid)", {
912
+ queryHash,
913
+ query: JSON.stringify(query),
914
+ locations: JSON.stringify(locations)
915
+ });
739
916
  let ret = [];
740
917
  try {
741
918
  ret = await api.all(query, locations);
919
+ logger2.debug("QUERY_CACHE: API response received", {
920
+ queryHash,
921
+ itemCount: ret.length,
922
+ itemKeys: ret.map((item) => JSON.stringify(item.key))
923
+ });
924
+ logger2.debug("QUERY_CACHE: Storing items in item cache", {
925
+ queryHash,
926
+ itemCount: ret.length
927
+ });
742
928
  for (const v of ret) {
743
929
  await cacheMap.set(v.key, v);
930
+ logger2.debug("QUERY_CACHE: Stored item in cache", {
931
+ itemKey: JSON.stringify(v.key),
932
+ queryHash
933
+ });
744
934
  const keyStr = JSON.stringify(v.key);
745
935
  ttlManager.onItemAdded(keyStr, cacheMap);
746
936
  const evictedKeys = await context.evictionManager.onItemAdded(keyStr, v, cacheMap);
747
937
  for (const evictedKey of evictedKeys) {
748
938
  const parsedKey = JSON.parse(evictedKey);
749
939
  await cacheMap.delete(parsedKey);
940
+ logger2.debug("QUERY_CACHE: Evicted item due to cache limits", {
941
+ evictedKey,
942
+ queryHash
943
+ });
750
944
  }
751
945
  }
752
946
  const itemKeys = ret.map((item) => item.key);
753
- cacheMap.setQueryResult(queryHash, itemKeys);
754
- logger2.debug("Cached query result", { queryHash, itemKeyCount: itemKeys.length });
947
+ await cacheMap.setQueryResult(queryHash, itemKeys);
948
+ logger2.debug("QUERY_CACHE: Stored query result in query cache", {
949
+ queryHash,
950
+ itemKeyCount: itemKeys.length,
951
+ itemKeys: itemKeys.map((k) => JSON.stringify(k))
952
+ });
755
953
  const event = CacheEventFactory.createQueryEvent(query, locations, ret);
756
954
  context.eventEmitter.emit(event);
955
+ logger2.debug("QUERY_CACHE: Emitted query event", { queryHash });
757
956
  } catch (e) {
758
957
  if (e instanceof NotFoundError) {
759
- cacheMap.setQueryResult(queryHash, []);
760
- logger2.debug("Cached empty query result for not found", { queryHash });
958
+ logger2.debug("QUERY_CACHE: API returned NotFoundError, caching empty result", { queryHash });
959
+ await cacheMap.setQueryResult(queryHash, []);
960
+ logger2.debug("QUERY_CACHE: Cached empty query result for not found", { queryHash });
761
961
  } else {
962
+ logger2.debug("QUERY_CACHE: API error occurred", {
963
+ queryHash,
964
+ error: e instanceof Error ? e.message : String(e)
965
+ });
762
966
  throw e;
763
967
  }
764
968
  }
969
+ logger2.debug("QUERY_CACHE: all() operation completed", {
970
+ queryHash,
971
+ resultCount: ret.length
972
+ });
765
973
  return ret;
766
974
  }
767
975
 
@@ -964,37 +1172,93 @@ async function executeOneLogic(query, locations, context) {
964
1172
  }
965
1173
  }
966
1174
  const queryHash = createQueryHash(pkType, query, locations);
967
- logger3.debug("Generated query hash for one", { queryHash });
1175
+ logger3.debug("QUERY_CACHE: Generated query hash for one()", {
1176
+ queryHash,
1177
+ query: JSON.stringify(query),
1178
+ locations: JSON.stringify(locations),
1179
+ pkType
1180
+ });
1181
+ logger3.debug("QUERY_CACHE: Checking query cache for hash", { queryHash });
968
1182
  const cachedItemKeys = await cacheMap.getQueryResult(queryHash);
969
1183
  if (cachedItemKeys) {
970
- logger3.debug("Using cached query results", { cachedKeyCount: cachedItemKeys.length });
1184
+ logger3.debug("QUERY_CACHE: Cache HIT - Found cached query result", {
1185
+ queryHash,
1186
+ cachedKeyCount: cachedItemKeys.length,
1187
+ itemKeys: cachedItemKeys.map((k) => JSON.stringify(k))
1188
+ });
971
1189
  if (cachedItemKeys.length === 0) {
1190
+ logger3.debug("QUERY_CACHE: Cached empty result (not found)", { queryHash });
972
1191
  return null;
973
1192
  }
974
- const item = await cacheMap.get(cachedItemKeys[0]);
1193
+ const itemKey = cachedItemKeys[0];
1194
+ logger3.debug("QUERY_CACHE: Retrieving first cached item", {
1195
+ queryHash,
1196
+ itemKey: JSON.stringify(itemKey)
1197
+ });
1198
+ const item = await cacheMap.get(itemKey);
975
1199
  if (item) {
1200
+ logger3.debug("QUERY_CACHE: Retrieved cached item successfully", {
1201
+ queryHash,
1202
+ itemKey: JSON.stringify(itemKey),
1203
+ itemKeyStr: JSON.stringify(item.key)
1204
+ });
976
1205
  return item;
977
1206
  } else {
978
- logger3.debug("Cached item missing, invalidating query cache");
1207
+ logger3.debug("QUERY_CACHE: Cached item MISSING from item cache, invalidating query cache", {
1208
+ queryHash,
1209
+ itemKey: JSON.stringify(itemKey)
1210
+ });
979
1211
  cacheMap.deleteQueryResult(queryHash);
980
1212
  }
1213
+ } else {
1214
+ logger3.debug("QUERY_CACHE: Cache MISS - No cached query result found", { queryHash });
981
1215
  }
1216
+ logger3.debug("QUERY_CACHE: Attempting direct cache query using queryIn()", {
1217
+ queryHash,
1218
+ query: JSON.stringify(query),
1219
+ locations: JSON.stringify(locations)
1220
+ });
982
1221
  try {
983
1222
  const directCachedItems = await cacheMap.queryIn(query, locations);
984
1223
  if (directCachedItems && directCachedItems.length > 0) {
985
- logger3.debug("Found item directly in cache, skipping API call");
1224
+ logger3.debug("QUERY_CACHE: Direct cache query SUCCESS - Found item in item cache", {
1225
+ queryHash,
1226
+ itemCount: directCachedItems.length,
1227
+ itemKeys: directCachedItems.map((item) => JSON.stringify(item.key))
1228
+ });
986
1229
  const foundItem = directCachedItems[0];
987
1230
  await cacheMap.setQueryResult(queryHash, [foundItem.key]);
988
- logger3.debug("Cached query result from direct cache hit", { queryHash, itemKey: foundItem.key });
1231
+ logger3.debug("QUERY_CACHE: Stored query result from direct cache hit", {
1232
+ queryHash,
1233
+ itemKey: JSON.stringify(foundItem.key)
1234
+ });
989
1235
  return foundItem;
1236
+ } else {
1237
+ logger3.debug("QUERY_CACHE: Direct cache query returned no items", { queryHash });
990
1238
  }
991
1239
  } catch (error) {
992
- logger3.debug("Error querying cache directly, proceeding to API", { error });
1240
+ logger3.debug("QUERY_CACHE: Error querying cache directly, proceeding to API", {
1241
+ queryHash,
1242
+ error: error instanceof Error ? error.message : String(error)
1243
+ });
993
1244
  }
1245
+ logger3.debug("QUERY_CACHE: Fetching from API (cache miss or invalid)", {
1246
+ queryHash,
1247
+ query: JSON.stringify(query),
1248
+ locations: JSON.stringify(locations)
1249
+ });
994
1250
  let retItem = null;
995
1251
  try {
996
1252
  retItem = await api.one(query, locations);
997
1253
  if (retItem) {
1254
+ logger3.debug("QUERY_CACHE: API response received", {
1255
+ queryHash,
1256
+ itemKey: JSON.stringify(retItem.key)
1257
+ });
1258
+ logger3.debug("QUERY_CACHE: Storing item in item cache", {
1259
+ queryHash,
1260
+ itemKey: JSON.stringify(retItem.key)
1261
+ });
998
1262
  await cacheMap.set(retItem.key, retItem);
999
1263
  const keyStr = JSON.stringify(retItem.key);
1000
1264
  const metadata = await cacheMap.getMetadata(keyStr);
@@ -1014,21 +1278,38 @@ async function executeOneLogic(query, locations, context) {
1014
1278
  for (const evictedKey of evictedKeys) {
1015
1279
  const parsedKey = JSON.parse(evictedKey);
1016
1280
  await cacheMap.delete(parsedKey);
1281
+ logger3.debug("QUERY_CACHE: Evicted item due to cache limits", {
1282
+ evictedKey,
1283
+ queryHash
1284
+ });
1017
1285
  }
1018
1286
  await cacheMap.setQueryResult(queryHash, [retItem.key]);
1019
- logger3.debug("Cached query result", { queryHash, itemKey: retItem.key });
1287
+ logger3.debug("QUERY_CACHE: Stored query result in query cache", {
1288
+ queryHash,
1289
+ itemKey: JSON.stringify(retItem.key)
1290
+ });
1020
1291
  } else {
1292
+ logger3.debug("QUERY_CACHE: API returned null, caching empty result", { queryHash });
1021
1293
  await cacheMap.setQueryResult(queryHash, []);
1022
- logger3.debug("Cached empty query result", { queryHash });
1294
+ logger3.debug("QUERY_CACHE: Cached empty query result", { queryHash });
1023
1295
  }
1024
1296
  } catch (e) {
1025
1297
  if (e instanceof NotFoundError2) {
1026
- cacheMap.setQueryResult(queryHash, []);
1027
- logger3.debug("Cached empty query result for not found", { queryHash });
1298
+ logger3.debug("QUERY_CACHE: API returned NotFoundError, caching empty result", { queryHash });
1299
+ await cacheMap.setQueryResult(queryHash, []);
1300
+ logger3.debug("QUERY_CACHE: Cached empty query result for not found", { queryHash });
1028
1301
  } else {
1302
+ logger3.debug("QUERY_CACHE: API error occurred", {
1303
+ queryHash,
1304
+ error: e instanceof Error ? e.message : String(e)
1305
+ });
1029
1306
  throw e;
1030
1307
  }
1031
1308
  }
1309
+ logger3.debug("QUERY_CACHE: one() operation completed", {
1310
+ queryHash,
1311
+ result: retItem ? JSON.stringify(retItem.key) : null
1312
+ });
1032
1313
  return retItem || null;
1033
1314
  }
1034
1315
 
@@ -1110,68 +1391,128 @@ var get = async (key, context) => {
1110
1391
  return [context, result];
1111
1392
  };
1112
1393
  async function executeGetLogic(key, context) {
1394
+ const startTime = Date.now();
1113
1395
  const { api, cacheMap, pkType, ttlManager, statsManager } = context;
1396
+ const keyStr = JSON.stringify(key);
1397
+ logger5.debug("CACHE_OP: get() started", {
1398
+ key: keyStr,
1399
+ ttlEnabled: ttlManager.isTTLEnabled(),
1400
+ defaultTTL: ttlManager.getDefaultTTL(),
1401
+ cacheType: cacheMap.implementationType
1402
+ });
1114
1403
  statsManager.incrementRequests();
1115
1404
  if (!isValidItemKey(key)) {
1116
- logger5.error("Key for Get is not a valid ItemKey: %j", key);
1405
+ logger5.error("CACHE_OP: Invalid key for get", { key: keyStr });
1117
1406
  throw new Error("Key for Get is not a valid ItemKey");
1118
1407
  }
1119
1408
  if (context.options?.bypassCache) {
1120
- logger5.debug("Cache bypass enabled, fetching directly from API", { key });
1409
+ logger5.debug("CACHE_OP: Cache bypass enabled, fetching directly from API", { key: keyStr });
1121
1410
  statsManager.incrementMisses();
1122
1411
  try {
1412
+ const apiStartTime = Date.now();
1123
1413
  const ret2 = await api.get(key);
1414
+ const apiDuration = Date.now() - apiStartTime;
1124
1415
  if (ret2) {
1125
- logger5.debug("API response received (not cached due to bypass)", { key });
1416
+ logger5.debug("CACHE_OP: API response received (bypass mode, not cached)", {
1417
+ key: keyStr,
1418
+ apiDuration,
1419
+ totalDuration: Date.now() - startTime
1420
+ });
1126
1421
  return ret2;
1127
1422
  } else {
1128
- logger5.debug("API returned null", { key });
1423
+ logger5.debug("CACHE_OP: API returned null (bypass mode)", {
1424
+ key: keyStr,
1425
+ apiDuration
1426
+ });
1129
1427
  return null;
1130
1428
  }
1131
1429
  } catch (error) {
1132
- logger5.error("API request failed", { key, error });
1430
+ logger5.error("CACHE_OP: API request failed in bypass mode", {
1431
+ key: keyStr,
1432
+ duration: Date.now() - startTime,
1433
+ error
1434
+ });
1133
1435
  throw error;
1134
1436
  }
1135
1437
  }
1136
1438
  if (ttlManager.isTTLEnabled()) {
1137
- const keyStr2 = JSON.stringify(key);
1439
+ const cacheCheckStart = Date.now();
1138
1440
  const cachedItem = await cacheMap.get(key);
1441
+ const cacheCheckDuration = Date.now() - cacheCheckStart;
1139
1442
  if (cachedItem) {
1140
- const isValid = await ttlManager.validateItem(keyStr2, cacheMap);
1443
+ logger5.debug("CACHE_OP: Item found in cache, checking TTL validity", {
1444
+ key: keyStr,
1445
+ cacheCheckDuration,
1446
+ defaultTTL: ttlManager.getDefaultTTL()
1447
+ });
1448
+ const ttlCheckStart = Date.now();
1449
+ const isValid = await ttlManager.validateItem(keyStr, cacheMap);
1450
+ const ttlCheckDuration = Date.now() - ttlCheckStart;
1141
1451
  if (isValid) {
1142
- logger5.debug("Cache hit with valid TTL", { key, defaultTTL: ttlManager.getDefaultTTL() });
1452
+ const totalDuration = Date.now() - startTime;
1453
+ logger5.debug("CACHE_OP: Cache HIT with valid TTL", {
1454
+ key: keyStr,
1455
+ cacheCheckDuration,
1456
+ ttlCheckDuration,
1457
+ totalDuration,
1458
+ defaultTTL: ttlManager.getDefaultTTL()
1459
+ });
1143
1460
  statsManager.incrementHits();
1144
1461
  return cachedItem;
1145
1462
  } else {
1146
- logger5.debug("Cache item expired, removing", { key });
1463
+ logger5.debug("CACHE_OP: Cache item EXPIRED, removing from cache", {
1464
+ key: keyStr,
1465
+ cacheCheckDuration,
1466
+ ttlCheckDuration
1467
+ });
1147
1468
  cacheMap.delete(key);
1148
1469
  statsManager.incrementMisses();
1149
1470
  }
1150
1471
  } else {
1472
+ logger5.debug("CACHE_OP: Cache MISS (no item found)", {
1473
+ key: keyStr,
1474
+ cacheCheckDuration
1475
+ });
1151
1476
  statsManager.incrementMisses();
1152
1477
  }
1153
- logger5.debug("Cache miss or expired", { key, defaultTTL: ttlManager.getDefaultTTL() });
1478
+ logger5.debug("CACHE_OP: Proceeding to API fetch (TTL-enabled cache miss or expired)", {
1479
+ key: keyStr,
1480
+ defaultTTL: ttlManager.getDefaultTTL()
1481
+ });
1154
1482
  } else {
1483
+ const cacheCheckStart = Date.now();
1155
1484
  const cachedItem = await cacheMap.get(key);
1485
+ const cacheCheckDuration = Date.now() - cacheCheckStart;
1156
1486
  if (cachedItem) {
1157
- logger5.debug("Cache hit (TTL disabled)", { key });
1487
+ const totalDuration = Date.now() - startTime;
1488
+ logger5.debug("CACHE_OP: Cache HIT (TTL disabled)", {
1489
+ key: keyStr,
1490
+ cacheCheckDuration,
1491
+ totalDuration
1492
+ });
1158
1493
  statsManager.incrementHits();
1159
1494
  return cachedItem;
1160
1495
  } else {
1496
+ logger5.debug("CACHE_OP: Cache MISS (TTL disabled)", {
1497
+ key: keyStr,
1498
+ cacheCheckDuration
1499
+ });
1161
1500
  statsManager.incrementMisses();
1162
1501
  }
1163
1502
  }
1164
1503
  let ret;
1165
- const keyStr = keyToString(key);
1504
+ const requestKeyStr = keyToString(key);
1166
1505
  try {
1167
- const requestEntry = inFlightRequests.get(keyStr);
1506
+ const requestEntry = inFlightRequests.get(requestKeyStr);
1168
1507
  let apiRequest;
1508
+ const apiStartTime = Date.now();
1169
1509
  if (!requestEntry) {
1510
+ logger5.debug("CACHE_OP: Creating new API request", { key: keyStr });
1170
1511
  apiRequest = api.get(key);
1171
1512
  if (apiRequest && typeof apiRequest.then === "function") {
1172
1513
  const timestamp = Date.now();
1173
- inFlightRequests.set(keyStr, { promise: apiRequest, timestamp });
1174
- const cleanup = () => inFlightRequests.delete(keyStr);
1514
+ inFlightRequests.set(requestKeyStr, { promise: apiRequest, timestamp });
1515
+ const cleanup = () => inFlightRequests.delete(requestKeyStr);
1175
1516
  if (typeof apiRequest.finally === "function") {
1176
1517
  apiRequest.finally(cleanup);
1177
1518
  } else {
@@ -1179,37 +1520,90 @@ async function executeGetLogic(key, context) {
1179
1520
  }
1180
1521
  }
1181
1522
  } else {
1182
- logger5.debug("Using in-flight request for key", { key });
1523
+ logger5.debug("CACHE_OP: Using existing in-flight request", {
1524
+ key: keyStr,
1525
+ requestAge: Date.now() - requestEntry.timestamp
1526
+ });
1183
1527
  apiRequest = requestEntry.promise;
1184
1528
  }
1185
1529
  ret = await apiRequest;
1530
+ const apiDuration = Date.now() - apiStartTime;
1186
1531
  if (ret) {
1532
+ logger5.debug("CACHE_OP: API request successful, caching result", {
1533
+ key: keyStr,
1534
+ apiDuration,
1535
+ itemKeyMatches: JSON.stringify(ret.key) === keyStr
1536
+ });
1537
+ const cacheSetStart = Date.now();
1187
1538
  await cacheMap.set(ret.key, ret);
1188
- const keyStr2 = JSON.stringify(ret.key);
1189
- const metadata = await cacheMap.getMetadata(keyStr2);
1539
+ const cacheSetDuration = Date.now() - cacheSetStart;
1540
+ const itemKeyStr = JSON.stringify(ret.key);
1541
+ const metadataStart = Date.now();
1542
+ const metadata = await cacheMap.getMetadata(itemKeyStr);
1190
1543
  if (!metadata) {
1191
1544
  const now = Date.now();
1545
+ const estimatedSize = estimateValueSize(ret);
1192
1546
  const baseMetadata = {
1193
- key: keyStr2,
1547
+ key: itemKeyStr,
1194
1548
  addedAt: now,
1195
1549
  lastAccessedAt: now,
1196
1550
  accessCount: 1,
1197
- estimatedSize: estimateValueSize(ret)
1551
+ estimatedSize
1198
1552
  };
1199
- await cacheMap.setMetadata(keyStr2, baseMetadata);
1553
+ await cacheMap.setMetadata(itemKeyStr, baseMetadata);
1554
+ logger5.debug("CACHE_OP: Created base metadata for cached item", {
1555
+ key: itemKeyStr,
1556
+ estimatedSize
1557
+ });
1200
1558
  }
1201
- const evictedKeys = await context.evictionManager.onItemAdded(keyStr2, ret, cacheMap);
1202
- await ttlManager.onItemAdded(keyStr2, cacheMap);
1559
+ const metadataDuration = Date.now() - metadataStart;
1560
+ const evictionStart = Date.now();
1561
+ const evictedKeys = await context.evictionManager.onItemAdded(itemKeyStr, ret, cacheMap);
1562
+ const evictionDuration = Date.now() - evictionStart;
1563
+ if (evictedKeys.length > 0) {
1564
+ logger5.debug("CACHE_OP: Eviction triggered by new item", {
1565
+ key: itemKeyStr,
1566
+ evictedCount: evictedKeys.length,
1567
+ evictedKeys
1568
+ });
1569
+ }
1570
+ const ttlStart = Date.now();
1571
+ await ttlManager.onItemAdded(itemKeyStr, cacheMap);
1572
+ const ttlDuration = Date.now() - ttlStart;
1203
1573
  for (const evictedKey of evictedKeys) {
1204
1574
  const parsedKey = JSON.parse(evictedKey);
1205
1575
  await cacheMap.delete(parsedKey);
1576
+ logger5.debug("CACHE_OP: Removed evicted item", { evictedKey });
1206
1577
  }
1207
1578
  const event = CacheEventFactory.itemRetrieved(ret.key, ret, "api");
1208
1579
  context.eventEmitter.emit(event);
1580
+ const totalDuration = Date.now() - startTime;
1581
+ logger5.debug("CACHE_OP: get() completed successfully (cache miss)", {
1582
+ key: keyStr,
1583
+ apiDuration,
1584
+ cacheSetDuration,
1585
+ metadataDuration,
1586
+ evictionDuration,
1587
+ ttlDuration,
1588
+ totalDuration,
1589
+ evictedCount: evictedKeys.length
1590
+ });
1591
+ } else {
1592
+ logger5.debug("CACHE_OP: API returned null", {
1593
+ key: keyStr,
1594
+ apiDuration,
1595
+ totalDuration: Date.now() - startTime
1596
+ });
1209
1597
  }
1210
1598
  } catch (e) {
1211
- inFlightRequests.delete(keyStr);
1212
- logger5.error("Error getting item for key", { key, message: e.message, stack: e.stack });
1599
+ inFlightRequests.delete(requestKeyStr);
1600
+ const duration = Date.now() - startTime;
1601
+ logger5.error("CACHE_OP: Error in get() operation", {
1602
+ key: keyStr,
1603
+ duration,
1604
+ message: e.message,
1605
+ stack: e.stack
1606
+ });
1213
1607
  throw e;
1214
1608
  }
1215
1609
  return ret || null;
@@ -1221,43 +1615,88 @@ import {
1221
1615
  } from "@fjell/core";
1222
1616
  var logger6 = logger_default.get("retrieve");
1223
1617
  var retrieve = async (key, context) => {
1618
+ const startTime = Date.now();
1224
1619
  const { cacheMap, pkType, statsManager } = context;
1620
+ const keyStr = JSON.stringify(key);
1225
1621
  logger6.default("retrieve", { key });
1622
+ logger6.debug("CACHE_OP: retrieve() started", {
1623
+ key: keyStr,
1624
+ cacheType: cacheMap.implementationType,
1625
+ bypassEnabled: !!context.options?.bypassCache
1626
+ });
1226
1627
  statsManager.incrementRequests();
1227
1628
  if (!isValidItemKey2(key)) {
1228
- logger6.error("Key for Retrieve is not a valid ItemKey: %j", key);
1629
+ logger6.error("CACHE_OP: Invalid key for retrieve", { key: keyStr });
1229
1630
  throw new Error("Key for Retrieve is not a valid ItemKey");
1230
1631
  }
1231
1632
  if (context.options?.bypassCache) {
1232
- logger6.debug("Cache bypass enabled, fetching directly from API", { key });
1633
+ logger6.debug("CACHE_OP: Cache bypass enabled, fetching directly from API", { key: keyStr });
1233
1634
  statsManager.incrementMisses();
1234
1635
  try {
1636
+ const apiStartTime = Date.now();
1235
1637
  const { api } = context;
1236
1638
  const retrieved2 = await api.get(key);
1639
+ const apiDuration = Date.now() - apiStartTime;
1237
1640
  if (retrieved2) {
1238
- logger6.debug("API response received (not cached due to bypass)", { key });
1641
+ logger6.debug("CACHE_OP: API response received (bypass mode)", {
1642
+ key: keyStr,
1643
+ apiDuration,
1644
+ hasValue: true
1645
+ });
1239
1646
  return [null, retrieved2];
1240
1647
  } else {
1241
- logger6.debug("API returned null", { key });
1648
+ logger6.debug("CACHE_OP: API returned null (bypass mode)", {
1649
+ key: keyStr,
1650
+ apiDuration
1651
+ });
1242
1652
  return [null, null];
1243
1653
  }
1244
1654
  } catch (error) {
1245
- logger6.error("API request failed", { key, error });
1655
+ const duration = Date.now() - startTime;
1656
+ logger6.error("CACHE_OP: API request failed in bypass mode", {
1657
+ key: keyStr,
1658
+ duration,
1659
+ error
1660
+ });
1246
1661
  throw error;
1247
1662
  }
1248
1663
  }
1249
1664
  const containsItemKey = await cacheMap.includesKey(key);
1665
+ logger6.debug("CACHE_OP: Cache key check completed", {
1666
+ key: keyStr,
1667
+ exists: containsItemKey
1668
+ });
1250
1669
  let retrieved;
1251
1670
  let contextToReturn;
1252
1671
  if (containsItemKey) {
1253
1672
  logger6.default("Looking for Object in Cache", key);
1673
+ logger6.debug("CACHE_OP: Cache HIT - retrieving from cache", { key: keyStr });
1674
+ const getStartTime = Date.now();
1254
1675
  retrieved = await cacheMap.get(key);
1676
+ const getDuration = Date.now() - getStartTime;
1255
1677
  contextToReturn = null;
1256
1678
  statsManager.incrementHits();
1679
+ const totalDuration = Date.now() - startTime;
1680
+ logger6.debug("CACHE_OP: retrieve() completed (cache hit)", {
1681
+ key: keyStr,
1682
+ getDuration,
1683
+ totalDuration,
1684
+ hasValue: !!retrieved
1685
+ });
1257
1686
  } else {
1258
1687
  logger6.default("Object Not Found in Cache, Retrieving from Server API", { key });
1688
+ logger6.debug("CACHE_OP: Cache MISS - fetching from API", { key: keyStr });
1259
1689
  statsManager.incrementMisses();
1690
+ const apiStartTime = Date.now();
1260
1691
  [contextToReturn, retrieved] = await get(key, context);
1692
+ const apiDuration = Date.now() - apiStartTime;
1693
+ const totalDuration = Date.now() - startTime;
1694
+ logger6.debug("CACHE_OP: retrieve() completed (cache miss)", {
1695
+ key: keyStr,
1696
+ apiDuration,
1697
+ totalDuration,
1698
+ hasValue: !!retrieved
1699
+ });
1261
1700
  }
1262
1701
  const retValue = [
1263
1702
  contextToReturn,
@@ -1752,44 +2191,107 @@ async function executeFindLogic(finder, params, locations, context) {
1752
2191
  }
1753
2192
  }
1754
2193
  const queryHash = createFinderHash(finder, params, locations);
1755
- logger14.debug("Generated query hash for find", { queryHash, finder, params, locations });
2194
+ logger14.debug("QUERY_CACHE: Generated query hash for find()", {
2195
+ queryHash,
2196
+ finder,
2197
+ params: JSON.stringify(params),
2198
+ locations: JSON.stringify(locations)
2199
+ });
2200
+ logger14.debug("QUERY_CACHE: Checking query cache for hash", { queryHash });
1756
2201
  const cachedItemKeys = await cacheMap.getQueryResult(queryHash);
1757
2202
  if (cachedItemKeys) {
1758
- logger14.debug("Using cached query results", { cachedKeyCount: cachedItemKeys.length, queryHash });
2203
+ logger14.debug("QUERY_CACHE: Cache HIT - Found cached query result", {
2204
+ queryHash,
2205
+ cachedKeyCount: cachedItemKeys.length,
2206
+ itemKeys: cachedItemKeys.map((k) => JSON.stringify(k))
2207
+ });
1759
2208
  const cachedItems = [];
1760
2209
  let allItemsAvailable = true;
2210
+ const missingKeys = [];
1761
2211
  for (const itemKey of cachedItemKeys) {
1762
2212
  const item = await cacheMap.get(itemKey);
1763
2213
  if (item) {
1764
2214
  cachedItems.push(item);
2215
+ logger14.debug("QUERY_CACHE: Retrieved cached item", {
2216
+ itemKey: JSON.stringify(itemKey),
2217
+ itemKeyStr: JSON.stringify(item.key)
2218
+ });
1765
2219
  } else {
1766
2220
  allItemsAvailable = false;
2221
+ missingKeys.push(itemKey);
2222
+ logger14.debug("QUERY_CACHE: Cached item MISSING from item cache", {
2223
+ itemKey: JSON.stringify(itemKey),
2224
+ queryHash
2225
+ });
1767
2226
  break;
1768
2227
  }
1769
2228
  }
1770
2229
  if (allItemsAvailable) {
2230
+ logger14.debug("QUERY_CACHE: All cached items available, returning from cache", {
2231
+ queryHash,
2232
+ itemCount: cachedItems.length
2233
+ });
1771
2234
  return cachedItems;
1772
2235
  } else {
1773
- logger14.debug("Some cached items missing, invalidating query cache");
2236
+ logger14.debug("QUERY_CACHE: Some cached items missing, invalidating query cache", {
2237
+ queryHash,
2238
+ missingKeys: missingKeys.map((k) => JSON.stringify(k)),
2239
+ foundCount: cachedItems.length,
2240
+ expectedCount: cachedItemKeys.length
2241
+ });
1774
2242
  cacheMap.deleteQueryResult(queryHash);
1775
2243
  }
2244
+ } else {
2245
+ logger14.debug("QUERY_CACHE: Cache MISS - No cached query result found", { queryHash });
1776
2246
  }
2247
+ logger14.debug("QUERY_CACHE: Fetching from API (cache miss or invalid)", {
2248
+ queryHash,
2249
+ finder,
2250
+ params: JSON.stringify(params),
2251
+ locations: JSON.stringify(locations)
2252
+ });
1777
2253
  const ret = await api.find(finder, params, locations);
2254
+ logger14.debug("QUERY_CACHE: API response received", {
2255
+ queryHash,
2256
+ itemCount: ret.length,
2257
+ itemKeys: ret.map((item) => JSON.stringify(item.key))
2258
+ });
2259
+ logger14.debug("QUERY_CACHE: Storing items in item cache", {
2260
+ queryHash,
2261
+ itemCount: ret.length
2262
+ });
1778
2263
  for (const v of ret) {
1779
2264
  await cacheMap.set(v.key, v);
2265
+ logger14.debug("QUERY_CACHE: Stored item in cache", {
2266
+ itemKey: JSON.stringify(v.key),
2267
+ queryHash
2268
+ });
1780
2269
  const keyStr = JSON.stringify(v.key);
1781
2270
  ttlManager.onItemAdded(keyStr, cacheMap);
1782
2271
  const evictedKeys = await context.evictionManager.onItemAdded(keyStr, v, cacheMap);
1783
2272
  for (const evictedKey of evictedKeys) {
1784
2273
  const parsedKey = JSON.parse(evictedKey);
1785
2274
  await cacheMap.delete(parsedKey);
2275
+ logger14.debug("QUERY_CACHE: Evicted item due to cache limits", {
2276
+ evictedKey,
2277
+ queryHash
2278
+ });
1786
2279
  }
1787
2280
  }
1788
2281
  const itemKeys = ret.map((item) => item.key);
1789
- cacheMap.setQueryResult(queryHash, itemKeys);
1790
- logger14.debug("Cached query result", { queryHash, itemKeyCount: itemKeys.length });
2282
+ await cacheMap.setQueryResult(queryHash, itemKeys);
2283
+ logger14.debug("QUERY_CACHE: Stored query result in query cache", {
2284
+ queryHash,
2285
+ itemKeyCount: itemKeys.length,
2286
+ itemKeys: itemKeys.map((k) => JSON.stringify(k))
2287
+ });
1791
2288
  const event = CacheEventFactory.createQueryEvent(params, locations, ret);
1792
2289
  eventEmitter.emit(event);
2290
+ logger14.debug("QUERY_CACHE: Emitted query event", { queryHash });
2291
+ logger14.debug("QUERY_CACHE: find() operation completed", {
2292
+ queryHash,
2293
+ resultCount: ret.length
2294
+ });
1793
2295
  return ret;
1794
2296
  }
1795
2297
 
@@ -1827,34 +2329,86 @@ async function executeFindOneLogic(finder, finderParams, locations, context) {
1827
2329
  }
1828
2330
  }
1829
2331
  const queryHash = createFinderHash(finder, finderParams, locations);
1830
- logger15.debug("Generated query hash for findOne", { queryHash });
2332
+ logger15.debug("QUERY_CACHE: Generated query hash for findOne()", {
2333
+ queryHash,
2334
+ finder,
2335
+ finderParams: JSON.stringify(finderParams),
2336
+ locations: JSON.stringify(locations)
2337
+ });
2338
+ logger15.debug("QUERY_CACHE: Checking query cache for hash", { queryHash });
1831
2339
  const cachedItemKeys = await cacheMap.getQueryResult(queryHash);
1832
2340
  if (cachedItemKeys && cachedItemKeys.length > 0) {
1833
- logger15.debug("Using cached query results", { cachedKeyCount: cachedItemKeys.length });
1834
- const item = await cacheMap.get(cachedItemKeys[0]);
2341
+ logger15.debug("QUERY_CACHE: Cache HIT - Found cached query result", {
2342
+ queryHash,
2343
+ cachedKeyCount: cachedItemKeys.length,
2344
+ itemKeys: cachedItemKeys.map((k) => JSON.stringify(k))
2345
+ });
2346
+ const itemKey = cachedItemKeys[0];
2347
+ logger15.debug("QUERY_CACHE: Retrieving first cached item", {
2348
+ queryHash,
2349
+ itemKey: JSON.stringify(itemKey)
2350
+ });
2351
+ const item = await cacheMap.get(itemKey);
1835
2352
  if (item) {
2353
+ logger15.debug("QUERY_CACHE: Retrieved cached item successfully", {
2354
+ queryHash,
2355
+ itemKey: JSON.stringify(itemKey),
2356
+ itemKeyStr: JSON.stringify(item.key)
2357
+ });
1836
2358
  return item;
1837
2359
  } else {
1838
- logger15.debug("Cached item missing, invalidating query cache");
2360
+ logger15.debug("QUERY_CACHE: Cached item MISSING from item cache, invalidating query cache", {
2361
+ queryHash,
2362
+ itemKey: JSON.stringify(itemKey)
2363
+ });
1839
2364
  cacheMap.deleteQueryResult(queryHash);
1840
2365
  }
2366
+ } else {
2367
+ logger15.debug("QUERY_CACHE: Cache MISS - No cached query result found", { queryHash });
1841
2368
  }
2369
+ logger15.debug("QUERY_CACHE: Fetching from API (cache miss or invalid)", {
2370
+ queryHash,
2371
+ finder,
2372
+ finderParams: JSON.stringify(finderParams),
2373
+ locations: JSON.stringify(locations)
2374
+ });
1842
2375
  const ret = await api.findOne(finder, finderParams, locations);
1843
2376
  if (ret === null) {
2377
+ logger15.debug("QUERY_CACHE: API returned null, throwing error", { queryHash, finder });
1844
2378
  throw new Error(`findOne returned null for finder: ${finder}`);
1845
2379
  }
1846
- cacheMap.set(ret.key, ret);
2380
+ logger15.debug("QUERY_CACHE: API response received", {
2381
+ queryHash,
2382
+ itemKey: JSON.stringify(ret.key)
2383
+ });
2384
+ logger15.debug("QUERY_CACHE: Storing item in item cache", {
2385
+ queryHash,
2386
+ itemKey: JSON.stringify(ret.key)
2387
+ });
2388
+ await cacheMap.set(ret.key, ret);
1847
2389
  const keyStr = JSON.stringify(ret.key);
1848
2390
  ttlManager.onItemAdded(keyStr, cacheMap);
1849
2391
  const evictedKeys = await context.evictionManager.onItemAdded(keyStr, ret, cacheMap);
1850
2392
  for (const evictedKey of evictedKeys) {
1851
2393
  const parsedKey = JSON.parse(evictedKey);
1852
2394
  await cacheMap.delete(parsedKey);
2395
+ logger15.debug("QUERY_CACHE: Evicted item due to cache limits", {
2396
+ evictedKey,
2397
+ queryHash
2398
+ });
1853
2399
  }
1854
- cacheMap.setQueryResult(queryHash, [ret.key]);
1855
- logger15.debug("Cached query result", { queryHash, itemKey: ret.key });
2400
+ await cacheMap.setQueryResult(queryHash, [ret.key]);
2401
+ logger15.debug("QUERY_CACHE: Stored query result in query cache", {
2402
+ queryHash,
2403
+ itemKey: JSON.stringify(ret.key)
2404
+ });
1856
2405
  const event = CacheEventFactory.createQueryEvent(finderParams, locations, [ret]);
1857
2406
  eventEmitter.emit(event);
2407
+ logger15.debug("QUERY_CACHE: Emitted query event", { queryHash });
2408
+ logger15.debug("QUERY_CACHE: findOne() operation completed", {
2409
+ queryHash,
2410
+ itemKey: JSON.stringify(ret.key)
2411
+ });
1858
2412
  return ret;
1859
2413
  }
1860
2414
 
@@ -1912,39 +2466,93 @@ var normalizeKey = (key) => {
1912
2466
  return key;
1913
2467
  };
1914
2468
  var set = async (key, v, context) => {
2469
+ const startTime = Date.now();
1915
2470
  const { cacheMap, pkType, ttlManager, evictionManager, eventEmitter } = context;
2471
+ const keyStr = JSON.stringify(key);
1916
2472
  logger16.default("set", { key, v });
2473
+ logger16.debug("CACHE_OP: set() started", {
2474
+ key: keyStr,
2475
+ cacheType: cacheMap.implementationType
2476
+ });
1917
2477
  if (!isValidItemKey6(key)) {
1918
- logger16.error("Key for Set is not a valid ItemKey: %j", key);
2478
+ logger16.error("CACHE_OP: Invalid key for set", { key: keyStr });
1919
2479
  throw new Error("Key for Set is not a valid ItemKey");
1920
2480
  }
1921
2481
  if (!isItemKeyEqualNormalized(key, v.key)) {
1922
- logger16.error("Key does not match item key: %j != %j", key, v.key);
2482
+ logger16.error("CACHE_OP: Key mismatch in set", {
2483
+ providedKey: keyStr,
2484
+ itemKey: JSON.stringify(v.key)
2485
+ });
1923
2486
  throw new Error("Key does not match item key");
1924
2487
  }
2488
+ const checkStartTime = Date.now();
1925
2489
  const previousItem = await cacheMap.get(key);
2490
+ const checkDuration = Date.now() - checkStartTime;
2491
+ logger16.debug("CACHE_OP: Previous item check", {
2492
+ key: keyStr,
2493
+ hadPreviousItem: !!previousItem,
2494
+ checkDuration
2495
+ });
2496
+ const setStartTime = Date.now();
1926
2497
  await cacheMap.set(key, v);
1927
- const keyStr = JSON.stringify(key);
2498
+ const setDuration = Date.now() - setStartTime;
2499
+ const metadataStartTime = Date.now();
1928
2500
  const metadata = await cacheMap.getMetadata(keyStr);
1929
2501
  if (!metadata) {
1930
2502
  const now = Date.now();
2503
+ const estimatedSize = estimateValueSize(v);
1931
2504
  const baseMetadata = {
1932
2505
  key: keyStr,
1933
2506
  addedAt: now,
1934
2507
  lastAccessedAt: now,
1935
2508
  accessCount: 1,
1936
- estimatedSize: estimateValueSize(v)
2509
+ estimatedSize
1937
2510
  };
1938
2511
  await cacheMap.setMetadata(keyStr, baseMetadata);
2512
+ logger16.debug("CACHE_OP: Created base metadata", {
2513
+ key: keyStr,
2514
+ estimatedSize
2515
+ });
2516
+ } else {
2517
+ logger16.debug("CACHE_OP: Metadata already exists", {
2518
+ key: keyStr,
2519
+ addedAt: new Date(metadata.addedAt).toISOString(),
2520
+ accessCount: metadata.accessCount
2521
+ });
1939
2522
  }
2523
+ const metadataDuration = Date.now() - metadataStartTime;
2524
+ const ttlStartTime = Date.now();
1940
2525
  await ttlManager.onItemAdded(keyStr, cacheMap);
2526
+ const ttlDuration = Date.now() - ttlStartTime;
2527
+ const evictionStartTime = Date.now();
1941
2528
  const evictedKeys = await evictionManager.onItemAdded(keyStr, v, cacheMap);
2529
+ const evictionDuration = Date.now() - evictionStartTime;
2530
+ if (evictedKeys.length > 0) {
2531
+ logger16.debug("CACHE_OP: Eviction triggered by set", {
2532
+ key: keyStr,
2533
+ evictedCount: evictedKeys.length,
2534
+ evictedKeys
2535
+ });
2536
+ }
1942
2537
  for (const evictedKey of evictedKeys) {
1943
2538
  const parsedKey = JSON.parse(evictedKey);
1944
2539
  await cacheMap.delete(parsedKey);
2540
+ logger16.debug("CACHE_OP: Removed evicted item", { evictedKey });
1945
2541
  }
1946
2542
  const event = CacheEventFactory.itemSet(key, v, previousItem);
1947
2543
  eventEmitter.emit(event);
2544
+ const totalDuration = Date.now() - startTime;
2545
+ logger16.debug("CACHE_OP: set() completed", {
2546
+ key: keyStr,
2547
+ checkDuration,
2548
+ setDuration,
2549
+ metadataDuration,
2550
+ ttlDuration,
2551
+ evictionDuration,
2552
+ totalDuration,
2553
+ evictedCount: evictedKeys.length,
2554
+ wasUpdate: !!previousItem
2555
+ });
1948
2556
  return [context, v];
1949
2557
  };
1950
2558
 
@@ -5122,9 +5730,17 @@ var EvictionManager = class {
5122
5730
  return;
5123
5731
  }
5124
5732
  try {
5733
+ logger24.debug("EVICTION: Item accessed, updating metadata", {
5734
+ key,
5735
+ strategy: this.evictionStrategy.getStrategyName()
5736
+ });
5125
5737
  await this.evictionStrategy.onItemAccessed(key, metadataProvider);
5126
5738
  } catch (error) {
5127
- logger24.error("Error in eviction strategy onItemAccessed", { key, error });
5739
+ logger24.error("EVICTION: Error in eviction strategy onItemAccessed", {
5740
+ key,
5741
+ error,
5742
+ strategy: this.evictionStrategy?.getStrategyName()
5743
+ });
5128
5744
  }
5129
5745
  }
5130
5746
  /**
@@ -5135,28 +5751,81 @@ var EvictionManager = class {
5135
5751
  * @returns Array of keys that were evicted
5136
5752
  */
5137
5753
  async onItemAdded(key, value, metadataProvider) {
5754
+ const startTime = Date.now();
5138
5755
  const evictedKeys = [];
5139
5756
  if (!this.evictionStrategy) {
5757
+ logger24.debug("EVICTION: No eviction strategy configured", { key });
5140
5758
  return evictedKeys;
5141
5759
  }
5142
5760
  try {
5143
5761
  const estimatedSize = estimateValueSize(value);
5762
+ logger24.debug("EVICTION: Item addition started", {
5763
+ key,
5764
+ estimatedSize,
5765
+ strategy: this.evictionStrategy.getStrategyName()
5766
+ });
5767
+ const contextStartTime = Date.now();
5144
5768
  const context = await this.createEvictionContext(metadataProvider, estimatedSize);
5769
+ const contextDuration = Date.now() - contextStartTime;
5770
+ logger24.debug("EVICTION: Current cache state", {
5771
+ key,
5772
+ currentItemCount: context.currentSize.itemCount,
5773
+ currentSizeBytes: context.currentSize.sizeBytes,
5774
+ maxItems: context.limits.maxItems,
5775
+ maxSizeBytes: context.limits.maxSizeBytes,
5776
+ newItemSize: estimatedSize,
5777
+ contextDuration
5778
+ });
5779
+ const selectionStartTime = Date.now();
5145
5780
  const keysToEvict = await this.evictionStrategy.selectForEviction(metadataProvider, context);
5781
+ const selectionDuration = Date.now() - selectionStartTime;
5782
+ if (keysToEvict.length > 0) {
5783
+ logger24.debug("EVICTION: Items selected for eviction", {
5784
+ key,
5785
+ evictCount: keysToEvict.length,
5786
+ keysToEvict,
5787
+ selectionDuration,
5788
+ strategy: this.evictionStrategy.getStrategyName()
5789
+ });
5790
+ }
5791
+ const removalStartTime = Date.now();
5146
5792
  for (const evictKey of keysToEvict) {
5147
5793
  await this.evictionStrategy.onItemRemoved(evictKey, metadataProvider);
5148
5794
  evictedKeys.push(evictKey);
5795
+ logger24.debug("EVICTION: Marked item for eviction", {
5796
+ evictedKey: evictKey,
5797
+ newKey: key
5798
+ });
5149
5799
  }
5800
+ const removalDuration = Date.now() - removalStartTime;
5801
+ const addMetadataStart = Date.now();
5150
5802
  await this.evictionStrategy.onItemAdded(key, estimatedSize, metadataProvider);
5803
+ const addMetadataDuration = Date.now() - addMetadataStart;
5804
+ const totalDuration = Date.now() - startTime;
5151
5805
  if (evictedKeys.length > 0) {
5152
- logger24.debug("Items evicted during addition", {
5806
+ logger24.debug("EVICTION: Eviction completed", {
5153
5807
  newKey: key,
5808
+ evictedCount: evictedKeys.length,
5154
5809
  evictedKeys,
5155
- strategy: this.evictionStrategy.getStrategyName()
5810
+ strategy: this.evictionStrategy.getStrategyName(),
5811
+ selectionDuration,
5812
+ removalDuration,
5813
+ addMetadataDuration,
5814
+ totalDuration
5815
+ });
5816
+ } else {
5817
+ logger24.debug("EVICTION: No eviction needed", {
5818
+ newKey: key,
5819
+ estimatedSize,
5820
+ totalDuration
5156
5821
  });
5157
5822
  }
5158
5823
  } catch (error) {
5159
- logger24.error("Error in eviction strategy onItemAdded", { key, error });
5824
+ logger24.error("EVICTION: Error in eviction strategy onItemAdded", {
5825
+ key,
5826
+ error,
5827
+ strategy: this.evictionStrategy?.getStrategyName()
5828
+ });
5160
5829
  }
5161
5830
  return evictedKeys;
5162
5831
  }
@@ -5181,25 +5850,47 @@ var EvictionManager = class {
5181
5850
  * @returns Array of keys that were evicted
5182
5851
  */
5183
5852
  async performEviction(metadataProvider) {
5853
+ const startTime = Date.now();
5184
5854
  const evictedKeys = [];
5185
5855
  if (!this.evictionStrategy) {
5856
+ logger24.debug("EVICTION: No eviction strategy configured for manual eviction");
5186
5857
  return evictedKeys;
5187
5858
  }
5188
5859
  try {
5860
+ logger24.debug("EVICTION: Manual eviction started", {
5861
+ strategy: this.evictionStrategy.getStrategyName()
5862
+ });
5189
5863
  const context = await this.createEvictionContext(metadataProvider);
5864
+ logger24.debug("EVICTION: Manual eviction - current cache state", {
5865
+ currentItemCount: context.currentSize.itemCount,
5866
+ currentSizeBytes: context.currentSize.sizeBytes,
5867
+ maxItems: context.limits.maxItems,
5868
+ maxSizeBytes: context.limits.maxSizeBytes
5869
+ });
5190
5870
  const keysToEvict = await this.evictionStrategy.selectForEviction(metadataProvider, context);
5191
5871
  for (const evictKey of keysToEvict) {
5192
5872
  await this.evictionStrategy.onItemRemoved(evictKey, metadataProvider);
5193
5873
  evictedKeys.push(evictKey);
5194
5874
  }
5875
+ const duration = Date.now() - startTime;
5195
5876
  if (evictedKeys.length > 0) {
5196
- logger24.debug("Manual eviction performed", {
5877
+ logger24.debug("EVICTION: Manual eviction completed", {
5878
+ evictedCount: evictedKeys.length,
5197
5879
  evictedKeys,
5198
- strategy: this.evictionStrategy.getStrategyName()
5880
+ strategy: this.evictionStrategy.getStrategyName(),
5881
+ duration
5882
+ });
5883
+ } else {
5884
+ logger24.debug("EVICTION: Manual eviction - no items to evict", {
5885
+ strategy: this.evictionStrategy.getStrategyName(),
5886
+ duration
5199
5887
  });
5200
5888
  }
5201
5889
  } catch (error) {
5202
- logger24.error("Error in manual eviction", { error });
5890
+ logger24.error("EVICTION: Error in manual eviction", {
5891
+ error,
5892
+ strategy: this.evictionStrategy?.getStrategyName()
5893
+ });
5203
5894
  }
5204
5895
  return evictedKeys;
5205
5896
  }
@@ -6628,7 +7319,7 @@ var TTLManager = class {
6628
7319
  metadata
6629
7320
  });
6630
7321
  if (!metadata) {
6631
- logger25.warning("TTL_DEBUG: No metadata found for item when setting TTL", {
7322
+ logger25.debug("TTL_DEBUG: No metadata found for item when setting TTL", {
6632
7323
  key,
6633
7324
  metadataProviderType: metadataProvider?.constructor?.name,
6634
7325
  metadataProviderMethods: metadataProvider ? Object.getOwnPropertyNames(Object.getPrototypeOf(metadataProvider)) : null
@@ -6668,12 +7359,28 @@ var TTLManager = class {
6668
7359
  async isExpired(key, metadataProvider) {
6669
7360
  const metadata = await metadataProvider.getMetadata(key);
6670
7361
  if (!metadata || !metadata.expiresAt) {
7362
+ logger25.debug("TTL_CHECK: No TTL set for item", { key, hasMetadata: !!metadata });
6671
7363
  return false;
6672
7364
  }
6673
7365
  const now = Date.now();
6674
7366
  const expired = now >= metadata.expiresAt;
7367
+ const remainingMs = metadata.expiresAt - now;
6675
7368
  if (expired) {
6676
- logger25.trace("Item expired", { key, expiresAt: metadata.expiresAt, now });
7369
+ logger25.debug("TTL_CHECK: Item EXPIRED", {
7370
+ key,
7371
+ expiresAt: new Date(metadata.expiresAt).toISOString(),
7372
+ now: new Date(now).toISOString(),
7373
+ expiredByMs: now - metadata.expiresAt,
7374
+ ttl: metadata.ttl
7375
+ });
7376
+ } else {
7377
+ logger25.debug("TTL_CHECK: Item still valid", {
7378
+ key,
7379
+ expiresAt: new Date(metadata.expiresAt).toISOString(),
7380
+ remainingMs,
7381
+ remainingSec: Math.floor(remainingMs / 1e3),
7382
+ ttl: metadata.ttl
7383
+ });
6677
7384
  }
6678
7385
  return expired;
6679
7386
  }
@@ -6683,9 +7390,22 @@ var TTLManager = class {
6683
7390
  */
6684
7391
  async validateItem(key, metadataProvider) {
6685
7392
  if (!this.config.validateOnAccess) {
7393
+ logger25.debug("TTL_VALIDATE: Validation disabled, skipping check", { key });
6686
7394
  return true;
6687
7395
  }
6688
- return !await this.isExpired(key, metadataProvider);
7396
+ logger25.debug("TTL_VALIDATE: Validating item", {
7397
+ key,
7398
+ ttlEnabled: this.isTTLEnabled(),
7399
+ defaultTTL: this.config.defaultTTL
7400
+ });
7401
+ const isExpired = await this.isExpired(key, metadataProvider);
7402
+ const isValid = !isExpired;
7403
+ logger25.debug("TTL_VALIDATE: Validation result", {
7404
+ key,
7405
+ isValid,
7406
+ isExpired
7407
+ });
7408
+ return isValid;
6689
7409
  }
6690
7410
  /**
6691
7411
  * Get TTL information for an item
@@ -6710,17 +7430,44 @@ var TTLManager = class {
6710
7430
  * Find all expired items
6711
7431
  */
6712
7432
  async findExpiredItems(metadataProvider) {
7433
+ const startTime = Date.now();
6713
7434
  const expiredKeys = [];
6714
7435
  const allMetadata = await metadataProvider.getAllMetadata();
6715
7436
  const now = Date.now();
7437
+ logger25.debug("TTL_CLEANUP: Scanning for expired items", {
7438
+ totalItems: allMetadata.size,
7439
+ now: new Date(now).toISOString()
7440
+ });
7441
+ let itemsWithTTL = 0;
6716
7442
  for (const [key, metadata] of allMetadata) {
6717
7443
  const ttlMetadata = metadata;
6718
- if (ttlMetadata.expiresAt && now >= ttlMetadata.expiresAt) {
6719
- expiredKeys.push(key);
7444
+ if (ttlMetadata.expiresAt) {
7445
+ itemsWithTTL++;
7446
+ if (now >= ttlMetadata.expiresAt) {
7447
+ expiredKeys.push(key);
7448
+ logger25.debug("TTL_CLEANUP: Found expired item", {
7449
+ key,
7450
+ expiresAt: new Date(ttlMetadata.expiresAt).toISOString(),
7451
+ expiredByMs: now - ttlMetadata.expiresAt
7452
+ });
7453
+ }
6720
7454
  }
6721
7455
  }
7456
+ const duration = Date.now() - startTime;
6722
7457
  if (expiredKeys.length > 0) {
6723
- logger25.debug("Found expired items", { count: expiredKeys.length, keys: expiredKeys });
7458
+ logger25.debug("TTL_CLEANUP: Expired items found", {
7459
+ expiredCount: expiredKeys.length,
7460
+ totalItems: allMetadata.size,
7461
+ itemsWithTTL,
7462
+ keys: expiredKeys,
7463
+ duration
7464
+ });
7465
+ } else {
7466
+ logger25.debug("TTL_CLEANUP: No expired items found", {
7467
+ totalItems: allMetadata.size,
7468
+ itemsWithTTL,
7469
+ duration
7470
+ });
6724
7471
  }
6725
7472
  return expiredKeys;
6726
7473
  }