@itentialopensource/adapter-utils 5.10.5 → 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 +247 -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,74 +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);
518
+ } else {
519
+ log.debug(`${origin}: Cache remains disabled. No action required.`);
488
520
  }
489
- log.warn('Cache was disabled from enabled, removed cache memory.');
490
521
  return;
491
522
  }
492
523
 
493
- // check entityType was not deleted (if so flush that cache type)
524
+ log.debug(`${origin}: Checking for deleted or updated entity types.`);
494
525
  this.propertiesMap.forEach((value, key) => {
526
+ let entityExists = false;
527
+
495
528
  for (let i = 0; i < this.props.cache.entities.length; i += 1) {
496
- if (!this.props.cache.entities[i].name === key) { // currently in cache, but not props
497
- removeCacheEntry(this.cache, key);
498
- this.propertiesMap.delete(key);
499
- log.warn(`${origin}: Removed cache entity type due to change in properties.`);
500
- log.info(`Deleted props for entity type ${key} with val ${value}`);
501
- return; // continue forEach
529
+ if (this.props.cache.entities[i].name === key) {
530
+ entityExists = true;
531
+ break;
502
532
  }
503
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
+ }
504
541
  });
505
542
 
506
- // set properties map
543
+ log.debug(`${origin}: Updating and setting properties map for cache entities.`);
507
544
  this.props.cache.entities.forEach((entity) => {
508
545
  if (!this.propertiesMap.has(entity.entityType)) {
509
- // entity does not exist yet
546
+ log.debug(`${origin}: Adding new entity type '${entity.entityType}' to properties map.`);
510
547
  this.propertiesMap.set(entity.entityType, {});
511
- this.propertiesMap.get(entity.entityType).frequency = entity.frequency;
512
- this.propertiesMap.get(entity.entityType).flushOnFail = entity.flushOnFail;
513
- this.propertiesMap.get(entity.entityType).populate = entity.populate;
514
- this.propertiesMap.get(entity.entityType).limit = entity.limit;
515
- 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;
516
554
 
517
555
  const newIntervalId = setInterval(() => {
556
+ log.debug(`${origin}: Populating cache for entity type '${entity.entityType}'.`);
518
557
  this.populateCache(entity.entityType);
519
558
  }, entity.frequency * 60000);
520
559
 
521
560
  const sort = Object.prototype.hasOwnProperty.call(entity, 'sort') ? entity.sort : true; // default true
522
561
  this.cache.push(createCacheEntity(entity.entityType, null, newIntervalId, sort));
523
- this.populateCache(entity.entityType).then((result) => {
524
- if (result && result[0] === 'error') {
525
- retryPopulate(entity.entityType, this, entity.retryAttempts).then((nextResult) => {
526
- log.info(nextResult);
527
- });
528
- }
529
- }).catch((error) => {
530
- log.error('Failed populate cache!');
531
- if (error.icode === 'AD.301') {
532
- log.error(`Destroying interval, check path and call in properties for ${entity.entityType}`);
533
- clearInterval(newIntervalId);
534
- this.cache.removeCacheEntry(this.cache, entity.entityType);
535
- }
536
- });
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
+ });
537
580
  } else {
538
- // entity props frequency updated
539
- 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}'.`);
540
586
  changeUpdateFrequency(this.cache, entity.entityType, entity.frequency, this);
541
587
  }
542
588
 
543
- this.propertiesMap.get(entity.entityType).frequency = entity.frequency;
544
- this.propertiesMap.get(entity.entityType).flushOnFail = entity.flushOnFail;
545
- this.propertiesMap.get(entity.entityType).populate = entity.populate;
546
- this.propertiesMap.get(entity.entityType).limit = entity.limit;
547
- 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;
548
594
  }
549
595
  });
550
596
  }
