@objectstack/core 12.4.0 → 12.6.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.cjs CHANGED
@@ -54,6 +54,7 @@ __export(index_exports, {
54
54
  SemanticVersionManager: () => SemanticVersionManager,
55
55
  ServiceLifecycle: () => ServiceLifecycle,
56
56
  buildPermissionsFromGrants: () => buildPermissionsFromGrants,
57
+ bulkWrite: () => bulkWrite,
57
58
  calendarPartsInTz: () => calendarPartsInTz,
58
59
  calendarPartsInTzOrUtc: () => calendarPartsInTzOrUtc,
59
60
  counterSignPayload: () => counterSignPayload,
@@ -67,6 +68,7 @@ __export(index_exports, {
67
68
  createPluginConfigValidator: () => createPluginConfigValidator,
68
69
  createPluginPermissionEnforcer: () => createPluginPermissionEnforcer,
69
70
  deepMerge: () => deepMerge,
71
+ defaultIsTransientError: () => defaultIsTransientError,
70
72
  evaluateAuthGate: () => evaluateAuthGate,
71
73
  extractApiKey: () => extractApiKey,
72
74
  generateApiKey: () => generateApiKey,
@@ -90,7 +92,8 @@ __export(index_exports, {
90
92
  verifyPlatformSignature: () => verifyPlatformSignature,
91
93
  verifyPluginArtifact: () => verifyPluginArtifact,
92
94
  verifyPublisherSignature: () => verifyPublisherSignature,
93
- wireAuthoredTranslationSync: () => wireAuthoredTranslationSync
95
+ wireAuthoredTranslationSync: () => wireAuthoredTranslationSync,
96
+ withTransientRetry: () => withTransientRetry
94
97
  });
95
98
  module.exports = __toCommonJS(index_exports);
96
99
 
@@ -4463,6 +4466,87 @@ function calendarPartsInTzOrUtc(d, tz) {
4463
4466
  };
4464
4467
  }
4465
4468
 
4469
+ // src/utils/bulk-write.ts
4470
+ var DEFAULT_BATCH_SIZE = 200;
4471
+ var DEFAULT_MAX_RETRIES = 3;
4472
+ var DEFAULT_BACKOFF_BASE_MS = 200;
4473
+ var TRANSIENT_PATTERNS = [
4474
+ /fetch failed/i,
4475
+ /network/i,
4476
+ /timed?\s*out/i,
4477
+ /timeout/i,
4478
+ /socket hang ?up/i,
4479
+ /connection.*(closed|reset|refused|terminated|aborted)/i,
4480
+ /\b(502|503|504)\b/,
4481
+ /server.*unavailable/i,
4482
+ /too many connections/i
4483
+ ];
4484
+ var TRANSIENT_CODES = /^(ECONNRESET|ECONNREFUSED|ECONNABORTED|EPIPE|EAI_AGAIN|ETIMEDOUT|EHOSTUNREACH|ENETUNREACH|ENOTFOUND)$/i;
4485
+ function defaultIsTransientError(err) {
4486
+ const code = err?.code;
4487
+ if (typeof code === "string" && TRANSIENT_CODES.test(code)) return true;
4488
+ const message = err?.message;
4489
+ const text = typeof message === "string" ? message : String(err ?? "");
4490
+ return TRANSIENT_PATTERNS.some((re) => re.test(text));
4491
+ }
4492
+ var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
4493
+ async function withRetry(fn, opts) {
4494
+ let lastError;
4495
+ for (let attempt = 1; attempt <= opts.maxRetries; attempt++) {
4496
+ try {
4497
+ return await fn();
4498
+ } catch (err) {
4499
+ lastError = err;
4500
+ if (attempt >= opts.maxRetries || !opts.isTransientError(err)) throw err;
4501
+ const jitter = Math.floor(Math.random() * 50);
4502
+ await opts.sleep(opts.backoffBaseMs * 2 ** (attempt - 1) + jitter);
4503
+ }
4504
+ }
4505
+ throw lastError;
4506
+ }
4507
+ async function withTransientRetry(fn, opts = {}) {
4508
+ return withRetry(fn, {
4509
+ maxRetries: Math.max(1, opts.maxRetries ?? DEFAULT_MAX_RETRIES),
4510
+ backoffBaseMs: opts.backoffBaseMs ?? DEFAULT_BACKOFF_BASE_MS,
4511
+ isTransientError: opts.isTransientError ?? defaultIsTransientError,
4512
+ sleep: opts.sleep ?? defaultSleep
4513
+ });
4514
+ }
4515
+ async function bulkWrite(rows, opts) {
4516
+ const batchSize = Math.max(1, opts.batchSize ?? DEFAULT_BATCH_SIZE);
4517
+ const retryOpts = {
4518
+ maxRetries: Math.max(1, opts.maxRetries ?? DEFAULT_MAX_RETRIES),
4519
+ backoffBaseMs: opts.backoffBaseMs ?? DEFAULT_BACKOFF_BASE_MS,
4520
+ isTransientError: opts.isTransientError ?? defaultIsTransientError,
4521
+ sleep: opts.sleep ?? defaultSleep
4522
+ };
4523
+ const results = new Array(rows.length);
4524
+ for (let start = 0; start < rows.length; start += batchSize) {
4525
+ const batch = rows.slice(start, start + batchSize);
4526
+ try {
4527
+ const records = await withRetry(() => opts.writeBatch(batch), retryOpts);
4528
+ for (let i = 0; i < batch.length; i++) {
4529
+ results[start + i] = { index: start + i, ok: true, record: records[i] };
4530
+ }
4531
+ } catch (batchErr) {
4532
+ if (batch.length === 1) {
4533
+ results[start] = { index: start, ok: false, error: batchErr };
4534
+ continue;
4535
+ }
4536
+ for (let i = 0; i < batch.length; i++) {
4537
+ const idx = start + i;
4538
+ try {
4539
+ const record = await withRetry(() => opts.writeOne(batch[i]), retryOpts);
4540
+ results[idx] = { index: idx, ok: true, record };
4541
+ } catch (err) {
4542
+ results[idx] = { index: idx, ok: false, error: err };
4543
+ }
4544
+ }
4545
+ }
4546
+ }
4547
+ return results;
4548
+ }
4549
+
4466
4550
  // src/health-monitor.ts
4467
4551
  var PluginHealthMonitor = class {
4468
4552
  constructor(logger) {
@@ -5402,6 +5486,7 @@ var NamespaceResolver = class {
5402
5486
  SemanticVersionManager,
5403
5487
  ServiceLifecycle,
5404
5488
  buildPermissionsFromGrants,
5489
+ bulkWrite,
5405
5490
  calendarPartsInTz,
5406
5491
  calendarPartsInTzOrUtc,
5407
5492
  counterSignPayload,
@@ -5415,6 +5500,7 @@ var NamespaceResolver = class {
5415
5500
  createPluginConfigValidator,
5416
5501
  createPluginPermissionEnforcer,
5417
5502
  deepMerge,
5503
+ defaultIsTransientError,
5418
5504
  evaluateAuthGate,
5419
5505
  extractApiKey,
5420
5506
  generateApiKey,
@@ -5438,6 +5524,7 @@ var NamespaceResolver = class {
5438
5524
  verifyPlatformSignature,
5439
5525
  verifyPluginArtifact,
5440
5526
  verifyPublisherSignature,
5441
- wireAuthoredTranslationSync
5527
+ wireAuthoredTranslationSync,
5528
+ withTransientRetry
5442
5529
  });
5443
5530
  //# sourceMappingURL=index.cjs.map