@adaptic/utils 0.0.1003 → 0.0.1004

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.mjs CHANGED
@@ -14561,17 +14561,17 @@ var hasRequiredBrowser;
14561
14561
  function requireBrowser () {
14562
14562
  if (hasRequiredBrowser) return browser.exports;
14563
14563
  hasRequiredBrowser = 1;
14564
- (function (module, exports) {
14564
+ (function (module, exports$1) {
14565
14565
  /**
14566
14566
  * This is the web browser implementation of `debug()`.
14567
14567
  */
14568
14568
 
14569
- exports.formatArgs = formatArgs;
14570
- exports.save = save;
14571
- exports.load = load;
14572
- exports.useColors = useColors;
14573
- exports.storage = localstorage();
14574
- exports.destroy = (() => {
14569
+ exports$1.formatArgs = formatArgs;
14570
+ exports$1.save = save;
14571
+ exports$1.load = load;
14572
+ exports$1.useColors = useColors;
14573
+ exports$1.storage = localstorage();
14574
+ exports$1.destroy = (() => {
14575
14575
  let warned = false;
14576
14576
 
14577
14577
  return () => {
@@ -14586,7 +14586,7 @@ function requireBrowser () {
14586
14586
  * Colors.
14587
14587
  */
14588
14588
 
14589
- exports.colors = [
14589
+ exports$1.colors = [
14590
14590
  '#0000CC',
14591
14591
  '#0000FF',
14592
14592
  '#0033CC',
@@ -14751,7 +14751,7 @@ function requireBrowser () {
14751
14751
  *
14752
14752
  * @api public
14753
14753
  */
14754
- exports.log = console.debug || console.log || (() => {});
14754
+ exports$1.log = console.debug || console.log || (() => {});
14755
14755
 
14756
14756
  /**
14757
14757
  * Save `namespaces`.
@@ -14762,9 +14762,9 @@ function requireBrowser () {
14762
14762
  function save(namespaces) {
14763
14763
  try {
14764
14764
  if (namespaces) {
14765
- exports.storage.setItem('debug', namespaces);
14765
+ exports$1.storage.setItem('debug', namespaces);
14766
14766
  } else {
14767
- exports.storage.removeItem('debug');
14767
+ exports$1.storage.removeItem('debug');
14768
14768
  }
14769
14769
  } catch (error) {
14770
14770
  // Swallow
@@ -14781,7 +14781,7 @@ function requireBrowser () {
14781
14781
  function load() {
14782
14782
  let r;
14783
14783
  try {
14784
- r = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ;
14784
+ r = exports$1.storage.getItem('debug') || exports$1.storage.getItem('DEBUG') ;
14785
14785
  } catch (error) {
14786
14786
  // Swallow
14787
14787
  // XXX (@Qix-) should we be logging these?
@@ -14817,7 +14817,7 @@ function requireBrowser () {
14817
14817
  }
14818
14818
  }
14819
14819
 
14820
- module.exports = requireCommon()(exports);
14820
+ module.exports = requireCommon()(exports$1);
14821
14821
 
14822
14822
  const {formatters} = module.exports;
14823
14823
 
@@ -15006,7 +15006,7 @@ var hasRequiredNode$1;
15006
15006
  function requireNode$1 () {
15007
15007
  if (hasRequiredNode$1) return node$1.exports;
15008
15008
  hasRequiredNode$1 = 1;
15009
- (function (module, exports) {
15009
+ (function (module, exports$1) {
15010
15010
  const tty = require$$1$1;
15011
15011
  const util = require$$1$2;
15012
15012
 
@@ -15014,13 +15014,13 @@ function requireNode$1 () {
15014
15014
  * This is the Node.js implementation of `debug()`.
15015
15015
  */
15016
15016
 
15017
- exports.init = init;
15018
- exports.log = log;
15019
- exports.formatArgs = formatArgs;
15020
- exports.save = save;
15021
- exports.load = load;
15022
- exports.useColors = useColors;
15023
- exports.destroy = util.deprecate(
15017
+ exports$1.init = init;
15018
+ exports$1.log = log;
15019
+ exports$1.formatArgs = formatArgs;
15020
+ exports$1.save = save;
15021
+ exports$1.load = load;
15022
+ exports$1.useColors = useColors;
15023
+ exports$1.destroy = util.deprecate(
15024
15024
  () => {},
15025
15025
  'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'
15026
15026
  );
@@ -15029,7 +15029,7 @@ function requireNode$1 () {
15029
15029
  * Colors.
15030
15030
  */
15031
15031
 
15032
- exports.colors = [6, 2, 3, 4, 5, 1];
15032
+ exports$1.colors = [6, 2, 3, 4, 5, 1];
15033
15033
 
15034
15034
  try {
15035
15035
  // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)
@@ -15037,7 +15037,7 @@ function requireNode$1 () {
15037
15037
  const supportsColor = requireSupportsColor();
15038
15038
 
15039
15039
  if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
15040
- exports.colors = [
15040
+ exports$1.colors = [
15041
15041
  20,
15042
15042
  21,
15043
15043
  26,
@@ -15126,7 +15126,7 @@ function requireNode$1 () {
15126
15126
  * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
15127
15127
  */
15128
15128
 
15129
- exports.inspectOpts = Object.keys(process.env).filter(key => {
15129
+ exports$1.inspectOpts = Object.keys(process.env).filter(key => {
15130
15130
  return /^debug_/i.test(key);
15131
15131
  }).reduce((obj, key) => {
15132
15132
  // Camel-case
@@ -15158,8 +15158,8 @@ function requireNode$1 () {
15158
15158
  */
15159
15159
 
15160
15160
  function useColors() {
15161
- return 'colors' in exports.inspectOpts ?
15162
- Boolean(exports.inspectOpts.colors) :
15161
+ return 'colors' in exports$1.inspectOpts ?
15162
+ Boolean(exports$1.inspectOpts.colors) :
15163
15163
  tty.isatty(process.stderr.fd);
15164
15164
  }
15165
15165
 
@@ -15185,7 +15185,7 @@ function requireNode$1 () {
15185
15185
  }
15186
15186
 
15187
15187
  function getDate() {
15188
- if (exports.inspectOpts.hideDate) {
15188
+ if (exports$1.inspectOpts.hideDate) {
15189
15189
  return '';
15190
15190
  }
15191
15191
  return new Date().toISOString() + ' ';
@@ -15196,7 +15196,7 @@ function requireNode$1 () {
15196
15196
  */
15197
15197
 
15198
15198
  function log(...args) {
15199
- return process.stderr.write(util.formatWithOptions(exports.inspectOpts, ...args) + '\n');
15199
+ return process.stderr.write(util.formatWithOptions(exports$1.inspectOpts, ...args) + '\n');
15200
15200
  }
15201
15201
 
15202
15202
  /**
@@ -15236,13 +15236,13 @@ function requireNode$1 () {
15236
15236
  function init(debug) {
15237
15237
  debug.inspectOpts = {};
15238
15238
 
15239
- const keys = Object.keys(exports.inspectOpts);
15239
+ const keys = Object.keys(exports$1.inspectOpts);
15240
15240
  for (let i = 0; i < keys.length; i++) {
15241
- debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
15241
+ debug.inspectOpts[keys[i]] = exports$1.inspectOpts[keys[i]];
15242
15242
  }
15243
15243
  }
15244
15244
 
15245
- module.exports = requireCommon()(exports);
15245
+ module.exports = requireCommon()(exports$1);
15246
15246
 
15247
15247
  const {formatters} = module.exports;
15248
15248
 
@@ -15816,7 +15816,7 @@ function requireFollowRedirects () {
15816
15816
  // Wraps the key/value object of protocols with redirect functionality
15817
15817
  function wrap(protocols) {
15818
15818
  // Default settings
15819
- var exports = {
15819
+ var exports$1 = {
15820
15820
  maxRedirects: 21,
15821
15821
  maxBodyLength: 10 * 1024 * 1024,
15822
15822
  };
@@ -15826,7 +15826,7 @@ function requireFollowRedirects () {
15826
15826
  Object.keys(protocols).forEach(function (scheme) {
15827
15827
  var protocol = scheme + ":";
15828
15828
  var nativeProtocol = nativeProtocols[protocol] = protocols[scheme];
15829
- var wrappedProtocol = exports[scheme] = Object.create(nativeProtocol);
15829
+ var wrappedProtocol = exports$1[scheme] = Object.create(nativeProtocol);
15830
15830
 
15831
15831
  // Executes a request, following redirects
15832
15832
  function request(input, options, callback) {
@@ -15849,8 +15849,8 @@ function requireFollowRedirects () {
15849
15849
 
15850
15850
  // Set defaults
15851
15851
  options = Object.assign({
15852
- maxRedirects: exports.maxRedirects,
15853
- maxBodyLength: exports.maxBodyLength,
15852
+ maxRedirects: exports$1.maxRedirects,
15853
+ maxBodyLength: exports$1.maxBodyLength,
15854
15854
  }, input, options);
15855
15855
  options.nativeProtocols = nativeProtocols;
15856
15856
  if (!isString(options.host) && !isString(options.hostname)) {
@@ -15875,7 +15875,7 @@ function requireFollowRedirects () {
15875
15875
  get: { value: get, configurable: true, enumerable: true, writable: true },
15876
15876
  });
15877
15877
  });
15878
- return exports;
15878
+ return exports$1;
15879
15879
  }
15880
15880
 
15881
15881
  function noop() { /* empty */ }
@@ -17481,7 +17481,7 @@ var hasRequiredLodash;
17481
17481
  function requireLodash () {
17482
17482
  if (hasRequiredLodash) return lodash$1.exports;
17483
17483
  hasRequiredLodash = 1;
17484
- (function (module, exports) {
17484
+ (function (module, exports$1) {
17485
17485
  (function() {
17486
17486
 
17487
17487
  /** Used as a safe reference for `undefined` in pre-ES5 environments. */
@@ -17912,7 +17912,7 @@ function requireLodash () {
17912
17912
  var root = freeGlobal || freeSelf || Function('return this')();
17913
17913
 
17914
17914
  /** Detect free variable `exports`. */
17915
- var freeExports = exports && !exports.nodeType && exports;
17915
+ var freeExports = exports$1 && !exports$1.nodeType && exports$1;
17916
17916
 
17917
17917
  /** Detect free variable `module`. */
17918
17918
  var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
@@ -35742,12 +35742,12 @@ var hasRequiredIsBuffer;
35742
35742
  function requireIsBuffer () {
35743
35743
  if (hasRequiredIsBuffer) return isBuffer.exports;
35744
35744
  hasRequiredIsBuffer = 1;
35745
- (function (module, exports) {
35745
+ (function (module, exports$1) {
35746
35746
  var root = require_root(),
35747
35747
  stubFalse = requireStubFalse();
35748
35748
 
35749
35749
  /** Detect free variable `exports`. */
35750
- var freeExports = exports && !exports.nodeType && exports;
35750
+ var freeExports = exports$1 && !exports$1.nodeType && exports$1;
35751
35751
 
35752
35752
  /** Detect free variable `module`. */
35753
35753
  var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
@@ -35967,11 +35967,11 @@ var hasRequired_nodeUtil;
35967
35967
  function require_nodeUtil () {
35968
35968
  if (hasRequired_nodeUtil) return _nodeUtil.exports;
35969
35969
  hasRequired_nodeUtil = 1;
35970
- (function (module, exports) {
35970
+ (function (module, exports$1) {
35971
35971
  var freeGlobal = require_freeGlobal();
35972
35972
 
35973
35973
  /** Detect free variable `exports`. */
35974
- var freeExports = exports && !exports.nodeType && exports;
35974
+ var freeExports = exports$1 && !exports$1.nodeType && exports$1;
35975
35975
 
35976
35976
  /** Detect free variable `module`. */
35977
35977
  var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
@@ -44893,7 +44893,7 @@ var hasRequiredSafeBuffer;
44893
44893
  function requireSafeBuffer () {
44894
44894
  if (hasRequiredSafeBuffer) return safeBuffer.exports;
44895
44895
  hasRequiredSafeBuffer = 1;
44896
- (function (module, exports) {
44896
+ (function (module, exports$1) {
44897
44897
  /* eslint-disable node/no-deprecated-api */
44898
44898
  var buffer = require$$0$5;
44899
44899
  var Buffer = buffer.Buffer;
@@ -44908,8 +44908,8 @@ function requireSafeBuffer () {
44908
44908
  module.exports = buffer;
44909
44909
  } else {
44910
44910
  // Copy properties from require('buffer')
44911
- copyProps(buffer, exports);
44912
- exports.Buffer = SafeBuffer;
44911
+ copyProps(buffer, exports$1);
44912
+ exports$1.Buffer = SafeBuffer;
44913
44913
  }
44914
44914
 
44915
44915
  function SafeBuffer (arg, encodingOrOffset, length) {
@@ -48107,22 +48107,22 @@ var hasRequiredReadable;
48107
48107
  function requireReadable () {
48108
48108
  if (hasRequiredReadable) return readable.exports;
48109
48109
  hasRequiredReadable = 1;
48110
- (function (module, exports) {
48110
+ (function (module, exports$1) {
48111
48111
  var Stream = require$$0$3;
48112
48112
  if (process.env.READABLE_STREAM === 'disable' && Stream) {
48113
48113
  module.exports = Stream.Readable;
48114
48114
  Object.assign(module.exports, Stream);
48115
48115
  module.exports.Stream = Stream;
48116
48116
  } else {
48117
- exports = module.exports = require_stream_readable();
48118
- exports.Stream = Stream || exports;
48119
- exports.Readable = exports;
48120
- exports.Writable = require_stream_writable();
48121
- exports.Duplex = require_stream_duplex();
48122
- exports.Transform = require_stream_transform();
48123
- exports.PassThrough = require_stream_passthrough();
48124
- exports.finished = requireEndOfStream();
48125
- exports.pipeline = requirePipeline();
48117
+ exports$1 = module.exports = require_stream_readable();
48118
+ exports$1.Stream = Stream || exports$1;
48119
+ exports$1.Readable = exports$1;
48120
+ exports$1.Writable = require_stream_writable();
48121
+ exports$1.Duplex = require_stream_duplex();
48122
+ exports$1.Transform = require_stream_transform();
48123
+ exports$1.PassThrough = require_stream_passthrough();
48124
+ exports$1.finished = requireEndOfStream();
48125
+ exports$1.pipeline = requirePipeline();
48126
48126
  }
48127
48127
  } (readable, readable.exports));
48128
48128
  return readable.exports;
@@ -49557,12 +49557,12 @@ var hasRequiredWebsocket;
49557
49557
  function requireWebsocket () {
49558
49558
  if (hasRequiredWebsocket) return websocket$1;
49559
49559
  hasRequiredWebsocket = 1;
49560
- (function (exports) {
49560
+ (function (exports$1) {
49561
49561
  var __importDefault = (websocket$1 && websocket$1.__importDefault) || function (mod) {
49562
49562
  return (mod && mod.__esModule) ? mod : { "default": mod };
49563
49563
  };
49564
- Object.defineProperty(exports, "__esModule", { value: true });
49565
- exports.AlpacaWebsocket = exports.ERROR = exports.CONN_ERROR = exports.EVENT = exports.STATE = void 0;
49564
+ Object.defineProperty(exports$1, "__esModule", { value: true });
49565
+ exports$1.AlpacaWebsocket = exports$1.ERROR = exports$1.CONN_ERROR = exports$1.EVENT = exports$1.STATE = void 0;
49566
49566
  const events_1 = __importDefault(require$$0$4);
49567
49567
  const ws_1 = __importDefault(requireWs());
49568
49568
  const msgpack5_1 = __importDefault(requireMsgpack5());
@@ -49576,7 +49576,7 @@ function requireWebsocket () {
49576
49576
  STATE["DISCONNECTED"] = "disconnected";
49577
49577
  STATE["WAITING_TO_CONNECT"] = "waiting to connect";
49578
49578
  STATE["WAITING_TO_RECONNECT"] = "waiting to reconnect";
49579
- })(STATE || (exports.STATE = STATE = {}));
49579
+ })(STATE || (exports$1.STATE = STATE = {}));
49580
49580
  // Client events
49581
49581
  var EVENT;
49582
49582
  (function (EVENT) {
@@ -49595,9 +49595,9 @@ function requireWebsocket () {
49595
49595
  EVENT["CORRECTIONS"] = "corrections";
49596
49596
  EVENT["ORDERBOOKS"] = "orderbooks";
49597
49597
  EVENT["NEWS"] = "news";
49598
- })(EVENT || (exports.EVENT = EVENT = {}));
49598
+ })(EVENT || (exports$1.EVENT = EVENT = {}));
49599
49599
  // Connection errors by code
49600
- exports.CONN_ERROR = new Map([
49600
+ exports$1.CONN_ERROR = new Map([
49601
49601
  [400, "invalid syntax"],
49602
49602
  [401, "not authenticated"],
49603
49603
  [402, "auth failed"],
@@ -49616,7 +49616,7 @@ function requireWebsocket () {
49616
49616
  ERROR["MISSING_SECERT_KEY"] = "missing secret key";
49617
49617
  ERROR["MISSING_API_KEY"] = "missing api key";
49618
49618
  ERROR["UNEXPECTED_MESSAGE"] = "unexpected message";
49619
- })(ERROR || (exports.ERROR = ERROR = {}));
49619
+ })(ERROR || (exports$1.ERROR = ERROR = {}));
49620
49620
  class AlpacaWebsocket extends events_1.default.EventEmitter {
49621
49621
  constructor(options) {
49622
49622
  super();
@@ -49773,7 +49773,7 @@ function requireWebsocket () {
49773
49773
  this.updateSubscriptions(data[0]);
49774
49774
  break;
49775
49775
  case "error":
49776
- this.emit(EVENT.CLIENT_ERROR, exports.CONN_ERROR.get(data[0].code));
49776
+ this.emit(EVENT.CLIENT_ERROR, exports$1.CONN_ERROR.get(data[0].code));
49777
49777
  break;
49778
49778
  default:
49779
49779
  this.dataHandler(data);
@@ -49802,7 +49802,7 @@ function requireWebsocket () {
49802
49802
  }
49803
49803
  }
49804
49804
  }
49805
- exports.AlpacaWebsocket = AlpacaWebsocket;
49805
+ exports$1.AlpacaWebsocket = AlpacaWebsocket;
49806
49806
  } (websocket$1));
49807
49807
  return websocket$1;
49808
49808
  }
@@ -50436,8 +50436,8 @@ var hasRequiredWebsockets;
50436
50436
  function requireWebsockets () {
50437
50437
  if (hasRequiredWebsockets) return websockets;
50438
50438
  hasRequiredWebsockets = 1;
50439
- (function (exports) {
50440
- Object.defineProperty(exports, "__esModule", { value: true });
50439
+ (function (exports$1) {
50440
+ Object.defineProperty(exports$1, "__esModule", { value: true });
50441
50441
  const events = require$$0$4;
50442
50442
  const WebSocket = requireWs();
50443
50443
  const entity = requireEntity();
@@ -50452,7 +50452,7 @@ function requireWebsockets () {
50452
50452
  STATE.DISCONNECTED = "disconnected";
50453
50453
  STATE.WAITING_TO_CONNECT = "waiting to connect";
50454
50454
  STATE.WAITING_TO_RECONNECT = "waiting to reconnect";
50455
- })((STATE = exports.STATE || (exports.STATE = {})));
50455
+ })((STATE = exports$1.STATE || (exports$1.STATE = {})));
50456
50456
  // Client events
50457
50457
  var EVENT;
50458
50458
  (function (EVENT) {
@@ -50466,7 +50466,7 @@ function requireWebsockets () {
50466
50466
  EVENT.STOCK_QUOTES = "stock_quotes";
50467
50467
  EVENT.STOCK_AGG_SEC = "stock_agg_sec";
50468
50468
  EVENT.STOCK_AGG_MIN = "stock_agg_min";
50469
- })((EVENT = exports.EVENT || (exports.EVENT = {})));
50469
+ })((EVENT = exports$1.EVENT || (exports$1.EVENT = {})));
50470
50470
  // Connection errors Each of these will also emit EVENT.ERROR
50471
50471
  var ERROR;
50472
50472
  (function (ERROR) {
@@ -50475,7 +50475,7 @@ function requireWebsockets () {
50475
50475
  ERROR.MISSING_API_KEY = "missing api key";
50476
50476
  ERROR.MISSING_SECRET_KEY = "missing secret key";
50477
50477
  ERROR.UNKNOWN = "unknown error";
50478
- })((ERROR = exports.ERROR || (exports.ERROR = {})));
50478
+ })((ERROR = exports$1.ERROR || (exports$1.ERROR = {})));
50479
50479
  /**
50480
50480
  * AlpacaStreamClient manages a connection to Alpaca's websocket api
50481
50481
  */
@@ -50788,7 +50788,7 @@ function requireWebsockets () {
50788
50788
  }
50789
50789
  }
50790
50790
  }
50791
- exports.AlpacaStreamClient = AlpacaStreamClient;
50791
+ exports$1.AlpacaStreamClient = AlpacaStreamClient;
50792
50792
  } (websockets));
50793
50793
  return websockets;
50794
50794
  }
@@ -51040,13 +51040,13 @@ var hasRequiredDist;
51040
51040
  function requireDist () {
51041
51041
  if (hasRequiredDist) return dist$1.exports;
51042
51042
  hasRequiredDist = 1;
51043
- (function (module, exports) {
51043
+ (function (module, exports$1) {
51044
51044
  var __importDefault = (dist && dist.__importDefault) || function (mod) {
51045
51045
  return (mod && mod.__esModule) ? mod : { "default": mod };
51046
51046
  };
51047
- Object.defineProperty(exports, "__esModule", { value: true });
51047
+ Object.defineProperty(exports$1, "__esModule", { value: true });
51048
51048
  const alpaca_trade_api_1 = __importDefault(requireAlpacaTradeApi());
51049
- exports.default = alpaca_trade_api_1.default;
51049
+ exports$1.default = alpaca_trade_api_1.default;
51050
51050
  module.exports = alpaca_trade_api_1.default;
51051
51051
  } (dist$1, dist$1.exports));
51052
51052
  return dist$1.exports;
@@ -63155,6 +63155,7 @@ class StampedeProtectedCache {
63155
63155
  coalescedRequests: 0,
63156
63156
  backgroundRefreshes: 0,
63157
63157
  refreshErrors: 0,
63158
+ loadTimeouts: 0,
63158
63159
  };
63159
63160
  constructor(options) {
63160
63161
  this.options = {
@@ -63428,6 +63429,7 @@ class StampedeProtectedCache {
63428
63429
  coalescedRequests: this.stats.coalescedRequests,
63429
63430
  backgroundRefreshes: this.stats.backgroundRefreshes,
63430
63431
  refreshErrors: this.stats.refreshErrors,
63432
+ loadTimeouts: this.stats.loadTimeouts,
63431
63433
  };
63432
63434
  }
63433
63435
  /**
@@ -63478,8 +63480,9 @@ class StampedeProtectedCache {
63478
63480
  this.options.logger.debug("Request coalesced", { key });
63479
63481
  return existingPromise;
63480
63482
  }
63481
- // Create new promise and store it
63482
- const promise = this.loadAndCache(key, loader, ttl);
63483
+ // Create new promise and store it — bounded by loadTimeoutMs so a
63484
+ // never-settling loader cannot pin the key (see loadWithTimeout).
63485
+ const promise = this.loadWithTimeout(key, loader, ttl);
63483
63486
  this.pendingRefreshes.set(key, promise);
63484
63487
  try {
63485
63488
  const result = await promise;
@@ -63490,6 +63493,51 @@ class StampedeProtectedCache {
63490
63493
  this.pendingRefreshes.delete(key);
63491
63494
  }
63492
63495
  }
63496
+ /**
63497
+ * Race {@link loadAndCache} against the configured load timeout.
63498
+ *
63499
+ * On timeout: rejects with a typed timeout error, evicts the pending
63500
+ * single-flight entry so the NEXT caller retries with a fresh loader
63501
+ * (instead of coalescing onto the hung one), and attaches a settlement
63502
+ * observer to the abandoned loader so its eventual resolution/rejection
63503
+ * is logged rather than surfacing as an unhandled rejection.
63504
+ */
63505
+ async loadWithTimeout(key, loader, ttl) {
63506
+ const timeoutMs = this.options.loadTimeoutMs ?? 30000;
63507
+ const loadPromise = this.loadAndCache(key, loader, ttl);
63508
+ let timeoutHandle;
63509
+ const timeoutPromise = new Promise((_, reject) => {
63510
+ timeoutHandle = setTimeout(() => {
63511
+ this.stats.loadTimeouts++;
63512
+ // Evict the pin so the next caller retries fresh.
63513
+ this.pendingRefreshes.delete(key);
63514
+ this.options.logger.warn("Cache loader timed out — pin evicted", {
63515
+ key,
63516
+ timeoutMs,
63517
+ });
63518
+ // Observe the abandoned loader; never let it become unhandled.
63519
+ loadPromise
63520
+ .then(() => {
63521
+ this.options.logger.warn("Abandoned cache loader eventually resolved", { key });
63522
+ })
63523
+ .catch((error) => {
63524
+ this.options.logger.warn("Abandoned cache loader eventually rejected", {
63525
+ key,
63526
+ error: error instanceof Error ? error.message : String(error),
63527
+ });
63528
+ });
63529
+ reject(new Error(`StampedeProtectedCache loader timed out after ${timeoutMs}ms for key "${key}"`));
63530
+ }, timeoutMs);
63531
+ });
63532
+ try {
63533
+ return await Promise.race([loadPromise, timeoutPromise]);
63534
+ }
63535
+ finally {
63536
+ if (timeoutHandle !== undefined) {
63537
+ clearTimeout(timeoutHandle);
63538
+ }
63539
+ }
63540
+ }
63493
63541
  /**
63494
63542
  * Load data and cache it
63495
63543
  */
@@ -63639,6 +63687,7 @@ const DEFAULT_CACHE_OPTIONS = {
63639
63687
  minJitter: 0.9, // 90%
63640
63688
  maxJitter: 1.1, // 110%
63641
63689
  enableBackgroundRefresh: true,
63690
+ loadTimeoutMs: 30000, // 30s hard loader ceiling (anti-pinning)
63642
63691
  };
63643
63692
 
63644
63693
  /**