@utaba/deep-memory-storage-cosmosdb 0.12.0 → 0.12.1

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.cjs CHANGED
@@ -1127,12 +1127,14 @@ function isInTimeRange(timestamp, timeRange) {
1127
1127
 
1128
1128
  // src/queries/adaptive-import.ts
1129
1129
  var import_deep_memory5 = require("@utaba/deep-memory");
1130
- var DEFAULT_MIN = 2;
1130
+ var DEFAULT_MIN = 1;
1131
1131
  var DEFAULT_START = 5;
1132
1132
  var DEFAULT_MAX = 32;
1133
1133
  var DEFAULT_INCREASE_AFTER = 50;
1134
1134
  var DEFAULT_COOLDOWN_MS = 1e3;
1135
1135
  var DEFAULT_MAX_CONSECUTIVE_THROTTLES_AT_MIN = 10;
1136
+ var DEFAULT_THROTTLE_CEILING_MULTIPLIER = 3;
1137
+ var NO_SOFT_CEILING = Number.POSITIVE_INFINITY;
1136
1138
  function resolveOptions(opts) {
1137
1139
  const min = Math.max(1, opts?.min ?? DEFAULT_MIN);
1138
1140
  const max = Math.max(min, opts?.max ?? DEFAULT_MAX);
@@ -1143,6 +1145,10 @@ function resolveOptions(opts) {
1143
1145
  1,
1144
1146
  opts?.maxConsecutiveThrottlesAtMin ?? DEFAULT_MAX_CONSECUTIVE_THROTTLES_AT_MIN
1145
1147
  );
1148
+ const throttleCeilingMultiplier = Math.max(
1149
+ 1,
1150
+ opts?.throttleCeilingMultiplier ?? DEFAULT_THROTTLE_CEILING_MULTIPLIER
1151
+ );
1146
1152
  return {
1147
1153
  min,
1148
1154
  start,
@@ -1150,9 +1156,20 @@ function resolveOptions(opts) {
1150
1156
  increaseAfter,
1151
1157
  cooldownMs,
1152
1158
  maxConsecutiveThrottlesAtMin,
1159
+ throttleCeilingMultiplier,
1153
1160
  onAdjust: opts?.onAdjust
1154
1161
  };
1155
1162
  }
1163
+ function resolveController(options, handle) {
1164
+ if (!handle) {
1165
+ return new AdaptiveConcurrencyController(options);
1166
+ }
1167
+ const cosmosHandle = handle;
1168
+ if (!cosmosHandle.controller) {
1169
+ cosmosHandle.controller = new AdaptiveConcurrencyController(options);
1170
+ }
1171
+ return cosmosHandle.controller;
1172
+ }
1156
1173
  var AdaptiveConcurrencyController = class {
1157
1174
  opts;
1158
1175
  current;
@@ -1162,6 +1179,15 @@ var AdaptiveConcurrencyController = class {
1162
1179
  throttled = 0;
1163
1180
  startEmitted = false;
1164
1181
  consecutiveThrottlesAtMin = 0;
1182
+ /**
1183
+ * Highest concurrency at which a throttle has been observed and the
1184
+ * controller actually halved (i.e. concrete evidence the cluster could not
1185
+ * sustain that level). Re-approaching this level on subsequent ramp-ups
1186
+ * requires `increaseAfter * throttleCeilingMultiplier` consecutive successes
1187
+ * instead of just `increaseAfter`. Cleared once we've successfully held the
1188
+ * level without further throttling — see noteSuccess.
1189
+ */
1190
+ softCeiling = NO_SOFT_CEILING;
1165
1191
  constructor(opts) {
1166
1192
  this.opts = resolveOptions(opts);
1167
1193
  this.current = this.opts.start;
@@ -1203,10 +1229,16 @@ var AdaptiveConcurrencyController = class {
1203
1229
  this.completed++;
1204
1230
  this.streak++;
1205
1231
  this.consecutiveThrottlesAtMin = 0;
1206
- if (this.streak >= this.opts.increaseAfter && this.current < this.opts.max) {
1232
+ if (this.current >= this.opts.max) return;
1233
+ const target = this.current + 1;
1234
+ const needed = target >= this.softCeiling ? this.opts.increaseAfter * this.opts.throttleCeilingMultiplier : this.opts.increaseAfter;
1235
+ if (this.streak >= needed) {
1207
1236
  const previous = this.current;
1208
- this.current = Math.min(this.opts.max, this.current + 1);
1237
+ this.current = Math.min(this.opts.max, target);
1209
1238
  this.streak = 0;
1239
+ if (this.current >= this.softCeiling) {
1240
+ this.softCeiling = NO_SOFT_CEILING;
1241
+ }
1210
1242
  this.notify("ramp-up", previous);
1211
1243
  }
1212
1244
  }
@@ -1220,6 +1252,7 @@ var AdaptiveConcurrencyController = class {
1220
1252
  this.cooldownUntil = now + this.opts.cooldownMs;
1221
1253
  if (next !== previous) {
1222
1254
  this.current = next;
1255
+ this.softCeiling = previous;
1223
1256
  this.notify("throttle", previous);
1224
1257
  }
1225
1258
  if (this.current === this.opts.min) {
@@ -1228,6 +1261,15 @@ var AdaptiveConcurrencyController = class {
1228
1261
  this.consecutiveThrottlesAtMin = 0;
1229
1262
  }
1230
1263
  }
1264
+ /**
1265
+ * Current soft ceiling — the highest concurrency at which a throttle was
1266
+ * observed and the controller halved. {@link Number.POSITIVE_INFINITY} when
1267
+ * no ceiling is in effect. Re-approaching this level requires
1268
+ * `increaseAfter * throttleCeilingMultiplier` consecutive successes.
1269
+ */
1270
+ getSoftCeiling() {
1271
+ return this.softCeiling;
1272
+ }
1231
1273
  /** Configured circuit-breaker threshold. */
1232
1274
  getMaxConsecutiveThrottlesAtMin() {
1233
1275
  return this.opts.maxConsecutiveThrottlesAtMin;
@@ -1408,7 +1450,7 @@ async function importBulk(conn, repositoryId, data, options) {
1408
1450
  let relationshipsImported = 0;
1409
1451
  const errors = [];
1410
1452
  const skipCheck = options?.skipExistenceCheck ?? false;
1411
- const controller = new AdaptiveConcurrencyController(options?.adaptiveConcurrency);
1453
+ const controller = resolveController(options?.adaptiveConcurrency, options?.adaptiveConcurrencyHandle);
1412
1454
  for (const chunk of data) {
1413
1455
  if (chunk.entities && chunk.entities.length > 0) {
1414
1456
  const results = await runAdaptive(