@utaba/deep-memory-storage-cosmosdb 0.9.1 → 0.10.0

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.d.cts CHANGED
@@ -22,6 +22,14 @@ interface CosmosDbProviderConfig {
22
22
  defaultTimeoutMs?: number;
23
23
  /** Whether to reject unauthorized TLS certs — set false for emulator (default: true) */
24
24
  rejectUnauthorized?: boolean;
25
+ /**
26
+ * Milliseconds to pause between batches in deleteAllContents/deleteRepository
27
+ * to pace RU consumption. Required on low-RU tiers (e.g. CosmosDB free tier at
28
+ * 1000 RU/s), where a single batch drop query can consume the entire per-second
29
+ * budget and throttle the next batch. Set to 1000+ on constrained tiers.
30
+ * Default: 0 (no pacing — suitable for autoscale and provisioned throughput).
31
+ */
32
+ deleteBatchDelayMs?: number;
25
33
  /**
26
34
  * Optional usage sink. When provided, the provider emits one
27
35
  * {@link OperationUsage} record per public method call with the aggregated
package/dist/index.d.ts CHANGED
@@ -22,6 +22,14 @@ interface CosmosDbProviderConfig {
22
22
  defaultTimeoutMs?: number;
23
23
  /** Whether to reject unauthorized TLS certs — set false for emulator (default: true) */
24
24
  rejectUnauthorized?: boolean;
25
+ /**
26
+ * Milliseconds to pause between batches in deleteAllContents/deleteRepository
27
+ * to pace RU consumption. Required on low-RU tiers (e.g. CosmosDB free tier at
28
+ * 1000 RU/s), where a single batch drop query can consume the entire per-second
29
+ * budget and throttle the next batch. Set to 1000+ on constrained tiers.
30
+ * Default: 0 (no pacing — suitable for autoscale and provisioned throughput).
31
+ */
32
+ deleteBatchDelayMs?: number;
25
33
  /**
26
34
  * Optional usage sink. When provided, the provider emits one
27
35
  * {@link OperationUsage} record per public method call with the aggregated
package/dist/index.js CHANGED
@@ -92,11 +92,24 @@ function isTransientError(err) {
92
92
  return false;
93
93
  }
94
94
  function getRetryAfterMs(err, attempt) {
95
- const retryAfter = err?.["retryAfterMs"];
96
- if (typeof retryAfter === "number" && retryAfter > 0) {
97
- return retryAfter;
98
- }
99
- return Math.min(500 * Math.pow(2, attempt), 1e4);
95
+ const exponentialMs = Math.min(500 * Math.pow(2, attempt), 1e4);
96
+ const topLevel = err?.["retryAfterMs"];
97
+ if (typeof topLevel === "number" && topLevel > 0) {
98
+ return Math.max(topLevel, exponentialMs);
99
+ }
100
+ const attrs = err?.statusAttributes;
101
+ let hintVal;
102
+ if (attrs instanceof Map) {
103
+ hintVal = attrs.get("x-ms-retry-after-ms") ?? attrs.get("x-ms-retry-after");
104
+ } else if (typeof attrs === "object" && attrs !== null) {
105
+ const record = attrs;
106
+ hintVal = record["x-ms-retry-after-ms"] ?? record["x-ms-retry-after"];
107
+ }
108
+ const hintMs = Number(hintVal);
109
+ if (Number.isFinite(hintMs) && hintMs > 0) {
110
+ return Math.max(hintMs, exponentialMs);
111
+ }
112
+ return exponentialMs;
100
113
  }
101
114
  function extractRequestCharge(resultSet) {
102
115
  const attrs = resultSet.attributes;
@@ -380,7 +393,11 @@ async function updateRepository(conn, repositoryId, updates) {
380
393
  return await getRepository(conn, repositoryId);
381
394
  }
382
395
  var DELETE_BATCH_SIZE = 500;
383
- async function deleteRepository(conn, repositoryId, onProgress) {
396
+ function sleep2(ms) {
397
+ return new Promise((resolve) => setTimeout(resolve, ms));
398
+ }
399
+ async function deleteRepository(conn, repositoryId, onProgress, options) {
400
+ const batchDelayMs = options?.batchDelayMs ?? 0;
384
401
  const entityCountResult = await conn.submit(
385
402
  "g.V().has('repositoryId', rid).has('entityType').count()",
386
403
  { rid: repositoryId }
@@ -406,6 +423,7 @@ async function deleteRepository(conn, repositoryId, onProgress) {
406
423
  relationshipsDeleted = totalRelationships - remainingCount;
407
424
  await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });
408
425
  if (remainingCount === 0) break;
426
+ if (batchDelayMs > 0) await sleep2(batchDelayMs);
409
427
  }
410
428
  while (true) {
411
429
  await conn.submit(
@@ -420,9 +438,11 @@ async function deleteRepository(conn, repositoryId, onProgress) {
420
438
  entitiesDeleted = totalEntities - remainingCount;
421
439
  await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });
422
440
  if (remainingCount === 0) break;
441
+ if (batchDelayMs > 0) await sleep2(batchDelayMs);
423
442
  }
424
443
  }
425
- async function deleteAllContents(conn, repositoryId, onProgress) {
444
+ async function deleteAllContents(conn, repositoryId, onProgress, options) {
445
+ const batchDelayMs = options?.batchDelayMs ?? 0;
426
446
  const entityCountResult = await conn.submit(
427
447
  "g.V().has('repositoryId', rid).has('entityType').count()",
428
448
  { rid: repositoryId }
@@ -448,6 +468,7 @@ async function deleteAllContents(conn, repositoryId, onProgress) {
448
468
  relationshipsDeleted = totalRelationships - remainingCount;
449
469
  await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });
450
470
  if (remainingCount === 0) break;
471
+ if (batchDelayMs > 0) await sleep2(batchDelayMs);
451
472
  }
452
473
  while (true) {
453
474
  await conn.submit(
@@ -462,6 +483,7 @@ async function deleteAllContents(conn, repositoryId, onProgress) {
462
483
  entitiesDeleted = totalEntities - remainingCount;
463
484
  await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });
464
485
  if (remainingCount === 0) break;
486
+ if (batchDelayMs > 0) await sleep2(batchDelayMs);
465
487
  }
466
488
  return { deletedEntities: totalEntities, deletedRelationships: totalRelationships };
467
489
  }
@@ -1495,18 +1517,20 @@ var CosmosDbProvider = class {
1495
1517
  }
1496
1518
  async deleteRepository(repositoryId, onProgress) {
1497
1519
  this.assertValidRepositoryId(repositoryId);
1520
+ const batchDelayMs = this.config.deleteBatchDelayMs ?? 0;
1498
1521
  return this.track(
1499
1522
  "deleteRepository",
1500
1523
  repositoryId,
1501
- () => deleteRepository(this.conn, repositoryId, onProgress)
1524
+ () => deleteRepository(this.conn, repositoryId, onProgress, { batchDelayMs })
1502
1525
  );
1503
1526
  }
1504
1527
  async deleteAllContents(repositoryId, onProgress) {
1505
1528
  this.assertValidRepositoryId(repositoryId);
1529
+ const batchDelayMs = this.config.deleteBatchDelayMs ?? 0;
1506
1530
  return this.track(
1507
1531
  "deleteAllContents",
1508
1532
  repositoryId,
1509
- () => deleteAllContents(this.conn, repositoryId, onProgress)
1533
+ () => deleteAllContents(this.conn, repositoryId, onProgress, { batchDelayMs })
1510
1534
  );
1511
1535
  }
1512
1536
  async getRepositoryStats(repositoryId) {