@ductape/sdk 0.2.8 → 0.2.10

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 (43) hide show
  1. package/dist/api/services/processorApi.service.d.ts +4 -0
  2. package/dist/api/services/processorApi.service.js +13 -0
  3. package/dist/api/services/processorApi.service.js.map +1 -1
  4. package/dist/api/services/productsApi.service.d.ts +9 -0
  5. package/dist/api/services/productsApi.service.js.map +1 -1
  6. package/dist/database/databases.service.js +7 -9
  7. package/dist/database/databases.service.js.map +1 -1
  8. package/dist/features/feature-executor.js +3 -17
  9. package/dist/features/feature-executor.js.map +1 -1
  10. package/dist/index.d.ts +5 -1
  11. package/dist/index.js +41 -9
  12. package/dist/index.js.map +1 -1
  13. package/dist/logs/logs.service.d.ts +3 -0
  14. package/dist/logs/logs.service.js +25 -0
  15. package/dist/logs/logs.service.js.map +1 -1
  16. package/dist/processor/services/processor.service.d.ts +8 -0
  17. package/dist/processor/services/processor.service.js +28 -2
  18. package/dist/processor/services/processor.service.js.map +1 -1
  19. package/dist/products/services/products.service.js +2 -2
  20. package/dist/products/services/products.service.js.map +1 -1
  21. package/dist/resilience/fallback.service.d.ts +2 -4
  22. package/dist/resilience/fallback.service.js +56 -65
  23. package/dist/resilience/fallback.service.js.map +1 -1
  24. package/dist/resilience/health-status-cache.d.ts +11 -0
  25. package/dist/resilience/health-status-cache.js +46 -0
  26. package/dist/resilience/health-status-cache.js.map +1 -0
  27. package/dist/resilience/healthcheck.service.js +1 -1
  28. package/dist/resilience/healthcheck.service.js.map +1 -1
  29. package/dist/resilience/quota.service.d.ts +3 -5
  30. package/dist/resilience/quota.service.js +82 -62
  31. package/dist/resilience/quota.service.js.map +1 -1
  32. package/dist/resilience/resilience.service.js +6 -2
  33. package/dist/resilience/resilience.service.js.map +1 -1
  34. package/dist/resilience/types/index.d.ts +8 -0
  35. package/dist/runtime/resilient-write-queue.d.ts +18 -0
  36. package/dist/runtime/resilient-write-queue.js +74 -0
  37. package/dist/runtime/resilient-write-queue.js.map +1 -0
  38. package/dist/tsconfig.tsbuildinfo +1 -1
  39. package/dist/types/index.types.d.ts +4 -0
  40. package/dist/types/index.types.js.map +1 -1
  41. package/dist/types/productsBuilder.types.d.ts +2 -0
  42. package/dist/types/productsBuilder.types.js.map +1 -1
  43. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -67,6 +67,7 @@ const healthcheck_cache_key_1 = require("./resilience/healthcheck-cache-key");
67
67
  const enums_1 = require("./types/enums");
68
68
  const productsApi_service_1 = require("./api/services/productsApi.service");
69
69
  const bootstrap_cache_1 = require("./products/bootstrap-cache");
70
+ const health_status_cache_1 = require("./resilience/health-status-cache");
70
71
  const imports_service_1 = __importDefault(require("./imports/imports.service"));
71
72
  const processor_service_1 = __importDefault(require("./processor/services/processor.service"));
72
73
  const processor_utils_1 = require("./processor/utils/processor.utils");
@@ -503,7 +504,7 @@ class Ductape {
503
504
  }
504
505
  }
