@itentialopensource/adapter-utils 5.10.6 → 5.10.7

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.
Files changed (2) hide show
  1. package/lib/cacheHandler.js +245 -181
  2. package/package.json +1 -1
@@ -43,7 +43,12 @@ function deleteCacheData(cacheHandler) {
43
43
 
44
44
  const handler = cacheHandler;
45
45
 
46
- // get all keys to make sure nothing else is editing the cache at this time
46
+ // Log INFO level if cache is disabled
47
+ if (!handler.enabled) {
48
+ log.info(`${origin}: Cache is turned off.`);
49
+ }
50
+
51
+ // Get all keys to ensure nothing else is editing the cache at this time
47
52
  const keysArr = [];
48
53
  handler.cache.forEach((entity) => {
49
54
  keysArr.push(entity.lockKey);
@@ -51,12 +56,18 @@ function deleteCacheData(cacheHandler) {
51
56
 
52
57
  lock.acquire(keysArr, () => {
53
58
  if (!handler.enabled) {
59
+ // Clear cache and log once when going from enabled to disabled
60
+ if (handler.cache.length > 0 || handler.propertiesMap.size > 0) {
61
+ log.info(`${origin}: Cache has been cleared.`);
62
+ }
63
+
54
64
  handler.cache.forEach((entity) => {
55
65
  clearInterval(entity.intervalId);
56
66
  });
57
67
  handler.cache = [];
58
68
  handler.propertiesMap.clear();
59
- log.warn(`${origin}: Cache deletion confirmed`);
69
+ } else {
70
+ log.debug(`${origin}: Cache is currently enabled.`);
60
71
  }
61
72
  });
62
73
  }
@@ -132,79 +143,91 @@ function validateProperties(obj) {
132
143
  }
133
144
 
134
145
  const props = obj;
135
- // check cache, cache.enabled, cache.entities exist
146
+
147
+ // Check cache, cache.enabled, cache.entities exist
136
148
  if (!props.cache) {
137
- // no cache, no props
149
+ // No cache, initialize default props
138
150
  props.cache = {
139
151
  enabled: false,
140
152
  entities: []
141
153
  };
142
154
  } else {
143
155
  if (!props.cache.enabled) {
156
+ log.info(`${origin}: Cache is turned off.`);
144
157
  props.cache.enabled = false;
145
- log.error(`${origin}: Passed in cache properties but did not specify enabled!`);
146
158
  }
147
- if (!props.cache.entities) {
159
+
160
+ if (props.cache.enabled && !props.cache.entities) {
148
161
  props.cache.entities = [];
149
- log.error(`${origin}: Passed in cache properties but did not specify entities (not even as empty array)!`);
162
+ log.info(`${origin}: Cache entities initialized as an empty array.`);
150
163
  }
151
164
  }
152
- // check each entity type in entities
153
- for (let i = 0; i < props.cache.entities.length; i += 1) {
154
- // must have entityType and populate
155
- if (!props.cache.entities[i].entityType || !props.cache.entities[i].populate || props.cache.entities[i].populate.length === 0) {
156
- log.warn(`${origin}: removed invalid cache property at index ${i}`);
157
- // remove rather than throw error
158
- props.cache.entities.splice(i, 1);
159
- i -= 1; // already pointing at next after splice
160
- break;
161
- }
162
165
 
163
- // default frequency = 24 hrs, caps if <60 or >10080
164
- if (!props.cache.entities[i].frequency) {
165
- props.cache.entities[i].frequency = 24 * 60; // 1 day in minutes
166
- } else if (props.cache.entities[i].frequency < 15) { // 15 min minimum
167
- log.warn(`${origin}: Passed in frequency of ${props.cache.entities[i].frequency} is too small! Set to 15 minute.`);
168
- props.cache.entities[i].frequency = 15;
169
- } else if (props.cache.entities[i].frequency > 10080) { // 1 week max
170
- log.warn(`${origin}: Passed in frequency of ${props.cache.entities[i].frequency} is too large! Set to 1 week.`);
171
- props.cache.entities[i].frequency = 10080;
172
- }
166
+ // Validate each entity in cache.entities if cache is enabled
167
+ if (props.cache.enabled) {
168
+ for (let i = 0; i < props.cache.entities.length; i += 1) {
169
+ const entity = props.cache.entities[i];
170
+
171
+ // Ensure entityType and populate exist and are valid
172
+ if (!entity.entityType || !entity.populate || entity.populate.length === 0) {
173
+ log.warn(`${origin}: Removed invalid cache property at index ${i}`);
174
+ props.cache.entities.splice(i, 1);
175
+ i -= 1; // Adjust index after removal
176
+ break;
177
+ }
173
178
 
174
- // default flushOnFail = false
175
- if (!props.cache.entities[i].flushOnFail) {
176
- props.cache.entities[i].flushOnFail = false;
177
- }
179
+ // Validate frequency (default: 24 hrs, min: 15 mins, max: 1 week)
180
+ if (!entity.frequency) {
181
+ entity.frequency = 24 * 60; // Default to 1 day in minutes
182
+ log.debug(`${origin}: Frequency set to default (1440 minutes).`);
183
+ } else if (entity.frequency < 15) {
184
+ log.warn(`${origin}: Frequency ${entity.frequency} too small! Adjusted to 15 minutes.`);
185
+ entity.frequency = 15;
186
+ } else if (entity.frequency > 10080) {
187
+ log.warn(`${origin}: Frequency ${entity.frequency} too large! Adjusted to 1 week.`);
188
+ entity.frequency = 10080;
189
+ }
178
190
 
179
- // Limits entity type to 1000 entities
180
- if (!props.cache.entities[i].limit) {
181
- props.cache.entities[i].limits = 1000;
182
- }
191
+ // Default flushOnFail = false
192
+ if (entity.flushOnFail === undefined) {
193
+ entity.flushOnFail = false;
194
+ log.debug(`${origin}: flushOnFail defaulted to false.`);
195
+ }
183
196
 
184
- if (!props.cache.entities[i].retryAttempts) {
185
- props.cache.entities[i].retryAttempts = 5; // currently only used for startup
186
- }
197
+ // Default limit = 1000
198
+ if (!entity.limit) {
199
+ entity.limit = 1000;
200
+ log.debug(`${origin}: Limit defaulted to 1000.`);
201
+ }
187
202
 
188
- // make sure task and filterField exists for every object in cachedTasks
189
- if (!props.cache.entities[i].cachedTasks) {
190
- props.cache.entities[i].cachedTasks = [];
191
- } else {
192
- props.cache.entities[i].cachedTasks.forEach((cacheTask) => {
193
- const curTask = cacheTask; // for lint
194
- if (!curTask.name) {
195
- log.error('Cached task has no task name!');
196
- curTask.name = ''; // prevent errors, will not ever match a task name
197
- }
198
- if (!curTask.filterField) {
199
- // if no filter then assume is a get all call, would need to explicitly check this
200
- curTask.filterField = '';
201
- }
202
- });
203
- }
203
+ // Default retryAttempts = 5
204
+ if (!entity.retryAttempts) {
205
+ entity.retryAttempts = 5; // Used for startup retries
206
+ log.debug(`${origin}: retryAttempts defaulted to 5.`);
207
+ }
204
208
 
205
- // fill in missing populate fields
206
- validatePopulate(props.cache.entities[i].populate);
209
+ // Validate cachedTasks
210
+ if (!entity.cachedTasks) {
211
+ entity.cachedTasks = [];
212
+ log.debug(`${origin}: cachedTasks initialized as an empty array.`);
213
+ } else {
214
+ entity.cachedTasks.forEach((cacheTask, idx) => {
215
+ const curTask = cacheTask; // for lint
216
+ if (!cacheTask.name) {
217
+ log.error(`${origin}: Cached task at index ${idx} has no name! Defaulting to an empty string.`);
218
+ curTask.name = ''; // Prevent errors, will not match a task name
219
+ }
220
+ if (!cacheTask.filterField) {
221
+ curTask.filterField = ''; // Assume a "get all" call if no filter specified
222
+ }
223
+ });
224
+ }
225
+
226
+ // Fill in missing populate fields
227
+ validatePopulate(entity.populate);
228
+ }
207
229
  }
230
+
208
231
  return props;
209
232
  }
210
233
 
@@ -337,15 +360,20 @@ function removeCacheEntry(cache, entityType) {
337
360
 
338
361
  for (let i = 0; i < cache.length; i += 1) {
339
362
  if (cache[i].entityType === entityType) {
363
+ log.debug(`${origin}: Found entity type '${entityType}' in cache. Attempting to remove.`);
364
+
340
365
  lock.acquire(cache[i].lockKey, () => {
366
+ log.debug(`${origin}: Lock acquired for entity type '${entityType}'. Clearing interval and removing from cache.`);
341
367
  clearInterval(cache[i].intervalId);
342
- cache[i].splice(i, 1);
368
+ cache.splice(i, 1);
343
369
  });
344
- log.info(`Successfully removed ${entityType} from cache.`);
370
+
371
+ log.info(`${origin}: Successfully removed '${entityType}' from cache.`);
345
372
  return;
346
373
  }
347
374
  }
348
- log.error(`${origin}: Did not find cache type ${entityType} to remove!`);
375
+
376
+ log.error(`${origin}: Entity type '${entityType}' not found in cache. Removal failed.`);
349
377
  }
350
378
 
351
379
  /**
@@ -477,76 +505,92 @@ class CacheHandler {
477
505
  return;
478
506
  }
479
507
 
508
+ log.debug(`${origin}: Validating and setting new properties.`);
480
509
  this.props = validateProperties(properties);
481
510
 
482
511
  const wasEnabled = this.enabled || false; // in case undefined
483
512
  this.enabled = this.props.cache.enabled;
513
+
484
514
  if (!this.enabled) {
485
- // destroy cache and properties for memory efficiency
486
515
  if (wasEnabled) {
516
+ log.warn(`${origin}: Cache was disabled from enabled state. Clearing cache for memory efficiency.`);
487
517
  deleteCacheData(this);
488
518
  } else {
489
519
  log.debug(`${origin}: Cache remains disabled. No action required.`);
490
520
  }
491
- log.warn('Cache was disabled from enabled, removed cache memory.');
492
521
  return;
493
522
  }
494
523
 
495
- // check entityType was not deleted (if so flush that cache type)
524
+ log.debug(`${origin}: Checking for deleted or updated entity types.`);
496
525
  this.propertiesMap.forEach((value, key) => {
526
+ let entityExists = false;
527
+
497
528
  for (let i = 0; i < this.props.cache.entities.length; i += 1) {
498
- if (!this.props.cache.entities[i].name === key) { // currently in cache, but not props
499
- removeCacheEntry(this.cache, key);
500
- this.propertiesMap.delete(key);
501
- log.warn(`${origin}: Removed cache entity type due to change in properties.`);
502
- log.info(`Deleted props for entity type ${key} with val ${value}`);
503
- return; // continue forEach
529
+ if (this.props.cache.entities[i].name === key) {
530
+ entityExists = true;
531
+ break;
504
532
  }
505
533
  }
534
+
535
+ if (!entityExists) {
536
+ log.warn(`${origin}: Detected removed entity type '${key}'. Removing from cache.`);
537
+ removeCacheEntry(this.cache, key);
538
+ this.propertiesMap.delete(key);
539
+ log.info(`${origin}: Deleted properties for entity type '${key}' with value '${value}'.`);
540
+ }
506
541
  });
507
542
 
508
- // set properties map
543
+ log.debug(`${origin}: Updating and setting properties map for cache entities.`);
509
544
  this.props.cache.entities.forEach((entity) => {
510
545
  if (!this.propertiesMap.has(entity.entityType)) {
511
- // entity does not exist yet
546
+ log.debug(`${origin}: Adding new entity type '${entity.entityType}' to properties map.`);
512
547
  this.propertiesMap.set(entity.entityType, {});
513
- this.propertiesMap.get(entity.entityType).frequency = entity.frequency;
514
- this.propertiesMap.get(entity.entityType).flushOnFail = entity.flushOnFail;
515
- this.propertiesMap.get(entity.entityType).populate = entity.populate;
516
- this.propertiesMap.get(entity.entityType).limit = entity.limit;
517
- this.propertiesMap.get(entity.entityType).retryAttempts = entity.retryAttempts;
548
+ const entityProps = this.propertiesMap.get(entity.entityType);
549
+ entityProps.frequency = entity.frequency;
550
+ entityProps.flushOnFail = entity.flushOnFail;
551
+ entityProps.populate = entity.populate;
552
+ entityProps.limit = entity.limit;
553
+ entityProps.retryAttempts = entity.retryAttempts;
518
554
 
519
555
  const newIntervalId = setInterval(() => {
556
+ log.debug(`${origin}: Populating cache for entity type '${entity.entityType}'.`);
520
557
  this.populateCache(entity.entityType);
521
558
  }, entity.frequency * 60000);
522
559
 
523
560
  const sort = Object.prototype.hasOwnProperty.call(entity, 'sort') ? entity.sort : true; // default true
524
561
  this.cache.push(createCacheEntity(entity.entityType, null, newIntervalId, sort));
525
- this.populateCache(entity.entityType).then((result) => {
526
- if (result && result[0] === 'error') {
527
- retryPopulate(entity.entityType, this, entity.retryAttempts).then((nextResult) => {
528
- log.info(nextResult);
529
- });
530
- }
531
- }).catch((error) => {
532
- log.error('Failed populate cache!');
533
- if (error.icode === 'AD.301') {
534
- log.error(`Destroying interval, check path and call in properties for ${entity.entityType}`);
535
- clearInterval(newIntervalId);
536
- this.cache.removeCacheEntry(this.cache, entity.entityType);
537
- }
538
- });
562
+
563
+ this.populateCache(entity.entityType)
564
+ .then((result) => {
565
+ if (result && result[0] === 'error') {
566
+ log.warn(`${origin}: Populate failed for '${entity.entityType}'. Retrying...`);
567
+ retryPopulate(entity.entityType, this, entity.retryAttempts).then((nextResult) => {
568
+ log.info(`${origin}: Retry result for '${entity.entityType}': ${nextResult}`);
569
+ });
570
+ }
571
+ })
572
+ .catch((error) => {
573
+ log.error(`${origin}: Populate cache failed for '${entity.entityType}'.`);
574
+ if (error.icode === 'AD.301') {
575
+ log.error(`${origin}: Clearing interval and removing cache entity '${entity.entityType}' due to error.`);
576
+ clearInterval(newIntervalId);
577
+ this.cache.removeCacheEntry(this.cache, entity.entityType);
578
+ }
579
+ });
539
580
  } else {
540
- // entity props frequency updated
541
- if (entity.frequency !== this.propertiesMap.get(entity.entityType).frequency) {
581
+ log.debug(`${origin}: Updating frequency and properties for existing entity type '${entity.entityType}'.`);
582
+ const entityProps = this.propertiesMap.get(entity.entityType);
583
+
584
+ if (entity.frequency !== entityProps.frequency) {
585
+ log.info(`${origin}: Updating update frequency for '${entity.entityType}' from '${entityProps.frequency}' to '${entity.frequency}'.`);
542
586
  changeUpdateFrequency(this.cache, entity.entityType, entity.frequency, this);
543
587
  }
544
588
 
545
- this.propertiesMap.get(entity.entityType).frequency = entity.frequency;
546
- this.propertiesMap.get(entity.entityType).flushOnFail = entity.flushOnFail;
547
- this.propertiesMap.get(entity.entityType).populate = entity.populate;
548
- this.propertiesMap.get(entity.entityType).limit = entity.limit;
549
- this.propertiesMap.get(entity.entityType).retryAttempts = entity.retryAttempts;
589
+ entityProps.frequency = entity.frequency;
590
+ entityProps.flushOnFail = entity.flushOnFail;
591
+ entityProps.populate = entity.populate;
592
+ entityProps.limit = entity.limit;
593
+ entityProps.retryAttempts = entity.retryAttempts;
550
594
  }
551
595
  });
552
596
  }
@@ -563,37 +607,37 @@ class CacheHandler {
563
607
  log.trace(origin);
564
608
 
565
609
  if (!this.enabled) {
610
+ log.info(`${origin}: Cache is not enabled. Populate operation aborted.`);
566
611
  return Promise.reject(new Error('Cache is not enabled!'));
567
612
  }
568
613
 
569
- log.info('Populating cache.');
614
+ log.info(`${origin}: Starting cache population.`);
570
615
 
571
- // support string and array input
616
+ // Support string and array input
572
617
  let entityArr = entities;
573
618
  if (!Array.isArray(entities)) {
574
619
  entityArr = [entities];
575
620
  }
576
621
 
577
- // need all properties to make iap call
622
+ // Ensure all entities are tracked
578
623
  for (let i = 0; i < entityArr.length; i += 1) {
579
624
  const entityType = entityArr[i];
580
625
  if (!this.propertiesMap.has(entityType)) {
581
- log.error(`${entityType} is an untracked entity type! Check properties.`);
626
+ log.error(`${origin}: ${entityType} is an untracked entity type! Check properties.`);
582
627
  return Promise.reject(new Error(`${entityType} is an untracked entity type! Check properties.`));
583
628
  }
584
629
  }
585
630
 
586
631
  try {
587
632
  const promiseArr = [];
588
- // for each entityType need to populate
633
+ // Populate each entity type
589
634
  for (let j = 0; j < entityArr.length; j += 1) {
590
635
  const entityType = entityArr[j];
591
- // try to find current entityType in cache
592
636
  for (let i = 0; i < this.cache.length; i += 1) {
593
- if (this.cache[i].entityType === entityType) { // will always be found
637
+ if (this.cache[i].entityType === entityType) {
594
638
  promiseArr.push(new Promise((resolve, reject) => {
595
639
  makeIAPCall(this.propertiesMap.get(entityType).populate, this.requestHandler, (cacheData, error) => {
596
- // error message if applicable
640
+ // Error handling
597
641
  let errorMsg = null;
598
642
  if (error) {
599
643
  errorMsg = `${origin}: ${entityType} failed with error ${error.IAPerror.displayString}.`;
@@ -602,17 +646,12 @@ class CacheHandler {
602
646
  } else if (cacheData.length === 0) {
603
647
  errorMsg = `${origin}: ${entityType} failed. Nothing found.`;
604
648
  }
605
- // handle error
606
- if (errorMsg !== null) {
607
- /**
608
- * removed unnecessary check if cache[i].list is null here
609
- * setting null var to null again is fine and shortens critical section
610
- * */
611
649
 
650
+ if (errorMsg !== null) {
612
651
  if (this.propertiesMap.get(entityType).flushOnFail) {
613
652
  lock.acquire(this.cache[i].lockKey, (done) => {
614
653
  this.cache[i].list = null;
615
- done(`${errorMsg} Flushed.`);
654
+ done(`${errorMsg} Cache flushed.`);
616
655
  }, (ret) => {
617
656
  log.error(ret);
618
657
  });
@@ -620,24 +659,22 @@ class CacheHandler {
620
659
  log.error(`${errorMsg} Keeping old data.`);
621
660
  }
622
661
 
623
- // bad path
624
662
  if (error && error.icode === 'AD.301') {
625
663
  return reject(error);
626
664
  }
627
665
  return resolve('error');
628
666
  }
629
- // sort cache data, default true
667
+
668
+ // Sort and update cache
630
669
  if (this.cache[i].sort) {
631
670
  cacheData.sort(compareByName);
632
671
  }
633
-
634
- // no error, edit cache
635
672
  lock.acquire(this.cache[i].lockKey, (done) => {
636
- if (this.enabled) { // in case properties changes during iap call
673
+ if (this.enabled) {
637
674
  this.cache[i].list = cacheData;
638
- done(`${entityType}: cache updated.`);
675
+ done(`${origin}: ${entityType} cache updated successfully.`);
639
676
  } else {
640
- done('Populate cancelled due to disabled cache!');
677
+ done(`${origin}: Populate cancelled due to disabled cache.`);
641
678
  }
642
679
  }, (ret) => {
643
680
  log.info(ret);
@@ -649,6 +686,8 @@ class CacheHandler {
649
686
  }
650
687
  }
651
688
  }
689
+
690
+ // Resolve all promises
652
691
  const arr = await Promise.allSettled(promiseArr);
653
692
  return new Promise((resolve, reject) => {
654
693
  const valueArray = [];
@@ -661,7 +700,7 @@ class CacheHandler {
661
700
  resolve(valueArray);
662
701
  });
663
702
  } catch (e) {
664
- // re-throw any exception
703
+ log.error(`${origin}: An exception occurred during cache population - ${e.message}`);
665
704
  throw new Error(e);
666
705
  }
667
706
  }
@@ -684,47 +723,56 @@ class CacheHandler {
684
723
  log.trace(origin);
685
724
 
686
725
  if (!this.enabled) {
687
- log.warn(`${origin}: Cache is not enabled!`);
726
+ log.info(`${origin}: Cache is not enabled!`);
688
727
  return callback(null, 'Cache is not enabled.');
689
728
  }
690
729
 
691
730
  if (typeof entityType !== 'string') {
692
- log.error(`${entityType} is not of type String`);
731
+ log.error(`${origin}: Invalid entityType - ${entityType} is not of type String.`);
693
732
  return callback(null, `${entityType} is not of type String`);
694
733
  }
695
734
 
696
735
  try {
697
736
  const options = validateOptions(opts); // may throw error
698
- // go through the cache to find the entity we care about
737
+
738
+ log.debug(`${origin}: Searching cache for entityType: ${entityType}.`);
739
+ // Search for the specified entityType in the cache
699
740
  for (let i = 0; i < this.cache.length; i += 1) {
700
- // check if entity type we care about
701
741
  if (this.cache[i].entityType === entityType) {
702
- // Lock the cache for the entity so we can take what is in the cache
703
- // Lock and instant unlock as wait until lock is free
742
+ log.info(`${origin}: Found cache entry for entityType: ${entityType}.`);
743
+
744
+ // Lock the cache entry for safe access
704
745
  return lock.acquire(this.cache[i].lockKey, (done) => {
705
- // return the entity's list and free the lock
746
+ log.debug(`${origin}: Retrieved cache list for entityType: ${entityType}.`);
706
747
  done(this.cache[i].list);
707
748
  }, (ret) => {
708
- // last iap call failed and flushed, attempt new iap call
709
749
  if (!ret) {
710
- // this returns a promise but below we return a callback...
750
+ log.warn(`${origin}: Last IAP call failed and flushed cache for ${entityType}. Attempting to repopulate.`);
751
+
752
+ // Repopulate cache and retry retrieval
711
753
  return this.populateCache(entityType).then((result) => {
712
754
  if (result && result[0] === 'success') {
755
+ log.info(`${origin}: Repopulation succeeded for ${entityType}. Retrieving updated entries.`);
713
756
  return retrieveCacheEntriesHelper(this.cache, entityType, options, callback);
714
757
  }
715
- return callback(null, `Retrieve call for ${entityType} failed, and populate re-attempt failed`);
758
+ log.error(`${origin}: Repopulation failed for ${entityType}.`);
759
+ return callback(null, `Retrieve call for ${entityType} failed, and populate re-attempt failed.`);
760
+ }).catch((err) => {
761
+ log.error(`${origin}: Error during repopulation for ${entityType} - ${err.message}`);
762
+ return callback(null, `Retrieve call for ${entityType} failed due to an error during repopulation.`);
716
763
  });
717
764
  }
718
765
 
719
- // normal retrieve
766
+ log.debug(`${origin}: Retrieved entries successfully for entityType: ${entityType}.`);
720
767
  return retrieveCacheEntriesHelper(this.cache, entityType, options, callback);
721
768
  });
722
769
  }
723
770
  }
724
- log.error(`${origin}: Failed to find ${entityType} in retrieve!`);
771
+
772
+ log.error(`${origin}: Cache entry not found for entityType: ${entityType}.`);
725
773
  return callback(null, `Retrieve call for ${entityType} failed.`);
726
774
  } catch (e) {
727
- // re-throw any exception
775
+ log.error(`${origin}: Exception occurred during retrieval - ${e.message}`);
728
776
  throw new Error(e);
729
777
  }
730
778
  }
@@ -742,68 +790,72 @@ class CacheHandler {
742
790
  isEntityCached(entityType, entityNames, callback) {
743
791
  const origin = `${id}-cacheHandler-isEntityCached`;
744
792
  log.trace(origin);
745
- // Possibly supporting checking if entityType is cache? (set entityId = null)
793
+
746
794
  if (!this.enabled) {
747
- log.warn(`${origin}: Cache is not enabled!`);
795
+ log.info(`${origin}: Cache is not enabled!`);
748
796
  return callback(null, 'Cache is not enabled!');
749
797
  }
750
798
 
751
- let names = entityNames;
752
- if (!Array.isArray(entityNames)) {
753
- names = [entityNames];
754
- }
799
+ const names = Array.isArray(entityNames) ? entityNames : [entityNames];
755
800
 
756
801
  try {
802
+ log.debug(`${origin}: Checking cache for entityType: ${entityType}, entityNames: ${names}.`);
803
+
757
804
  for (let i = 0; i < this.cache.length; i += 1) {
758
805
  if (this.cache[i].entityType === entityType) {
806
+ log.info(`${origin}: Cache entry found for entityType: ${entityType}.`);
807
+
759
808
  const returnVals = [];
809
+
810
+ // Lock the cache entry to safely access the list
760
811
  return lock.acquire(this.cache[i].lockKey, (done) => {
812
+ log.debug(`${origin}: Acquired lock for cache entry of entityType: ${entityType}.`);
761
813
  done(this.cache[i].list);
762
814
  }, (ret) => {
763
- // null list means previously flushed or failed called
764
815
  if (!ret) {
765
- log.info(`Did not find ${entityType}, attempting populate in isEntityCached`);
766
- return this.populateCache(entityType).then((result) => { // populate will re-acquire lock
816
+ log.warn(`${origin}: Cache list is null or empty for ${entityType}. Attempting to repopulate.`);
817
+
818
+ return this.populateCache(entityType).then((result) => {
767
819
  if (result && result[0] === 'success') {
768
- // re-acquire lock to read list
769
- lock.acquire(this.cache[i].lockKey, (done) => {
820
+ log.info(`${origin}: Cache repopulation succeeded for ${entityType}. Rechecking cache.`);
821
+
822
+ // Reacquire lock to access the updated cache list
823
+ return lock.acquire(this.cache[i].lockKey, (done) => {
770
824
  names.forEach((name) => {
771
- for (let j = 0; j < this.cache[i].list.length; j += 1) {
772
- if (this.cache[i].list[j].name === name) {
773
- returnVals.push('found');
774
- return; // forEach
775
- }
776
- }
777
- returnVals.push('notfound');
825
+ const isFound = this.cache[i].list.some((item) => item.name === name);
826
+ returnVals.push(isFound ? 'found' : 'notfound');
778
827
  });
779
828
  done(returnVals);
780
829
  }, (retVals) => {
781
- log.info(retVals);
830
+ log.debug(`${origin}: Final cache check results: ${retVals}`);
782
831
  return callback(retVals);
783
832
  });
784
833
  }
834
+
835
+ log.error(`${origin}: Cache repopulation failed for ${entityType}.`);
785
836
  return callback(null, `isEntityCached call for ${entityType} failed.`);
837
+ }).catch((err) => {
838
+ log.error(`${origin}: Error during cache repopulation for ${entityType} - ${err.message}`);
839
+ return callback(null, `isEntityCached call for ${entityType} failed due to repopulation error.`);
786
840
  });
787
841
  }
788
842
 
843
+ log.debug(`${origin}: Processing cached list for entityType: ${entityType}.`);
789
844
  names.forEach((curName) => {
790
- for (let j = 0; j < ret.length; j += 1) {
791
- if (ret[j].name === curName) {
792
- returnVals.push('found');
793
- return; // continue the forEach
794
- }
795
- }
796
- returnVals.push('notfound');
845
+ const isFound = ret.some((item) => item.name === curName);
846
+ returnVals.push(isFound ? 'found' : 'notfound');
797
847
  });
798
- log.info(returnVals);
848
+
849
+ log.debug(`${origin}: Cache check results: ${returnVals}`);
799
850
  return callback(returnVals);
800
851
  }); // end of lock acquire
801
852
  }
802
853
  }
803
- log.error(`${entityType} not found in cache.`);
854
+
855
+ log.error(`${origin}: No cache entry found for entityType: ${entityType}.`);
804
856
  return callback(false);
805
857
  } catch (e) {
806
- log.error(e);
858
+ log.error(`${origin}: Exception occurred during cache check - ${e.message}`);
807
859
  return callback(false);
808
860
  }
809
861
  }
@@ -817,14 +869,16 @@ class CacheHandler {
817
869
  */
818
870
  isEntityTypeToBeCached(entityType, callback) {
819
871
  const origin = `${id}-cacheHandler-isEntityTypeToBeCached`;
820
- log.trace(origin);
872
+ log.trace(`${origin}: Checking if entityType should be cached.`);
821
873
 
822
874
  if (!this.enabled) {
823
- log.error('Cache is not enabled!');
875
+ log.info(`${origin}: Cache is not enabled.`);
824
876
  return callback(null, 'Cache is not enabled!');
825
877
  }
826
878
 
827
- return callback(this.propertiesMap.has(entityType));
879
+ const isCached = this.propertiesMap.has(entityType);
880
+ log.debug(`${origin}: entityType "${entityType}" is ${isCached ? '' : 'not '}to be cached.`);
881
+ return callback(isCached);
828
882
  }
829
883
 
830
884
  /**
@@ -836,28 +890,38 @@ class CacheHandler {
836
890
  */
837
891
  isTaskCached(entityType, task) {
838
892
  const origin = `${id}-cacheHandler-isTaskCached`;
839
- log.trace(origin);
893
+ log.trace(`${origin}: Checking if task "${task}" is cached under entityType "${entityType}".`);
840
894
 
841
- // do not bother with callbacks here
842
- if (!this.enabled || !this.propertiesMap.has(entityType)) {
895
+ // If cache is disabled or the entityType is not tracked, return false early
896
+ if (!this.enabled) {
897
+ log.info(`${origin}: Cache is not enabled.`);
843
898
  return false;
844
899
  }
845
900
 
846
- // find entity type
847
- for (let i = 0; i < this.props.cache.entities.length; i += 1) {
848
- if (this.props.cache.entities[i].entityType === entityType) {
849
- // check if contains task
850
- for (let c = 0; c < this.props.cache.entities[i].cachedTasks.length; c += 1) {
851
- if (this.props.cache.entity[i].cachedTasks[c].name === task) {
852
- return true;
853
- }
854
- }
855
- // does not have task under that entityType
856
- return false;
857
- }
901
+ if (!this.propertiesMap.has(entityType)) {
902
+ log.warn(`${origin}: entityType "${entityType}" is not configured in propertiesMap.`);
903
+ return false;
904
+ }
905
+
906
+ const cachedEntity = this.props.cache.entities.find(
907
+ (entity) => entity.entityType === entityType
908
+ );
909
+
910
+ if (!cachedEntity) {
911
+ log.error(`${origin}: entityType "${entityType}" not found in cache.`);
912
+ return false;
858
913
  }
859
- // entityType not cached, should never reach here
860
- log.error(`${origin}: EntityType not found in cache, should never reach here.`);
914
+
915
+ const isTaskFound = cachedEntity.cachedTasks.some(
916
+ (cachedTask) => cachedTask.name === task
917
+ );
918
+
919
+ if (isTaskFound) {
920
+ log.debug(`${origin}: Task "${task}" is cached under entityType "${entityType}".`);
921
+ return true;
922
+ }
923
+
924
+ log.debug(`${origin}: Task "${task}" is not cached under entityType "${entityType}".`);
861
925
  return false;
862
926
  }
863
927
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itentialopensource/adapter-utils",
3
- "version": "5.10.6",
3
+ "version": "5.10.7",
4
4
  "description": "Itential Adapter Utility Libraries",
5
5
  "scripts": {
6
6
  "postinstall": "node utils/setup.js",