@@ -561,37 +607,37 @@ class CacheHandler {
561
607
  log.trace(origin);
562
608
 
563
609
  if (!this.enabled) {
610
+ log.info(`${origin}: Cache is not enabled. Populate operation aborted.`);
564
611
  return Promise.reject(new Error('Cache is not enabled!'));
565
612
  }
566
613
 
567
- log.info('Populating cache.');
614
+ log.info(`${origin}: Starting cache population.`);
568
615
 
569
- // support string and array input
616
+ // Support string and array input
570
617
  let entityArr = entities;
571
618
  if (!Array.isArray(entities)) {
572
619
  entityArr = [entities];
573
620
  }
574
621
 
575
- // need all properties to make iap call
622
+ // Ensure all entities are tracked
576
623
  for (let i = 0; i < entityArr.length; i += 1) {
577
624
  const entityType = entityArr[i];
578
625
  if (!this.propertiesMap.has(entityType)) {
579
- log.error(`${entityType} is an untracked entity type! Check properties.`);
626
+ log.error(`${origin}: ${entityType} is an untracked entity type! Check properties.`);
580
627
  return Promise.reject(new Error(`${entityType} is an untracked entity type! Check properties.`));
581
628
  }
582
629
  }
583
630
 
584
631
  try {
585
632
  const promiseArr = [];
586
- // for each entityType need to populate
633
+ // Populate each entity type
587
634
  for (let j = 0; j < entityArr.length; j += 1) {
588
635
  const entityType = entityArr[j];
589
- // try to find current entityType in cache
590
636
  for (let i = 0; i < this.cache.length; i += 1) {
591
- if (this.cache[i].entityType === entityType) { // will always be found
637
+ if (this.cache[i].entityType === entityType) {
592
638
  promiseArr.push(new Promise((resolve, reject) => {
593
639
  makeIAPCall(this.propertiesMap.get(entityType).populate, this.requestHandler, (cacheData, error) => {
594
- // error message if applicable
640
+ // Error handling
595
641
  let errorMsg = null;
596
642
  if (error) {
597
643
  errorMsg = `${origin}: ${entityType} failed with error ${error.IAPerror.displayString}.`;
@@ -600,17 +646,12 @@ class CacheHandler {
600
646
  } else if (cacheData.length === 0) {
601
647
  errorMsg = `${origin}: ${entityType} failed. Nothing found.`;
602
648
  }
603
- // handle error
604
- if (errorMsg !== null) {
605
- /**
606
- * removed unnecessary check if cache[i].list is null here
607
- * setting null var to null again is fine and shortens critical section
608
- * */
609
649
 
650
+ if (errorMsg !== null) {
610
651
  if (this.propertiesMap.get(entityType).flushOnFail) {
611
652
  lock.acquire(this.cache[i].lockKey, (done) => {
612
653
  this.cache[i].list = null;
613
- done(`${errorMsg} Flushed.`);
654
+ done(`${errorMsg} Cache flushed.`);
614
655
  }, (ret) => {
615
656
  log.error(ret);
616
657
  });
@@ -618,24 +659,22 @@ class CacheHandler {
618
659
  log.error(`${errorMsg} Keeping old data.`);
619
660
  }
620
661
 
621
- // bad path
622
662
  if (error && error.icode === 'AD.301') {
623
663
  return reject(error);
624
664
  }
625
665
  return resolve('error');
626
666
  }
627
- // sort cache data, default true
667
+
668
+ // Sort and update cache
628
669
  if (this.cache[i].sort) {
629
670
  cacheData.sort(compareByName);
630
671
  }
631
-
632
- // no error, edit cache
633
672
  lock.acquire(this.cache[i].lockKey, (done) => {
634
- if (this.enabled) { // in case properties changes during iap call
673
+ if (this.enabled) {
635
674
  this.cache[i].list = cacheData;
636
- done(`${entityType}: cache updated.`);
675
+ done(`${origin}: ${entityType} cache updated successfully.`);
637
676
  } else {
638
- done('Populate cancelled due to disabled cache!');
677
+ done(`${origin}: Populate cancelled due to disabled cache.`);
639
678
  }
640
679
  }, (ret) => {
641
680
  log.info(ret);
@@ -647,6 +686,8 @@ class CacheHandler {
647
686
  }
648
687
  }
649
688
  }
689
+
690
+ // Resolve all promises
650
691
  const arr = await Promise.allSettled(promiseArr);
651
692
  return new Promise((resolve, reject) => {
652
693
  const valueArray = [];
@@ -659,7 +700,7 @@ class CacheHandler {
659
700
  resolve(valueArray);
660
701
  });
661
702
  } catch (e) {
662
- // re-throw any exception
703
+ log.error(`${origin}: An exception occurred during cache population - ${e.message}`);
663
704
  throw new Error(e);
664
705
  }
665
706
  }
@@ -682,47 +723,56 @@ class CacheHandler {
682
723
  log.trace(origin);
683
724
 
684
725
  if (!this.enabled) {
685
- log.warn(`${origin}: Cache is not enabled!`);
726
+ log.info(`${origin}: Cache is not enabled!`);
686
727
  return callback(null, 'Cache is not enabled.');
687
728
  }
688
729
 
689
730
  if (typeof entityType !== 'string') {
690
- log.error(`${entityType} is not of type String`);
731
+ log.error(`${origin}: Invalid entityType - ${entityType} is not of type String.`);
691
732
  return callback(null, `${entityType} is not of type String`);
692
733
  }
693
734
 
694
735
  try {
695
736
  const options = validateOptions(opts); // may throw error
696
- // 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
697
740
  for (let i = 0; i < this.cache.length; i += 1) {
698
- // check if entity type we care about
699
741
  if (this.cache[i].entityType === entityType) {
700
- // Lock the cache for the entity so we can take what is in the cache
701
- // 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
702
745
  return lock.acquire(this.cache[i].lockKey, (done) => {
703
- // return the entity's list and free the lock
746
+ log.debug(`${origin}: Retrieved cache list for entityType: ${entityType}.`);
704
747
  done(this.cache[i].list);
705
748
  }, (ret) => {
706
- // last iap call failed and flushed, attempt new iap call
707
749
  if (!ret) {
708
- // 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
709
753
  return this.populateCache(entityType).then((result) => {
710
754
  if (result && result[0] === 'success') {
755
+ log.info(`${origin}: Repopulation succeeded for ${entityType}. Retrieving updated entries.`);
711
756
  return retrieveCacheEntriesHelper(this.cache, entityType, options, callback);
712
757
  }
713
- 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.`);
714
763
  });
715
764
  }
716
765
 
717
- // normal retrieve
766
+ log.debug(`${origin}: Retrieved entries successfully for entityType: ${entityType}.`);
718
767
  return retrieveCacheEntriesHelper(this.cache, entityType, options, callback);
719
768
  });
720
769
  }
721
770
  }
722
- log.error(`${origin}: Failed to find ${entityType} in retrieve!`);
771
+
772
+ log.error(`${origin}: Cache entry not found for entityType: ${entityType}.`);
723
773
  return callback(null, `Retrieve call for ${entityType} failed.`);
724
774
  } catch (e) {
725
- // re-throw any exception
775
+ log.error(`${origin}: Exception occurred during retrieval - ${e.message}`);
726
776
  throw new Error(e);
727
777
  }
728
778
  }
@@ -740,68 +790,72 @@ class CacheHandler {
740
790
  isEntityCached(entityType, entityNames, callback) {
741
791
  const origin = `${id}-cacheHandler-isEntityCached`;
742
792
  log.trace(origin);
743
- // Possibly supporting checking if entityType is cache? (set entityId = null)
793
+
744
794
  if (!this.enabled) {
745
- log.warn(`${origin}: Cache is not enabled!`);
795
+ log.info(`${origin}: Cache is not enabled!`);
746
796
  return callback(null, 'Cache is not enabled!');
747
797
  }
748
798
 
749
- let names = entityNames;
750
- if (!Array.isArray(entityNames)) {
751
- names = [entityNames];
752
- }
799
+ const names = Array.isArray(entityNames) ? entityNames : [entityNames];
753
800
 
754
801
  try {
802
+ log.debug(`${origin}: Checking cache for entityType: ${entityType}, entityNames: ${names}.`);
803
+
755
804
  for (let i = 0; i < this.cache.length; i += 1) {
756
805
  if (this.cache[i].entityType === entityType) {
806
+ log.info(`${origin}: Cache entry found for entityType: ${entityType}.`);
807
+
757
808
  const returnVals = [];
809
+
810
+ // Lock the cache entry to safely access the list
758
811
  return lock.acquire(this.cache[i].lockKey, (done) => {
812
+ log.debug(`${origin}: Acquired lock for cache entry of entityType: ${entityType}.`);
759
813
  done(this.cache[i].list);
760
814
  }, (ret) => {
761
- // null list means previously flushed or failed called
762
815
  if (!ret) {
763
- log.info(`Did not find ${entityType}, attempting populate in isEntityCached`);
764
- 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) => {
765
819
  if (result && result[0] === 'success') {
766
- // re-acquire lock to read list
767
- 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) => {
768
824
  names.forEach((name) => {
769
- for (let j = 0; j < this.cache[i].list.length; j += 1) {
770
- if (this.cache[i].list[j].name === name) {
771
- returnVals.push('found');
772
- return; // forEach
773
- }
774
- }
775
- returnVals.push('notfound');
825
+ const isFound = this.cache[i].list.some((item) => item.name === name);
826
+ returnVals.push(isFound ? 'found' : 'notfound');
776
827
  });
777
828
  done(returnVals);
778
829
  }, (retVals) => {
779
- log.info(retVals);
830
+ log.debug(`${origin}: Final cache check results: ${retVals}`);
780
831
  return callback(retVals);
781
832
  });
782
833
  }
834
+
835
+ log.error(`${origin}: Cache repopulation failed for ${entityType}.`);
783
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.`);
784
840
  });
785
841
  }
786
842
 
843
+ log.debug(`${origin}: Processing cached list for entityType: ${entityType}.`);
787
844
  names.forEach((curName) => {
788
- for (let j = 0; j < ret.length; j += 1) {
789
- if (ret[j].name === curName) {
790
- returnVals.push('found');
791
- return; // continue the forEach
792
- }
793
- }
794
- returnVals.push('notfound');
845
+ const isFound = ret.some((item) => item.name === curName);
846
+ returnVals.push(isFound ? 'found' : 'notfound');
795
847
  });
796
- log.info(returnVals);
848
+
849
+ log.debug(`${origin}: Cache check results: ${returnVals}`);
797
850
  return callback(returnVals);
798
851
  }); // end of lock acquire
799
852
  }
800
853
  }
801
- log.error(`${entityType} not found in cache.`);
854
+
855
+ log.error(`${origin}: No cache entry found for entityType: ${entityType}.`);
802
856
  return callback(false);
803
857
  } catch (e) {
804
- log.error(e);
858
+ log.error(`${origin}: Exception occurred during cache check - ${e.message}`);
805
859
  return callback(false);
806
860
  }
807
861
  }
@@ -815,14 +869,16 @@ class CacheHandler {
815
869
  */
816
870
  isEntityTypeToBeCached(entityType, callback) {
817
871
  const origin = `${id}-cacheHandler-isEntityTypeToBeCached`;
818
- log.trace(origin);
872
+ log.trace(`${origin}: Checking if entityType should be cached.`);
819
873
 
820
874
  if (!this.enabled) {
821
- log.error('Cache is not enabled!');
875
+ log.info(`${origin}: Cache is not enabled.`);
822
876
  return callback(null, 'Cache is not enabled!');
823
877
  }
824
878
 
825
- 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);
826
882
  }
827
883
 
828
884
  /**
@@ -834,28 +890,38 @@ class CacheHandler {
834
890
  */
835
891
  isTaskCached(entityType, task) {
836
892
  const origin = `${id}-cacheHandler-isTaskCached`;
837
- log.trace(origin);
893
+ log.trace(`${origin}: Checking if task "${task}" is cached under entityType "${entityType}".`);
838
894
 
839
- // do not bother with callbacks here
840
- 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.`);
841
898
  return false;
842
899
  }
843
900
 
844
- // find entity type
845
- for (let i = 0; i < this.props.cache.entities.length; i += 1) {
846
- if (this.props.cache.entities[i].entityType === entityType) {
847
- // check if contains task
848
- for (let c = 0; c < this.props.cache.entities[i].cachedTasks.length; c += 1) {
849
- if (this.props.cache.entity[i].cachedTasks[c].name === task) {
850
- return true;
851
- }
852
- }
853
- // does not have task under that entityType
854
- return false;
855
- }
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;
856
913
  }
857
- // entityType not cached, should never reach here
858
- 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}".`);
859
925
  return false;
860
926
  }
861
927
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itentialopensource/adapter-utils",
3
- "version": "5.10.5",
3
+ "version": "5.10.7",
4
4
  "description": "Itential Adapter Utility Libraries",
5
5
  "scripts": {
6
6
  "postinstall": "node utils/setup.js",