505
506
  constructor({ accessKey, redis_url, product, env, local, ip_address, language, runtime_sync }) {
506
- var _a, _b, _c;
507
+ var _a, _b, _c, _d;
507
508
  this.productBuilders = new Map();
508
509
  this.appBuilders = new Map();
509
510
  // Cached service instances (lazily initialized after auth)
@@ -531,6 +532,9 @@ class Ductape {
531
532
  this.runtimePollJitter = 0.2;
532
533
  this.runtimeMaxBackoffMs = 300000;
533
534
  this.runtimeWarmupEnabled = true;
535
+ this.runtimeWarmupConnectionTimeoutMs = 5000;
536
+ this.runtimeStrictReady = false;
537
+ this.runtimeDatabaseTags = [];
534
538
  this.runtimeCredentialState = { status: 'idle', referenced: 0, cached: 0, missing: 0 };
535
539
  this.runtimeClosed = false;
536
540
  /** Register and inspect portable application functions used by Feature JSON. */
@@ -5456,6 +5460,8 @@ class Ductape {
5456
5460
  this.runtimePollJitter = Math.max(0, Math.min(1, (_b = runtime_sync.jitter) !== null && _b !== void 0 ? _b : 0.2));
5457
5461
  this.runtimeMaxBackoffMs = Math.max(this.runtimePollIntervalMs, (_c = runtime_sync.max_backoff_ms) !== null && _c !== void 0 ? _c : 300000);
5458
5462
  this.runtimeWarmupEnabled = runtime_sync.warm_connections !== false;
5463
+ this.runtimeWarmupConnectionTimeoutMs = Math.max(1000, (_d = runtime_sync.warm_connection_timeout_ms) !== null && _d !== void 0 ? _d : 5000);
5464
+ this.runtimeStrictReady = runtime_sync.strict_ready === true;
5459
5465
  }
5460
5466
  // Services are lazily initialized via factory methods (createNewDatabaseService, etc.)
5461
5467
  // This ensures initUserAuth() is called before service creation
@@ -5805,6 +5811,11 @@ class Ductape {
5805
5811
  const previousManifest = this.runtimeManifest;
5806
5812
  const scope = `${this.workspace_id}:${response.snapshot.product_tag}:${response.snapshot.env_slug}`;
5807
5813
  (0, bootstrap_cache_1.primeRuntimeBootstrapCache)(this.workspace_id, scope, response.snapshot.entries);
5814
+ const healthchecks = response.snapshot.entries
5815
+ .filter((entry) => { var _a; return (entry === null || entry === void 0 ? void 0 : entry.domain) === 'resilience' && ((_a = entry === null || entry === void 0 ? void 0 : entry.parts) === null || _a === void 0 ? void 0 : _a[2]) === 'healthcheck'; })
5816
+ .map((entry) => { var _a; return (_a = entry === null || entry === void 0 ? void 0 : entry.data) === null || _a === void 0 ? void 0 : _a.component; })
5817
+ .filter(Boolean);
5818
+ (0, health_status_cache_1.primeRuntimeHealthSnapshot)(this.workspace_id, response.snapshot.product_tag, response.snapshot.env_slug, healthchecks);
5808
5819
  this.runtimeManifest = response.manifest;
5809
5820
  const derivedReferences = (0, secrets_1.findAllSecretReferences)(response.snapshot.entries.map((entry) => entry.data)).sort();
5810
5821
  this.runtimeCredentialBundle = response.snapshot.credentials
@@ -5867,6 +5878,7 @@ class Ductape {
5867
5878
  .filter((entry) => (entry === null || entry === void 0 ? void 0 : entry.domain) === 'database')
5868
5879
  .map((entry) => { var _a, _b, _c; return String(((_a = entry === null || entry === void 0 ? void 0 : entry.parts) === null || _a === void 0 ? void 0 : _a[2]) || ((_c = (_b = entry === null || entry === void 0 ? void 0 : entry.data) === null || _b === void 0 ? void 0 : _b.database) === null || _c === void 0 ? void 0 : _c.tag) || '').trim(); })
5869
5880
  .filter(Boolean))];
5881
+ this.runtimeDatabaseTags = databaseTags;
5870
5882
  this.startRuntimeWarmup(databaseTags, Boolean(previousManifest && previousManifest.connectionRevision !== response.manifest.connectionRevision));
5871
5883
  }
5872
5884
  startRuntimeWarmup(databaseTags, recycleConnections) {
@@ -5883,7 +5895,10 @@ class Ductape {
5883
5895
  const databases = await Promise.all(databaseTags.map(async (tag) => {
5884
5896
  const start = Date.now();
5885
5897
  try {
5886
- await service.connect({ product: this.defaultProduct, env: this.defaultEnv, database: tag });
5898
+ await service.connect({
5899
+ product: this.defaultProduct, env: this.defaultEnv, database: tag,
5900
+ options: { connectionTimeout: this.runtimeWarmupConnectionTimeoutMs },
5901
+ });
5887
5902
  return { tag, status: 'ready', durationMs: Date.now() - start };
5888
5903
  }
5889
5904
  catch (error) {
@@ -5921,7 +5936,7 @@ class Ductape {
5921
5936
  (_b = (_a = this.runtimePollTimer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
5922
5937
  }
5923
5938
  async pollRuntimeManifest(failureCount) {
5924
- var _a, _b;
5939
+ var _a, _b, _c;
5925
5940
  if (!this.defaultProduct || !this.defaultEnv || this.runtimeClosed)
5926
5941
  return;
5927
5942
  try {
@@ -5929,13 +5944,29 @@ class Ductape {
5929
5944
  product_tag: this.defaultProduct,
5930
5945
  env_slug: this.defaultEnv,
5931
5946
  manifest_only: true,
5932
- etag: (_a = this.runtimeManifest) === null || _a === void 0 ? void 0 : _a.runtimeRevision,
5947
+ etag: this.runtimeManifest
5948
+ ? `${this.runtimeManifest.runtimeRevision}:${this.runtimeManifest.healthRevision}`
5949
+ : undefined,
5933
5950
  }, this.runtimeAuth());
5934
- if (manifestResponse && manifestResponse.manifest.runtimeRevision !== ((_b = this.runtimeManifest) === null || _b === void 0 ? void 0 : _b.runtimeRevision)) {
5935
- await this.refreshRuntimeSnapshot(true);
5951
+ const runtimeChanged = (manifestResponse === null || manifestResponse === void 0 ? void 0 : manifestResponse.manifest.runtimeRevision) !== ((_a = this.runtimeManifest) === null || _a === void 0 ? void 0 : _a.runtimeRevision);
5952
+ const healthChanged = (manifestResponse === null || manifestResponse === void 0 ? void 0 : manifestResponse.manifest.healthRevision) !== ((_b = this.runtimeManifest) === null || _b === void 0 ? void 0 : _b.healthRevision);
5953
+ if (manifestResponse && (runtimeChanged || healthChanged)) {
5954
+ const previous = this.runtimeManifest;
5955
+ const next = manifestResponse.manifest;
5956
+ const healthOnly = Boolean(previous) && !runtimeChanged && healthChanged;
5957
+ if (healthOnly && manifestResponse.health) {
5958
+ (0, health_status_cache_1.primeRuntimeHealthSnapshot)(this.workspace_id, manifestResponse.health.product_tag, manifestResponse.health.env_slug, manifestResponse.health.healthchecks);
5959
+ this.runtimeManifest = next;
5960
+ }
5961
+ else {
5962
+ await this.refreshRuntimeSnapshot(true);
5963
+ }
5936
5964
  }
5937
5965
  else if (this.defaultProduct && this.defaultEnv) {
5938
5966
  (0, bootstrap_cache_1.touchRuntimeBootstrapCache)(`${this.workspace_id}:${this.defaultProduct}:${this.defaultEnv}`);
5967
+ if ((_c = this.runtimeWarmupState) === null || _c === void 0 ? void 0 : _c.databases.some((database) => database.status === 'failed')) {
5968
+ this.startRuntimeWarmup(this.runtimeDatabaseTags, false);
5969
+ }
5939
5970
  }
5940
5971
  this.runtimeLastError = undefined;
5941
5972
  this.scheduleRuntimePoll(0);
@@ -5951,8 +5982,9 @@ class Ductape {
5951
5982
  if (this.runtimeRefreshInFlight)
5952
5983
  return await this.runtimeRefreshInFlight;
5953
5984
  this.runtimeRefreshInFlight = (async () => {
5954
- var _a;
5955
- const response = await this.productsApi.bootstrapRuntime(Object.assign({ product_tag: this.defaultProduct, env_slug: this.defaultEnv }, (force ? {} : { etag: (_a = this.runtimeManifest) === null || _a === void 0 ? void 0 : _a.runtimeRevision })), this.runtimeAuth());
5985
+ const response = await this.productsApi.bootstrapRuntime(Object.assign({ product_tag: this.defaultProduct, env_slug: this.defaultEnv }, (force || !this.runtimeManifest ? {} : {
5986
+ etag: `${this.runtimeManifest.runtimeRevision}:${this.runtimeManifest.healthRevision}`,
5987
+ })), this.runtimeAuth());
5956
5988
  if (response) {
5957
5989
  this.applyRuntimeSnapshot(response);
5958
5990
  const secrets = await this.createNewSecretsService();
@@ -5977,7 +6009,7 @@ class Ductape {
5977
6009
  }
5978
6010
  assertRuntimeReady() {
5979
6011
  var _a, _b;
5980
- if (!this.runtimeSyncEnabled)
6012
+ if (!this.runtimeSyncEnabled || !this.runtimeStrictReady)
5981
6013
  return;
5982
6014
  if (this.runtimeCredentialState.status === 'incomplete') {
5983
6015
  throw new Error(`Runtime credentials are incomplete (${this.runtimeCredentialState.missing} referenced secret(s) unavailable)`);