@wildo-ai/saas-backend-lib 1.1.8 → 1.1.9

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 (174) hide show
  1. package/dist/esm/data-seeding/models/data-seed.shared.schemas.d.ts +8 -0
  2. package/dist/esm/data-seeding/models/data-seed.shared.schemas.d.ts.map +1 -1
  3. package/dist/esm/data-seeding/models/data-seed.shared.schemas.js +17 -0
  4. package/dist/esm/data-seeding/models/data-seed.shared.schemas.js.map +1 -1
  5. package/dist/esm/data-seeding/services/data-seed-application-bootstrap.backend.d.ts.map +1 -1
  6. package/dist/esm/data-seeding/services/data-seed-application-bootstrap.backend.js +9 -1
  7. package/dist/esm/data-seeding/services/data-seed-application-bootstrap.backend.js.map +1 -1
  8. package/dist/esm/data-seeding/services/data-seed-environment-admission.backend.d.ts +23 -0
  9. package/dist/esm/data-seeding/services/data-seed-environment-admission.backend.d.ts.map +1 -0
  10. package/dist/esm/data-seeding/services/data-seed-environment-admission.backend.js +25 -0
  11. package/dist/esm/data-seeding/services/data-seed-environment-admission.backend.js.map +1 -0
  12. package/dist/esm/databases/services/postgresql-migration-runner.backend.d.ts +6 -0
  13. package/dist/esm/databases/services/postgresql-migration-runner.backend.d.ts.map +1 -1
  14. package/dist/esm/databases/services/postgresql-migration-runner.backend.js +8 -1
  15. package/dist/esm/databases/services/postgresql-migration-runner.backend.js.map +1 -1
  16. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts +0 -1
  17. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts.map +1 -1
  18. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js +4 -39
  19. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js.map +1 -1
  20. package/dist/esm/flows-actors/services/agents.backend.service.d.ts +15 -4
  21. package/dist/esm/flows-actors/services/agents.backend.service.d.ts.map +1 -1
  22. package/dist/esm/flows-actors/services/agents.backend.service.js +21 -11
  23. package/dist/esm/flows-actors/services/agents.backend.service.js.map +1 -1
  24. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts +47 -2
  25. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts.map +1 -1
  26. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js +56 -8
  27. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js.map +1 -1
  28. package/dist/esm/queue/job-consumer.backend.service.d.ts.map +1 -1
  29. package/dist/esm/queue/job-consumer.backend.service.js +21 -8
  30. package/dist/esm/queue/job-consumer.backend.service.js.map +1 -1
  31. package/dist/esm/queue/job-status-tracking.backend.service.d.ts.map +1 -1
  32. package/dist/esm/queue/job-status-tracking.backend.service.js +4 -1
  33. package/dist/esm/queue/job-status-tracking.backend.service.js.map +1 -1
  34. package/dist/esm/queue/queue.backend.service.d.ts +14 -0
  35. package/dist/esm/queue/queue.backend.service.d.ts.map +1 -1
  36. package/dist/esm/queue/queue.backend.service.js +68 -12
  37. package/dist/esm/queue/queue.backend.service.js.map +1 -1
  38. package/dist/esm/queue/scheduled-evidence-coverage.backend.d.ts +8 -0
  39. package/dist/esm/queue/scheduled-evidence-coverage.backend.d.ts.map +1 -1
  40. package/dist/esm/queue/scheduled-evidence-coverage.backend.js +20 -2
  41. package/dist/esm/queue/scheduled-evidence-coverage.backend.js.map +1 -1
  42. package/dist/esm/queue/scheduled-execution.backend.service.d.ts +44 -1
  43. package/dist/esm/queue/scheduled-execution.backend.service.d.ts.map +1 -1
  44. package/dist/esm/queue/scheduled-execution.backend.service.js +180 -10
  45. package/dist/esm/queue/scheduled-execution.backend.service.js.map +1 -1
  46. package/dist/esm/queue/scheduled-message-verifier.backend.service.d.ts +73 -21
  47. package/dist/esm/queue/scheduled-message-verifier.backend.service.d.ts.map +1 -1
  48. package/dist/esm/queue/scheduled-message-verifier.backend.service.js +162 -88
  49. package/dist/esm/queue/scheduled-message-verifier.backend.service.js.map +1 -1
  50. package/dist/esm/runtime/services/start-application.backend.service.d.ts.map +1 -1
  51. package/dist/esm/runtime/services/start-application.backend.service.js +16 -1
  52. package/dist/esm/runtime/services/start-application.backend.service.js.map +1 -1
  53. package/package.json +10 -10
  54. package/dist/esm/__tests__/fixture-deep-partial.d.ts +0 -18
  55. package/dist/esm/__tests__/fixture-deep-partial.d.ts.map +0 -1
  56. package/dist/esm/__tests__/fixture-deep-partial.js +0 -1
  57. package/dist/esm/__tests__/fixture-deep-partial.js.map +0 -1
  58. package/dist/esm/__tests__/integration/redis-integration-gate.d.ts +0 -26
  59. package/dist/esm/__tests__/integration/redis-integration-gate.d.ts.map +0 -1
  60. package/dist/esm/__tests__/integration/redis-integration-gate.js +0 -105
  61. package/dist/esm/__tests__/integration/redis-integration-gate.js.map +0 -1
  62. package/dist/esm/__tests__/setup.d.ts +0 -7
  63. package/dist/esm/__tests__/setup.d.ts.map +0 -1
  64. package/dist/esm/__tests__/setup.js +0 -14
  65. package/dist/esm/__tests__/setup.js.map +0 -1
  66. package/dist/esm/__tests__/test-container.d.ts +0 -41
  67. package/dist/esm/__tests__/test-container.d.ts.map +0 -1
  68. package/dist/esm/__tests__/test-container.js +0 -98
  69. package/dist/esm/__tests__/test-container.js.map +0 -1
  70. package/dist/esm/base-classes/services/__tests__/mock-resource-operation-helper.service.d.ts +0 -47
  71. package/dist/esm/base-classes/services/__tests__/mock-resource-operation-helper.service.d.ts.map +0 -1
  72. package/dist/esm/base-classes/services/__tests__/mock-resource-operation-helper.service.js +0 -82
  73. package/dist/esm/base-classes/services/__tests__/mock-resource-operation-helper.service.js.map +0 -1
  74. package/dist/esm/base-classes/services/repositories/__tests__/method-span-scan.guard-helpers.d.ts +0 -57
  75. package/dist/esm/base-classes/services/repositories/__tests__/method-span-scan.guard-helpers.d.ts.map +0 -1
  76. package/dist/esm/base-classes/services/repositories/__tests__/method-span-scan.guard-helpers.js +0 -172
  77. package/dist/esm/base-classes/services/repositories/__tests__/method-span-scan.guard-helpers.js.map +0 -1
  78. package/dist/esm/base-classes/services/repositories/__tests__/repositories-registry-infrastructure-read.double.d.ts +0 -41
  79. package/dist/esm/base-classes/services/repositories/__tests__/repositories-registry-infrastructure-read.double.d.ts.map +0 -1
  80. package/dist/esm/base-classes/services/repositories/__tests__/repositories-registry-infrastructure-read.double.js +0 -54
  81. package/dist/esm/base-classes/services/repositories/__tests__/repositories-registry-infrastructure-read.double.js.map +0 -1
  82. package/dist/esm/billing/services/__tests__/subscription-provider-projection.test-double.d.ts +0 -20
  83. package/dist/esm/billing/services/__tests__/subscription-provider-projection.test-double.d.ts.map +0 -1
  84. package/dist/esm/billing/services/__tests__/subscription-provider-projection.test-double.js +0 -33
  85. package/dist/esm/billing/services/__tests__/subscription-provider-projection.test-double.js.map +0 -1
  86. package/dist/esm/billing/services/custom-impl/__tests__/plan-change-confirmation.fixture.d.ts +0 -22
  87. package/dist/esm/billing/services/custom-impl/__tests__/plan-change-confirmation.fixture.d.ts.map +0 -1
  88. package/dist/esm/billing/services/custom-impl/__tests__/plan-change-confirmation.fixture.js +0 -92
  89. package/dist/esm/billing/services/custom-impl/__tests__/plan-change-confirmation.fixture.js.map +0 -1
  90. package/dist/esm/billing/services/custom-impl/__tests__/subscription-keyed-mutation.fixture.d.ts +0 -15
  91. package/dist/esm/billing/services/custom-impl/__tests__/subscription-keyed-mutation.fixture.d.ts.map +0 -1
  92. package/dist/esm/billing/services/custom-impl/__tests__/subscription-keyed-mutation.fixture.js +0 -61
  93. package/dist/esm/billing/services/custom-impl/__tests__/subscription-keyed-mutation.fixture.js.map +0 -1
  94. package/dist/esm/billing/services/webhooks/__tests__/billing-event-authority.test-double.d.ts +0 -21
  95. package/dist/esm/billing/services/webhooks/__tests__/billing-event-authority.test-double.d.ts.map +0 -1
  96. package/dist/esm/billing/services/webhooks/__tests__/billing-event-authority.test-double.js +0 -32
  97. package/dist/esm/billing/services/webhooks/__tests__/billing-event-authority.test-double.js.map +0 -1
  98. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.d.ts +0 -52
  99. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.d.ts.map +0 -1
  100. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.js +0 -74
  101. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.js.map +0 -1
  102. package/dist/esm/config/services/__tests__/mock-app-configuration.service.d.ts +0 -60
  103. package/dist/esm/config/services/__tests__/mock-app-configuration.service.d.ts.map +0 -1
  104. package/dist/esm/config/services/__tests__/mock-app-configuration.service.js +0 -156
  105. package/dist/esm/config/services/__tests__/mock-app-configuration.service.js.map +0 -1
  106. package/dist/esm/config/services/__tests__/startup-validator-resources-registry.double.d.ts +0 -31
  107. package/dist/esm/config/services/__tests__/startup-validator-resources-registry.double.d.ts.map +0 -1
  108. package/dist/esm/config/services/__tests__/startup-validator-resources-registry.double.js +0 -47
  109. package/dist/esm/config/services/__tests__/startup-validator-resources-registry.double.js.map +0 -1
  110. package/dist/esm/databases/services/__tests__/mock-mongoose-model.service.d.ts +0 -20
  111. package/dist/esm/databases/services/__tests__/mock-mongoose-model.service.d.ts.map +0 -1
  112. package/dist/esm/databases/services/__tests__/mock-mongoose-model.service.js +0 -424
  113. package/dist/esm/databases/services/__tests__/mock-mongoose-model.service.js.map +0 -1
  114. package/dist/esm/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.d.ts +0 -19
  115. package/dist/esm/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.d.ts.map +0 -1
  116. package/dist/esm/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.js +0 -49
  117. package/dist/esm/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.js.map +0 -1
  118. package/dist/esm/flows-actors/services/__tests__/pending-decision.fixtures.d.ts +0 -43
  119. package/dist/esm/flows-actors/services/__tests__/pending-decision.fixtures.d.ts.map +0 -1
  120. package/dist/esm/flows-actors/services/__tests__/pending-decision.fixtures.js +0 -61
  121. package/dist/esm/flows-actors/services/__tests__/pending-decision.fixtures.js.map +0 -1
  122. package/dist/esm/inbound/services/__tests__/support/in-memory-infrastructure-repositories.d.ts +0 -25
  123. package/dist/esm/inbound/services/__tests__/support/in-memory-infrastructure-repositories.d.ts.map +0 -1
  124. package/dist/esm/inbound/services/__tests__/support/in-memory-infrastructure-repositories.js +0 -92
  125. package/dist/esm/inbound/services/__tests__/support/in-memory-infrastructure-repositories.js.map +0 -1
  126. package/dist/esm/meta-workflows/services/__tests__/fixtures/meta-workflow-evaluation-treatment.test-fixture.d.ts +0 -7
  127. package/dist/esm/meta-workflows/services/__tests__/fixtures/meta-workflow-evaluation-treatment.test-fixture.d.ts.map +0 -1
  128. package/dist/esm/meta-workflows/services/__tests__/fixtures/meta-workflow-evaluation-treatment.test-fixture.js +0 -194
  129. package/dist/esm/meta-workflows/services/__tests__/fixtures/meta-workflow-evaluation-treatment.test-fixture.js.map +0 -1
  130. package/dist/esm/monitoring/logger/services/__tests__/mock-logger.service.d.ts +0 -34
  131. package/dist/esm/monitoring/logger/services/__tests__/mock-logger.service.d.ts.map +0 -1
  132. package/dist/esm/monitoring/logger/services/__tests__/mock-logger.service.js +0 -59
  133. package/dist/esm/monitoring/logger/services/__tests__/mock-logger.service.js.map +0 -1
  134. package/dist/esm/monitoring/observability/services/__tests__/mock-metrics.service.d.ts +0 -48
  135. package/dist/esm/monitoring/observability/services/__tests__/mock-metrics.service.d.ts.map +0 -1
  136. package/dist/esm/monitoring/observability/services/__tests__/mock-metrics.service.js +0 -53
  137. package/dist/esm/monitoring/observability/services/__tests__/mock-metrics.service.js.map +0 -1
  138. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/bundle.d.ts +0 -3
  139. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/bundle.d.ts.map +0 -1
  140. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/bundle.js +0 -19
  141. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/bundle.js.map +0 -1
  142. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/host.d.ts +0 -51
  143. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/host.d.ts.map +0 -1
  144. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/host.js +0 -24
  145. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/host.js.map +0 -1
  146. package/dist/esm/notifications/services/__tests__/recipient-language.test-double.d.ts +0 -8
  147. package/dist/esm/notifications/services/__tests__/recipient-language.test-double.d.ts.map +0 -1
  148. package/dist/esm/notifications/services/__tests__/recipient-language.test-double.js +0 -9
  149. package/dist/esm/notifications/services/__tests__/recipient-language.test-double.js.map +0 -1
  150. package/dist/esm/pdf-templates/__tests__/fixtures/tiny-pdf-template.fixture.d.ts +0 -10
  151. package/dist/esm/pdf-templates/__tests__/fixtures/tiny-pdf-template.fixture.d.ts.map +0 -1
  152. package/dist/esm/pdf-templates/__tests__/fixtures/tiny-pdf-template.fixture.js +0 -18
  153. package/dist/esm/pdf-templates/__tests__/fixtures/tiny-pdf-template.fixture.js.map +0 -1
  154. package/dist/esm/security/api-keys/__tests__/api-key-usage-redis.double.d.ts +0 -11
  155. package/dist/esm/security/api-keys/__tests__/api-key-usage-redis.double.d.ts.map +0 -1
  156. package/dist/esm/security/api-keys/__tests__/api-key-usage-redis.double.js +0 -34
  157. package/dist/esm/security/api-keys/__tests__/api-key-usage-redis.double.js.map +0 -1
  158. package/dist/esm/security/authentications/__tests__/registration-onboarding.harness.d.ts +0 -105
  159. package/dist/esm/security/authentications/__tests__/registration-onboarding.harness.d.ts.map +0 -1
  160. package/dist/esm/security/authentications/__tests__/registration-onboarding.harness.js +0 -140
  161. package/dist/esm/security/authentications/__tests__/registration-onboarding.harness.js.map +0 -1
  162. package/dist/esm/security/authentications/services/__tests__/oauth-provider-audit-spies.mock.d.ts +0 -35
  163. package/dist/esm/security/authentications/services/__tests__/oauth-provider-audit-spies.mock.d.ts.map +0 -1
  164. package/dist/esm/security/authentications/services/__tests__/oauth-provider-audit-spies.mock.js +0 -46
  165. package/dist/esm/security/authentications/services/__tests__/oauth-provider-audit-spies.mock.js.map +0 -1
  166. package/dist/esm/security/connected-accounts/__tests__/support/real-connection-client-methods.d.ts +0 -2
  167. package/dist/esm/security/connected-accounts/__tests__/support/real-connection-client-methods.d.ts.map +0 -1
  168. package/dist/esm/security/connected-accounts/__tests__/support/real-connection-client-methods.js +0 -18
  169. package/dist/esm/security/connected-accounts/__tests__/support/real-connection-client-methods.js.map +0 -1
  170. package/dist/esm/systems-of-record/credentials/__tests__/certificate-fixtures.d.ts +0 -20
  171. package/dist/esm/systems-of-record/credentials/__tests__/certificate-fixtures.d.ts.map +0 -1
  172. package/dist/esm/systems-of-record/credentials/__tests__/certificate-fixtures.js +0 -56
  173. package/dist/esm/systems-of-record/credentials/__tests__/certificate-fixtures.js.map +0 -1
  174. package/dist/tsconfig.build.tsbuildinfo +0 -1
@@ -38,7 +38,7 @@ import { JobPayloadStorageBackendService } from './job-payload-storage.backend.s
38
38
  import { JobStatusTrackingBackendService } from './job-status-tracking.backend.service.js';
39
39
  import { JobCompletionRegistryBackendService } from './job-completion-registry.backend.service.js';
40
40
  import { WorkerShutdownManagerBackendService } from './worker-shutdown-manager.backend.service.js';
41
- import { ScheduledMessageVerifierBackendService } from './scheduled-message-verifier.backend.service.js';
41
+ import { ScheduledMessageVerifierBackendService, ScheduledDeliveryVerdict } from './scheduled-message-verifier.backend.service.js';
42
42
  import { JobPayloadSchema, JobType, ResourceSerializationUtils, ResourcesConfig_OperationPathUtils, JobStatus, JobExecutionStatus, isWildoBackendError, JobRetryUtils, QueueNamingUtils, QueueVariant, QUEUE_RETRY_DEFAULTS, ErrorHandling_Strategy, ErrorType, ErrorCustomMessageReference, ErrorSeverity, } from '@wildo-ai/saas-models';
43
43
  const DEFAULT_CONSUMER_CONFIG = {
44
44
  enableRetry: true,
@@ -467,10 +467,13 @@ let JobConsumerBackendService = class JobConsumerBackendService {
467
467
  let accepted = false;
468
468
  let admitted;
469
469
  try {
470
- const job = await this.scheduledMessageVerifier.verifyAndConvert(msg.content.toString());
470
+ const delivery = await this.scheduledMessageVerifier.verifyAndConvert(msg.content.toString());
471
+ const job = delivery.value;
471
472
  // A WIRE check: the crontabs-manager signs the platform id it registered this application
472
473
  // under, so the platform id is the right thing to compare the message against. The row the
473
- // receipt then creates is anchored by the tracker to the record id, not to this value.
474
+ // receipt then creates is anchored by the tracker to the record id, not to this value. It
475
+ // applies to a LATE delivery too: a genuine token addressed to another application is foreign
476
+ // whether or not it is on time, and recording it here would plant another tenant's miss.
474
477
  if (job.applicationId !== this.platformApplicationId)
475
478
  throw this.errorBuilder.buildError(ErrorType.AUTHENTICATION, undefined, {
476
479
  customMessageReference: ErrorCustomMessageReference.AUTHENTICATION_INVALID_TOKEN,
@@ -479,12 +482,22 @@ let JobConsumerBackendService = class JobConsumerBackendService {
479
482
  this.scheduledRunner ??= new ScheduledExecutionRunner(this.jobStatusTracking, this.logger, this.payloadStorage, {
480
483
  started: () => this.shutdownManager.jobStarted(), completed: () => this.shutdownManager.jobCompleted(),
481
484
  });
482
- // Durable receipt, then acknowledge, THEN run: the delivery is released as soon as the occurrence
483
- // is in the database, so a long run can no longer hold every later delivery unreceived until its
484
- // five-minute token lapses (`ScheduledExecutionRunner.admit`).
485
485
  const resolveContract = (payload) => this.resolveScheduledContract(payload);
486
- admitted = await this.scheduledRunner.admit(job, QueueNamingUtils.buildQueueName(this.platformApplicationId, 'scheduled'), resolveContract);
487
- accepted = true;
486
+ const queueName = QueueNamingUtils.buildQueueName(this.platformApplicationId, 'scheduled');
487
+ if (delivery.verdict === ScheduledDeliveryVerdict.LATE) {
488
+ // Genuine but past its admission deadline: the occurrence was missed — usually because nothing
489
+ // consumed this queue, though the scheduler can share the delay (see `ScheduledDeliveryLateness`).
490
+ // Record the miss and acknowledge; the runner reports the whole drain ONCE
491
+ // (#2212). Only a delivery it could not record is dead-lettered, so its copy survives.
492
+ accepted = await this.scheduledRunner.recordLateDelivery(job, queueName, resolveContract, delivery.lateness);
493
+ }
494
+ else {
495
+ // Durable receipt, then acknowledge, THEN run: the delivery is released as soon as the occurrence
496
+ // is in the database, so a long run can no longer hold every later delivery unreceived until its
497
+ // five-minute token lapses (`ScheduledExecutionRunner.admit`).
498
+ admitted = await this.scheduledRunner.admit(job, queueName, resolveContract);
499
+ accepted = true;
500
+ }
488
501
  }
489
502
  catch (error) {
490
503
  this.logger.error('Scheduled receipt failed', { ...projectCaughtErrorLogFields(error) });
@@ -1 +1 @@
1
- {"version":3,"file":"job-consumer.backend.service.js","sourceRoot":"","sources":["../../../../src/queue/job-consumer.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Job Consumer Backend Service\n *\n * Handles the complete message lifecycle:\n * - Consumes messages from RabbitMQ\n * - Executes jobs via JobExecutorBackendService\n * - Handles retry logic with exponential backoff\n * - Sends RPC replies for QUEUED mode\n * - Tracks job status\n * - Acknowledges/rejects messages appropriately\n */\n\nimport { injectable, inject } from 'inversify';\nimport { z } from 'zod';\nimport { v4 as uuidv4 } from 'uuid';\nimport * as os from 'os';\nimport type { ConsumeMessage, Channel } from 'amqplib';\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport { LoggerService } from '~wildo-backend-lib/monitoring/logger/services/logger.service';\nimport { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';\nimport { ErrorBuilderBackendService } from '~wildo-backend-lib/errors/services/error-builder.backend.service';\nimport { projectWildoBackendErrorLogFields, describeCaughtError, projectCaughtErrorLogFields } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\nimport { adoptCorrelationIdIntoCurrentFrame, runInFreshRequestContextIfAbsent } from '~wildo-backend-lib/runtime/models/request-context.als.backend';\nimport { runWithJobWorkAttributionFrame } from '~wildo-backend-lib/runtime/models/work-attribution.als.backend';\nimport type { QueueAdapter } from './adapters/queue-adapter.backend.interface';\nimport type { MessageHandler } from './adapters/queue-adapter.backend.interface';\nimport { ScheduledExecutionRunner, type ScheduledExecutionContract } from './scheduled-execution.backend.service';\nimport { JobExecutorBackendService } from './job-executor.backend.service';\nimport { JobPayloadStorageBackendService } from './job-payload-storage.backend.service';\nimport { JobStatusTrackingBackendService } from './job-status-tracking.backend.service';\nimport { JobCompletionRegistryBackendService } from './job-completion-registry.backend.service';\nimport { WorkerShutdownManagerBackendService } from './worker-shutdown-manager.backend.service';\nimport { ScheduledMessageVerifierBackendService } from './scheduled-message-verifier.backend.service';\nimport {\n JobPayload,\n JobPayloadSchema,\n type ResourceConfiguration_OperationPath,\n JobType,\n ResourceSerializationUtils,\n ResourcesConfig_OperationPathUtils,\n JobResult,\n JobStatus,\n JobExecutionStatus,\n type JobExecution,\n isWildoBackendError,\n JobRetryUtils,\n QueueNamingUtils,\n QueueVariant,\n QUEUE_RETRY_DEFAULTS,\n ErrorHandling_Strategy,\n QueueRetryConfig,\n ErrorType,\n ErrorCustomMessageReference,\n ErrorSeverity,\n} from '@wildo-ai/saas-models';\n\n/**\n * Worker identification for tracking.\n */\ninterface WorkerIdentity {\n workerId: string;\n hostname: string;\n pid: number;\n}\n\n/**\n * Consumer configuration.\n */\nexport interface JobConsumerConfig {\n /** Whether to enable retry logic */\n enableRetry?: boolean;\n /** Default retry configuration */\n retryConfig?: Partial<QueueRetryConfig>;\n}\n\nconst DEFAULT_CONSUMER_CONFIG: JobConsumerConfig = {\n enableRetry: true,\n retryConfig: QUEUE_RETRY_DEFAULTS,\n};\n\n@injectable()\nexport class JobConsumerBackendService {\n protected logDebug: (message: string, context?: Record<string, unknown>) => void;\n private _applicationId: string | null = null;\n private readonly workerIdentity: WorkerIdentity;\n private isConsuming = false;\n private scheduledRunner?: ScheduledExecutionRunner;\n private consumingQueues: string[] = [];\n\n constructor(\n @inject(SAAS_SERVICE_TYPES.AppConfigService)\n private readonly appConfigService: AppConfigurationService,\n @inject(SAAS_SERVICE_TYPES.RabbitMQAdapterService)\n private readonly adapter: QueueAdapter,\n @inject(SAAS_SERVICE_TYPES.JobExecutorBackendService)\n private readonly jobExecutor: JobExecutorBackendService,\n @inject(SAAS_SERVICE_TYPES.JobStatusTrackingService)\n private readonly jobStatusTracking: JobStatusTrackingBackendService,\n @inject(SAAS_SERVICE_TYPES.JobCompletionRegistryService)\n private readonly completionRegistry: JobCompletionRegistryBackendService,\n @inject(SAAS_SERVICE_TYPES.WorkerShutdownManagerService)\n private readonly shutdownManager: WorkerShutdownManagerBackendService,\n @inject(SAAS_SERVICE_TYPES.ScheduledMessageVerifierService)\n private readonly scheduledMessageVerifier: ScheduledMessageVerifierBackendService,\n @inject(SAAS_SERVICE_TYPES.Logger)\n private readonly logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.ErrorBuilderService)\n private readonly errorBuilder: ErrorBuilderBackendService,\n @inject(SAAS_SERVICE_TYPES.JobPayloadStorageService)\n private readonly payloadStorage: JobPayloadStorageBackendService,\n ) {\n this.logDebug = this.logger.debugByType('JobConsumerBackendService');\n this.logger.setDebugTypeLogging('JobConsumerBackendService', false);\n // Lazy-load applicationId to avoid accessing config before initialization\n this.workerIdentity = {\n workerId: uuidv4(),\n hostname: os.hostname(),\n pid: process.pid,\n };\n }\n\n /**\n * The PLATFORM's id for this application — what every queue name is built from and what the\n * crontabs-manager signs into a scheduled message. Lazy, to avoid reading config in the constructor.\n *\n * This consumer ADDRESSES with it and never stamps it: the job rows and stored payloads are\n * anchored by `JobStatusTrackingBackendService` and `JobPayloadStorageBackendService` to the\n * application RECORD id (`applications._id`), which they resolve themselves. Until 2026-09-18 this\n * one value was handed to the scheduled runner for its row scans as well, and it \"worked\" only\n * because the rows had been stamped from the same wire value — the defect #1296 records.\n */\n private get platformApplicationId(): string {\n if (!this._applicationId) {\n this._applicationId = this.appConfigService.applicationId;\n }\n return this._applicationId;\n }\n\n /**\n * Start consuming from all operation and scheduled queues.\n */\n async startConsuming(config: JobConsumerConfig = {}): Promise<void> {\n if (this.isConsuming) {\n this.logger.warn('Consumer already running');\n return;\n }\n\n const mergedConfig = { ...DEFAULT_CONSUMER_CONFIG, ...config };\n\n // Connect to RabbitMQ\n await this.adapter.connect();\n\n // Start consuming from operations queues (normal and priority variant)\n const operationsQueueConfigs = [\n { category: 'operations', variant: undefined },\n { category: 'operations', variant: QueueVariant.PRIORITY },\n ];\n\n for (const queueConfig of operationsQueueConfigs) {\n const queueName = QueueNamingUtils.buildQueueName(\n this.platformApplicationId,\n queueConfig.category,\n queueConfig.variant\n );\n\n // Create handler that matches MessageHandler signature\n const handler: MessageHandler = async (msg: ConsumeMessage, channel: Channel) => {\n // Phase 1 — each consumed job runs in its own correlation frame (fresh id). Phase 6 will seed\n // it from the enqueuing request's originCorrelationId carried on the job payload.\n await runInFreshRequestContextIfAbsent(() => this.handleMessage(msg, channel, mergedConfig));\n };\n\n await this.adapter.consume(queueName, handler);\n this.consumingQueues.push(queueName);\n\n this.logDebug('Started consuming from queue', {\n queueName,\n workerId: this.workerIdentity.workerId,\n });\n }\n\n // Start consuming from scheduled queue (JWT-signed messages from crontabs-manager)\n const scheduledQueueName = QueueNamingUtils.buildQueueName(this.platformApplicationId, 'scheduled');\n\n const scheduledHandler: MessageHandler = async (msg: ConsumeMessage, channel: Channel) => {\n // Phase 1 — each cron tick (scheduled-queue message) runs in its own correlation frame.\n await runInFreshRequestContextIfAbsent(() => this.handleScheduledMessage(msg, channel, mergedConfig));\n };\n\n this.scheduledRunner = new ScheduledExecutionRunner(this.jobStatusTracking, this.logger, this.payloadStorage, {\n started: () => this.shutdownManager.jobStarted(), completed: () => this.shutdownManager.jobCompleted(),\n });\n await this.diagnoseScheduledEvidenceTargets();\n await this.adapter.consume(scheduledQueueName, scheduledHandler);\n this.scheduledRunner.start(scheduledQueueName, job => this.resolveScheduledContract(job));\n this.consumingQueues.push(scheduledQueueName);\n\n this.logDebug('Started consuming from scheduled queue', {\n queueName: scheduledQueueName,\n workerId: this.workerIdentity.workerId,\n });\n\n this.isConsuming = true;\n this.logDebug('Job consumer started', {\n workerId: this.workerIdentity.workerId,\n queues: this.consumingQueues.length,\n });\n }\n\n /**\n * Stop consuming and close connections.\n */\n async stopConsuming(): Promise<void> {\n this.scheduledRunner?.stop();\n if (!this.isConsuming) {\n return;\n }\n\n // Cancel all consumers\n for (const queueName of this.consumingQueues) {\n await this.adapter.cancelConsumer(queueName);\n }\n\n this.consumingQueues = [];\n this.isConsuming = false;\n\n this.logDebug('Job consumer stopped', {\n workerId: this.workerIdentity.workerId,\n });\n }\n\n /**\n * Handle a single message from the queue.\n */\n private async handleMessage(\n msg: ConsumeMessage,\n channel: Channel,\n config: JobConsumerConfig\n ): Promise<void> {\n let job: JobPayload;\n\n try {\n job = JSON.parse(msg.content.toString());\n } catch (parseError) {\n this.logger.error('Failed to parse job message', {\n ...projectCaughtErrorLogFields(parseError),\n });\n // Invalid message - don't requeue\n channel.nack(msg, false, false);\n return;\n }\n\n // Phase 6 — this job belongs to the trace of the request that enqueued it: adopt that request's\n // originCorrelationId into the (freshly-minted) consume frame, so every log line + audit row this\n // job produces on the worker carries the originating request's correlationId. Absent/malformed →\n // the frame keeps its fresh id (a job with no originating request stays independently traceable).\n adoptCorrelationIdIntoCurrentFrame(job.originCorrelationId);\n\n const startTime = Date.now();\n const { replyTo, correlationId } = msg.properties;\n\n // Track in-flight job for graceful shutdown\n this.shutdownManager.jobStarted();\n\n this.logDebug('Processing job', {\n jobId: job.jobId,\n jobType: job.jobType,\n priority: job.priority,\n retryCount: job.retryCount ?? 0,\n });\n\n try {\n // Mark job as started\n await this.jobStatusTracking.markStarted(job.jobId, this.workerIdentity.workerId, job.retryCount ?? 0);\n\n // Execute the job - returns JobResult which may indicate success OR failure\n // The executor catches all errors and returns a result with status\n // #1598 F14 (I7): reopen the work frame the job was enqueued inside, beside the correlation id adopted\n // above, so a model call the job makes is attributed to the same tenant and case. A payload without one\n // runs OUTSIDE any frame, whatever this continuation carries (see `runWithJobWorkAttributionFrame`).\n const result = await runWithJobWorkAttributionFrame(job.attribution, () => this.jobExecutor.execute(job));\n\n // Check if job failed (executor returns result with FAILED status, doesn't throw)\n if (result.status === JobStatus.FAILED) {\n // Convert the error result to proper retry handling\n await this.handleJobFailure(job, result, msg, channel, config, startTime);\n return;\n }\n\n await this.finishJob(job, result, msg, channel);\n\n this.logDebug('Job completed successfully', {\n jobId: job.jobId,\n durationMs: Date.now() - startTime,\n });\n\n } catch (error) {\n // This catch block handles unexpected errors before a final outcome (e.g., from markStarted)\n // NOT job execution errors (those are returned by executor as FAILED status)\n await this.handleJobError(job, error, msg, channel, config, startTime);\n } finally {\n // Always track job completion for graceful shutdown\n this.shutdownManager.jobCompleted();\n }\n }\n\n /**\n * Process-local completion is best effort, never a new attempt of the business\n * operation. Called only for success or a terminal failure, not retry handoff.\n * Failed jobs can contain malformed identity, so decoding must not obstruct\n * dead-letter settlement. Such jobs can reach general/type handlers, but never\n * a resource selector without the required typed identity (see #768).\n */\n private async dispatchCompletion(job: JobPayload, result: JobResult): Promise<void> {\n const jobType = z.enum(JobType).safeParse(job.jobType);\n if (!jobType.success) {\n this.logger.error('Completion skipped for invalid job type', { jobId: job.jobId, jobType: job.jobType });\n return;\n }\n let operationPath: ResourceConfiguration_OperationPath<any, any> | undefined;\n try {\n operationPath = jobType.data === JobType.RESOURCE_OPERATION && job.operationPathJson\n ? ResourceSerializationUtils.deserializeOperationPath(job.operationPathJson)\n : jobType.data === JobType.SCHEDULED_CRON && job.operationPathKey\n ? ResourcesConfig_OperationPathUtils.parseOperationPathKey(job.operationPathKey)\n : undefined;\n } catch (error) {\n this.logger.error('Completion resource identity unavailable', { jobId: job.jobId, ...projectCaughtErrorLogFields(error) });\n }\n try {\n await this.completionRegistry.dispatch({ result, jobType: jobType.data, operationPath, operationPathKey: job.operationPathKey, batchRef: job.batchRef });\n } catch (error) {\n // The registry already isolates individual handler failures. Guard its\n // dispatch boundary too: notification infrastructure must not replay work.\n this.logger.error('Completion dispatch failed', { jobId: job.jobId, ...projectCaughtErrorLogFields(error) });\n }\n }\n\n /**\n * Once execution succeeds or retry eligibility says terminal, failures in\n * tracking, callbacks or an RPC reply must not reclassify the outcome.\n * Settlement can itself fail on a closed channel; the broker then owns any\n * redelivery. Local callbacks may repeat on redelivery; they are not durable receipts.\n */\n private async finishJob(job: JobPayload, result: JobResult, msg: ConsumeMessage, channel: Channel): Promise<void> {\n const succeeded = result.status === JobStatus.COMPLETED;\n try {\n if (succeeded) await this.jobStatusTracking.markCompleted(job.jobId, job.retryCount ?? 0);\n else await this.jobStatusTracking.recordFailure(job.jobId, { status: JobExecutionStatus.DEAD_LETTER, deliveredRetryCount: job.retryCount ?? 0, error: result.error });\n } catch (error) {\n this.logger.error('Finished job tracking failed', { jobId: job.jobId, ...projectCaughtErrorLogFields(error) });\n }\n await this.dispatchCompletion(job, result);\n const { replyTo, correlationId } = msg.properties;\n if (replyTo && correlationId) {\n try {\n await this.adapter.publishResult(replyTo, correlationId, result);\n } catch (error) {\n this.logger.error('Finished job reply failed', { jobId: job.jobId, ...projectCaughtErrorLogFields(error) });\n }\n }\n try {\n if (succeeded) channel.ack(msg);\n // Reject without requeue; the queue's DLX owns parking this delivery.\n else channel.nack(msg, false, false);\n } catch (error) {\n this.logger.error('Finished job settlement failed', { jobId: job.jobId, ...projectCaughtErrorLogFields(error) });\n }\n }\n\n /**\n * Handle job failure when executor returns FAILED status (not an exception).\n * The executor catches errors and returns a JobResult with status FAILED.\n */\n private async handleJobFailure(\n job: JobPayload,\n result: JobResult,\n msg: ConsumeMessage,\n channel: Channel,\n config: JobConsumerConfig,\n startTime: number\n ): Promise<void> {\n const currentRetry = job.retryCount ?? 0;\n const maxRetries = job.maxRetries ?? config.retryConfig?.maxRetries ?? QUEUE_RETRY_DEFAULTS.maxRetries;\n const { replyTo, correlationId } = msg.properties;\n\n // Extract error handling strategy from the error\n const errorStrategy = result.error?.errorHandlingStrategy;\n const shouldRetry = config.enableRetry &&\n this.shouldRetryFromStrategy(errorStrategy, currentRetry, maxRetries);\n\n if (shouldRetry) {\n // Resolve backoff from the job's per-operation retryConfig, falling back to\n // the consumer config then the framework defaults (per-field, so a partial\n // authored retryConfig still gets sane values for the axes it omits).\n const backoff = job.retryConfig;\n const retryConfig: QueueRetryConfig = {\n retryPolicy: backoff?.retryPolicy ?? config.retryConfig?.retryPolicy ?? QUEUE_RETRY_DEFAULTS.retryPolicy,\n maxRetries: maxRetries,\n baseDelayMs: backoff?.baseDelayMs ?? config.retryConfig?.baseDelayMs ?? QUEUE_RETRY_DEFAULTS.baseDelayMs,\n maxDelayMs: backoff?.maxDelayMs ?? config.retryConfig?.maxDelayMs ?? QUEUE_RETRY_DEFAULTS.maxDelayMs,\n timeoutMs: job.timeoutMs ?? config.retryConfig?.timeoutMs ?? QUEUE_RETRY_DEFAULTS.timeoutMs,\n };\n\n const delay = JobRetryUtils.calculateDelay(retryConfig, currentRetry);\n\n // Create updated job with incremented retry count\n const retryJob: JobPayload = {\n ...job,\n retryCount: currentRetry + 1,\n };\n\n // Durable backoff: hand the retry to the broker (delay queue holds it, then\n // dead-letters it back) instead of an in-process setTimeout that would be\n // lost if this worker crashes during the wait.\n const operationsQueue = QueueNamingUtils.buildQueueName(this.platformApplicationId, 'operations');\n try {\n await this.adapter.scheduleDelayedRetry(operationsQueue, retryJob, delay, {\n replyTo,\n correlationId,\n });\n } catch (scheduleError) {\n // Could not hand the retry to the broker — requeue the ORIGINAL (do not\n // ACK) so it is redelivered rather than silently lost.\n this.logger.error('Failed to schedule durable retry; requeueing original', {\n jobId: job.jobId,\n ...projectCaughtErrorLogFields(scheduleError),\n });\n channel.nack(msg, false, true);\n return;\n }\n\n // The retry is already broker-owned. Neither tracking nor ACK failure may\n // return to execution-error handling and publish a second retry.\n try {\n await this.jobStatusTracking.recordFailure(job.jobId, {\n status: JobExecutionStatus.RETRYING, deliveredRetryCount: currentRetry, error: result.error,\n });\n } catch (trackingError) {\n this.logger.error('Failed to record retry outcome', { jobId: job.jobId, ...projectCaughtErrorLogFields(trackingError) });\n }\n try { channel.ack(msg); } catch (settlementError) {\n this.logger.error('Retry original settlement failed', { jobId: job.jobId, ...projectCaughtErrorLogFields(settlementError) });\n }\n\n this.logger.warn('Job retry scheduled (durable delay queue)', {\n jobId: job.jobId,\n retryCount: currentRetry + 1,\n maxRetries,\n delayMs: delay,\n // The queue is a non-HTTP boundary and owns its own operational level (a\n // scheduled retry is a `warn`, not classified from the error's severity).\n // Reuse the canonical field projection to restore the full error detail\n // that no longer self-logs at construction.\n ...(result.error ? projectWildoBackendErrorLogFields(result.error) : {}),\n });\n\n } else {\n await this.finishJob(job, result, msg, channel);\n\n this.logger.error('Job failed permanently', {\n jobId: job.jobId,\n retryCount: currentRetry,\n maxRetries,\n // Permanent (dead-lettered) failure is operationally an `error`\n // regardless of the underlying error's business severity, so the level\n // stays explicit; the projection restores the full error detail (type,\n // status, context) and the stack.\n ...(result.error ? projectWildoBackendErrorLogFields(result.error) : {}),\n ...(result.error?.stack ? { stack: result.error.stack } : {}),\n });\n }\n }\n\n /**\n * Check if retry should happen based on error strategy.\n */\n private shouldRetryFromStrategy(\n strategy: ErrorHandling_Strategy | undefined,\n currentRetry: number,\n maxRetries: number\n ): boolean {\n // Check retry count limit\n if (currentRetry >= maxRetries) {\n return false;\n }\n\n // Only retry if strategy is explicitly RETRY or undefined (default to retry)\n return strategy === undefined || strategy === ErrorHandling_Strategy.RETRY;\n }\n\n /**\n * Handle unexpected errors (not job execution failures).\n * This handles errors from execution and pre-execution tracking.\n * Terminal notification and settlement failures are isolated by finishJob.\n */\n private async handleJobError(\n job: JobPayload,\n error: unknown,\n msg: ConsumeMessage,\n channel: Channel,\n config: JobConsumerConfig,\n startTime: number\n ): Promise<void> {\n // Returned and thrown failures use one retry decision and one tracking path.\n const failure = isWildoBackendError(error) ? error : {\n type: ErrorType.INTERNAL, severity: ErrorSeverity.HIGH, timestamp: new Date(),\n context: { message: describeCaughtError(error) }, backendActions: [],\n customMessageReference: ErrorCustomMessageReference.INTERNAL, statusCode: 500,\n };\n await this.handleJobFailure(job, {\n jobId: job.jobId, status: JobStatus.FAILED, error: failure,\n startedAt: new Date(startTime), completedAt: new Date(), durationMs: Date.now() - startTime,\n }, msg, channel, config, startTime);\n }\n\n /** Registry resolution is side-effect free: diagnose misspelled targets before accepting scheduled deliveries. */\n private async diagnoseScheduledEvidenceTargets(): Promise<void> {\n const configured = this.appConfigService.config?.scheduledEvidence;\n if (!configured) return;\n for (const target of [\n ...Object.keys(configured.batches ?? {}).map(batchRef => ({ batchRef })),\n ...Object.keys(configured.operations ?? {}).map(operationPathKey => ({ operationPathKey })),\n ]) {\n const probe = JobPayloadSchema.parse({ jobId: uuidv4(), applicationId: this.platformApplicationId,\n jobType: JobType.SCHEDULED_CRON, createdAt: new Date(), ...target });\n if (!await this.jobExecutor.getScheduledContract(probe)) {\n this.logger.warn('Scheduled evidence policy has no registered executable target; no evidence will be collected for this key', target);\n }\n }\n for (const minionName of Object.keys(configured.minions ?? {})) {\n if (!Object.hasOwn(this.appConfigService.config.minions ?? {}, minionName)) {\n this.logger.warn('Scheduled evidence policy names an undeclared minion; no evidence will be collected for this key', { minionName });\n }\n }\n }\n\n /** One resolver owns policy selection for first delivery, scanner recovery and operator review. */\n private async resolveScheduledContract(job: JobPayload): Promise<ScheduledExecutionContract | undefined> {\n if (Boolean(job.batchRef) === Boolean(job.operationPathKey)) {\n this.logger.warn('Scheduled evidence target is ambiguous or missing', { jobId: job.jobId });\n return undefined;\n }\n const contract = await this.jobExecutor.getScheduledContract(job);\n if (!contract) return undefined;\n const configured = this.appConfigService.config?.scheduledEvidence;\n const policies = job.batchRef ? configured?.batches : configured?.operations;\n const target = job.batchRef ?? job.operationPathKey!;\n const evidencePolicy = policies && Object.hasOwn(policies, target) ? policies[target] : undefined;\n return { ...contract, evidencePolicy };\n }\n\n /**\n * Handle a scheduled message (JWT-signed from crontabs-batches-manager).\n */\n private async handleScheduledMessage(\n msg: ConsumeMessage,\n channel: Channel,\n config: JobConsumerConfig\n ): Promise<void> {\n this.shutdownManager.jobStarted();\n let accepted = false;\n let admitted: JobExecution | undefined;\n try {\n const job = await this.scheduledMessageVerifier.verifyAndConvert(msg.content.toString());\n // A WIRE check: the crontabs-manager signs the platform id it registered this application\n // under, so the platform id is the right thing to compare the message against. The row the\n // receipt then creates is anchored by the tracker to the record id, not to this value.\n if (job.applicationId !== this.platformApplicationId) throw this.errorBuilder.buildError(\n ErrorType.AUTHENTICATION, undefined, {\n customMessageReference: ErrorCustomMessageReference.AUTHENTICATION_INVALID_TOKEN,\n context: { reason: 'Scheduled message targets a different application' },\n },\n );\n this.scheduledRunner ??= new ScheduledExecutionRunner(this.jobStatusTracking, this.logger, this.payloadStorage, {\n started: () => this.shutdownManager.jobStarted(), completed: () => this.shutdownManager.jobCompleted(),\n });\n // Durable receipt, then acknowledge, THEN run: the delivery is released as soon as the occurrence\n // is in the database, so a long run can no longer hold every later delivery unreceived until its\n // five-minute token lapses (`ScheduledExecutionRunner.admit`).\n const resolveContract = (payload: JobPayload) => this.resolveScheduledContract(payload);\n admitted = await this.scheduledRunner.admit(job, QueueNamingUtils.buildQueueName(this.platformApplicationId, 'scheduled'),\n resolveContract);\n accepted = true;\n } catch (error) {\n this.logger.error('Scheduled receipt failed', { ...projectCaughtErrorLogFields(error) });\n }\n // Settlement cannot re-enter business execution. Durable recovery owns accepted failures.\n try {\n if (accepted) channel.ack(msg);\n else channel.nack(msg, false, false);\n } catch (error) {\n this.logger.error('Scheduled receipt settlement failed', { ...projectCaughtErrorLogFields(error) });\n } finally { this.shutdownManager.jobCompleted(); }\n // Started only after the delivery is settled; the runner tracks the run's own activity.\n if (admitted && this.scheduledRunner) this.scheduledRunner.launch(admitted, payload => this.resolveScheduledContract(payload));\n }\n\n /** Trusted backend administration entry: the caller authorizes its operator and supplies attribution. */\n async resolveScheduledReview(input: Omit<Parameters<ScheduledExecutionRunner['resolveReview']>[0], 'queueName'>): Promise<void> {\n this.scheduledRunner ??= new ScheduledExecutionRunner(this.jobStatusTracking, this.logger, this.payloadStorage, {\n started: () => this.shutdownManager.jobStarted(), completed: () => this.shutdownManager.jobCompleted(),\n });\n await this.scheduledRunner.resolveReview({ ...input,\n queueName: QueueNamingUtils.buildQueueName(this.platformApplicationId, 'scheduled') }, job => this.resolveScheduledContract(job));\n }\n\n /**\n * Get worker identity for external access.\n */\n getWorkerIdentity(): WorkerIdentity {\n return { ...this.workerIdentity };\n }\n\n /**\n * Check if consumer is running.\n */\n isRunning(): boolean {\n return this.isConsuming;\n }\n}\n"]}
1
+ {"version":3,"file":"job-consumer.backend.service.js","sourceRoot":"","sources":["../../../../src/queue/job-consumer.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Job Consumer Backend Service\n *\n * Handles the complete message lifecycle:\n * - Consumes messages from RabbitMQ\n * - Executes jobs via JobExecutorBackendService\n * - Handles retry logic with exponential backoff\n * - Sends RPC replies for QUEUED mode\n * - Tracks job status\n * - Acknowledges/rejects messages appropriately\n */\n\nimport { injectable, inject } from 'inversify';\nimport { z } from 'zod';\nimport { v4 as uuidv4 } from 'uuid';\nimport * as os from 'os';\nimport type { ConsumeMessage, Channel } from 'amqplib';\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport { LoggerService } from '~wildo-backend-lib/monitoring/logger/services/logger.service';\nimport { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';\nimport { ErrorBuilderBackendService } from '~wildo-backend-lib/errors/services/error-builder.backend.service';\nimport { projectWildoBackendErrorLogFields, describeCaughtError, projectCaughtErrorLogFields } from '~wildo-backend-lib/errors/utils/error-log-level-classification.backend.utils';\nimport { adoptCorrelationIdIntoCurrentFrame, runInFreshRequestContextIfAbsent } from '~wildo-backend-lib/runtime/models/request-context.als.backend';\nimport { runWithJobWorkAttributionFrame } from '~wildo-backend-lib/runtime/models/work-attribution.als.backend';\nimport type { QueueAdapter } from './adapters/queue-adapter.backend.interface';\nimport type { MessageHandler } from './adapters/queue-adapter.backend.interface';\nimport { ScheduledExecutionRunner, type ScheduledExecutionContract } from './scheduled-execution.backend.service';\nimport { JobExecutorBackendService } from './job-executor.backend.service';\nimport { JobPayloadStorageBackendService } from './job-payload-storage.backend.service';\nimport { JobStatusTrackingBackendService } from './job-status-tracking.backend.service';\nimport { JobCompletionRegistryBackendService } from './job-completion-registry.backend.service';\nimport { WorkerShutdownManagerBackendService } from './worker-shutdown-manager.backend.service';\nimport { ScheduledMessageVerifierBackendService, ScheduledDeliveryVerdict } from './scheduled-message-verifier.backend.service';\nimport {\n JobPayload,\n JobPayloadSchema,\n type ResourceConfiguration_OperationPath,\n JobType,\n ResourceSerializationUtils,\n ResourcesConfig_OperationPathUtils,\n JobResult,\n JobStatus,\n JobExecutionStatus,\n type JobExecution,\n isWildoBackendError,\n JobRetryUtils,\n QueueNamingUtils,\n QueueVariant,\n QUEUE_RETRY_DEFAULTS,\n ErrorHandling_Strategy,\n QueueRetryConfig,\n ErrorType,\n ErrorCustomMessageReference,\n ErrorSeverity,\n} from '@wildo-ai/saas-models';\n\n/**\n * Worker identification for tracking.\n */\ninterface WorkerIdentity {\n workerId: string;\n hostname: string;\n pid: number;\n}\n\n/**\n * Consumer configuration.\n */\nexport interface JobConsumerConfig {\n /** Whether to enable retry logic */\n enableRetry?: boolean;\n /** Default retry configuration */\n retryConfig?: Partial<QueueRetryConfig>;\n}\n\nconst DEFAULT_CONSUMER_CONFIG: JobConsumerConfig = {\n enableRetry: true,\n retryConfig: QUEUE_RETRY_DEFAULTS,\n};\n\n@injectable()\nexport class JobConsumerBackendService {\n protected logDebug: (message: string, context?: Record<string, unknown>) => void;\n private _applicationId: string | null = null;\n private readonly workerIdentity: WorkerIdentity;\n private isConsuming = false;\n private scheduledRunner?: ScheduledExecutionRunner;\n private consumingQueues: string[] = [];\n\n constructor(\n @inject(SAAS_SERVICE_TYPES.AppConfigService)\n private readonly appConfigService: AppConfigurationService,\n @inject(SAAS_SERVICE_TYPES.RabbitMQAdapterService)\n private readonly adapter: QueueAdapter,\n @inject(SAAS_SERVICE_TYPES.JobExecutorBackendService)\n private readonly jobExecutor: JobExecutorBackendService,\n @inject(SAAS_SERVICE_TYPES.JobStatusTrackingService)\n private readonly jobStatusTracking: JobStatusTrackingBackendService,\n @inject(SAAS_SERVICE_TYPES.JobCompletionRegistryService)\n private readonly completionRegistry: JobCompletionRegistryBackendService,\n @inject(SAAS_SERVICE_TYPES.WorkerShutdownManagerService)\n private readonly shutdownManager: WorkerShutdownManagerBackendService,\n @inject(SAAS_SERVICE_TYPES.ScheduledMessageVerifierService)\n private readonly scheduledMessageVerifier: ScheduledMessageVerifierBackendService,\n @inject(SAAS_SERVICE_TYPES.Logger)\n private readonly logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.ErrorBuilderService)\n private readonly errorBuilder: ErrorBuilderBackendService,\n @inject(SAAS_SERVICE_TYPES.JobPayloadStorageService)\n private readonly payloadStorage: JobPayloadStorageBackendService,\n ) {\n this.logDebug = this.logger.debugByType('JobConsumerBackendService');\n this.logger.setDebugTypeLogging('JobConsumerBackendService', false);\n // Lazy-load applicationId to avoid accessing config before initialization\n this.workerIdentity = {\n workerId: uuidv4(),\n hostname: os.hostname(),\n pid: process.pid,\n };\n }\n\n /**\n * The PLATFORM's id for this application — what every queue name is built from and what the\n * crontabs-manager signs into a scheduled message. Lazy, to avoid reading config in the constructor.\n *\n * This consumer ADDRESSES with it and never stamps it: the job rows and stored payloads are\n * anchored by `JobStatusTrackingBackendService` and `JobPayloadStorageBackendService` to the\n * application RECORD id (`applications._id`), which they resolve themselves. Until 2026-09-18 this\n * one value was handed to the scheduled runner for its row scans as well, and it \"worked\" only\n * because the rows had been stamped from the same wire value — the defect #1296 records.\n */\n private get platformApplicationId(): string {\n if (!this._applicationId) {\n this._applicationId = this.appConfigService.applicationId;\n }\n return this._applicationId;\n }\n\n /**\n * Start consuming from all operation and scheduled queues.\n */\n async startConsuming(config: JobConsumerConfig = {}): Promise<void> {\n if (this.isConsuming) {\n this.logger.warn('Consumer already running');\n return;\n }\n\n const mergedConfig = { ...DEFAULT_CONSUMER_CONFIG, ...config };\n\n // Connect to RabbitMQ\n await this.adapter.connect();\n\n // Start consuming from operations queues (normal and priority variant)\n const operationsQueueConfigs = [\n { category: 'operations', variant: undefined },\n { category: 'operations', variant: QueueVariant.PRIORITY },\n ];\n\n for (const queueConfig of operationsQueueConfigs) {\n const queueName = QueueNamingUtils.buildQueueName(\n this.platformApplicationId,\n queueConfig.category,\n queueConfig.variant\n );\n\n // Create handler that matches MessageHandler signature\n const handler: MessageHandler = async (msg: ConsumeMessage, channel: Channel) => {\n // Phase 1 — each consumed job runs in its own correlation frame (fresh id). Phase 6 will seed\n // it from the enqueuing request's originCorrelationId carried on the job payload.\n await runInFreshRequestContextIfAbsent(() => this.handleMessage(msg, channel, mergedConfig));\n };\n\n await this.adapter.consume(queueName, handler);\n this.consumingQueues.push(queueName);\n\n this.logDebug('Started consuming from queue', {\n queueName,\n workerId: this.workerIdentity.workerId,\n });\n }\n\n // Start consuming from scheduled queue (JWT-signed messages from crontabs-manager)\n const scheduledQueueName = QueueNamingUtils.buildQueueName(this.platformApplicationId, 'scheduled');\n\n const scheduledHandler: MessageHandler = async (msg: ConsumeMessage, channel: Channel) => {\n // Phase 1 — each cron tick (scheduled-queue message) runs in its own correlation frame.\n await runInFreshRequestContextIfAbsent(() => this.handleScheduledMessage(msg, channel, mergedConfig));\n };\n\n this.scheduledRunner = new ScheduledExecutionRunner(this.jobStatusTracking, this.logger, this.payloadStorage, {\n started: () => this.shutdownManager.jobStarted(), completed: () => this.shutdownManager.jobCompleted(),\n });\n await this.diagnoseScheduledEvidenceTargets();\n await this.adapter.consume(scheduledQueueName, scheduledHandler);\n this.scheduledRunner.start(scheduledQueueName, job => this.resolveScheduledContract(job));\n this.consumingQueues.push(scheduledQueueName);\n\n this.logDebug('Started consuming from scheduled queue', {\n queueName: scheduledQueueName,\n workerId: this.workerIdentity.workerId,\n });\n\n this.isConsuming = true;\n this.logDebug('Job consumer started', {\n workerId: this.workerIdentity.workerId,\n queues: this.consumingQueues.length,\n });\n }\n\n /**\n * Stop consuming and close connections.\n */\n async stopConsuming(): Promise<void> {\n this.scheduledRunner?.stop();\n if (!this.isConsuming) {\n return;\n }\n\n // Cancel all consumers\n for (const queueName of this.consumingQueues) {\n await this.adapter.cancelConsumer(queueName);\n }\n\n this.consumingQueues = [];\n this.isConsuming = false;\n\n this.logDebug('Job consumer stopped', {\n workerId: this.workerIdentity.workerId,\n });\n }\n\n /**\n * Handle a single message from the queue.\n */\n private async handleMessage(\n msg: ConsumeMessage,\n channel: Channel,\n config: JobConsumerConfig\n ): Promise<void> {\n let job: JobPayload;\n\n try {\n job = JSON.parse(msg.content.toString());\n } catch (parseError) {\n this.logger.error('Failed to parse job message', {\n ...projectCaughtErrorLogFields(parseError),\n });\n // Invalid message - don't requeue\n channel.nack(msg, false, false);\n return;\n }\n\n // Phase 6 — this job belongs to the trace of the request that enqueued it: adopt that request's\n // originCorrelationId into the (freshly-minted) consume frame, so every log line + audit row this\n // job produces on the worker carries the originating request's correlationId. Absent/malformed →\n // the frame keeps its fresh id (a job with no originating request stays independently traceable).\n adoptCorrelationIdIntoCurrentFrame(job.originCorrelationId);\n\n const startTime = Date.now();\n const { replyTo, correlationId } = msg.properties;\n\n // Track in-flight job for graceful shutdown\n this.shutdownManager.jobStarted();\n\n this.logDebug('Processing job', {\n jobId: job.jobId,\n jobType: job.jobType,\n priority: job.priority,\n retryCount: job.retryCount ?? 0,\n });\n\n try {\n // Mark job as started\n await this.jobStatusTracking.markStarted(job.jobId, this.workerIdentity.workerId, job.retryCount ?? 0);\n\n // Execute the job - returns JobResult which may indicate success OR failure\n // The executor catches all errors and returns a result with status\n // #1598 F14 (I7): reopen the work frame the job was enqueued inside, beside the correlation id adopted\n // above, so a model call the job makes is attributed to the same tenant and case. A payload without one\n // runs OUTSIDE any frame, whatever this continuation carries (see `runWithJobWorkAttributionFrame`).\n const result = await runWithJobWorkAttributionFrame(job.attribution, () => this.jobExecutor.execute(job));\n\n // Check if job failed (executor returns result with FAILED status, doesn't throw)\n if (result.status === JobStatus.FAILED) {\n // Convert the error result to proper retry handling\n await this.handleJobFailure(job, result, msg, channel, config, startTime);\n return;\n }\n\n await this.finishJob(job, result, msg, channel);\n\n this.logDebug('Job completed successfully', {\n jobId: job.jobId,\n durationMs: Date.now() - startTime,\n });\n\n } catch (error) {\n // This catch block handles unexpected errors before a final outcome (e.g., from markStarted)\n // NOT job execution errors (those are returned by executor as FAILED status)\n await this.handleJobError(job, error, msg, channel, config, startTime);\n } finally {\n // Always track job completion for graceful shutdown\n this.shutdownManager.jobCompleted();\n }\n }\n\n /**\n * Process-local completion is best effort, never a new attempt of the business\n * operation. Called only for success or a terminal failure, not retry handoff.\n * Failed jobs can contain malformed identity, so decoding must not obstruct\n * dead-letter settlement. Such jobs can reach general/type handlers, but never\n * a resource selector without the required typed identity (see #768).\n */\n private async dispatchCompletion(job: JobPayload, result: JobResult): Promise<void> {\n const jobType = z.enum(JobType).safeParse(job.jobType);\n if (!jobType.success) {\n this.logger.error('Completion skipped for invalid job type', { jobId: job.jobId, jobType: job.jobType });\n return;\n }\n let operationPath: ResourceConfiguration_OperationPath<any, any> | undefined;\n try {\n operationPath = jobType.data === JobType.RESOURCE_OPERATION && job.operationPathJson\n ? ResourceSerializationUtils.deserializeOperationPath(job.operationPathJson)\n : jobType.data === JobType.SCHEDULED_CRON && job.operationPathKey\n ? ResourcesConfig_OperationPathUtils.parseOperationPathKey(job.operationPathKey)\n : undefined;\n } catch (error) {\n this.logger.error('Completion resource identity unavailable', { jobId: job.jobId, ...projectCaughtErrorLogFields(error) });\n }\n try {\n await this.completionRegistry.dispatch({ result, jobType: jobType.data, operationPath, operationPathKey: job.operationPathKey, batchRef: job.batchRef });\n } catch (error) {\n // The registry already isolates individual handler failures. Guard its\n // dispatch boundary too: notification infrastructure must not replay work.\n this.logger.error('Completion dispatch failed', { jobId: job.jobId, ...projectCaughtErrorLogFields(error) });\n }\n }\n\n /**\n * Once execution succeeds or retry eligibility says terminal, failures in\n * tracking, callbacks or an RPC reply must not reclassify the outcome.\n * Settlement can itself fail on a closed channel; the broker then owns any\n * redelivery. Local callbacks may repeat on redelivery; they are not durable receipts.\n */\n private async finishJob(job: JobPayload, result: JobResult, msg: ConsumeMessage, channel: Channel): Promise<void> {\n const succeeded = result.status === JobStatus.COMPLETED;\n try {\n if (succeeded) await this.jobStatusTracking.markCompleted(job.jobId, job.retryCount ?? 0);\n else await this.jobStatusTracking.recordFailure(job.jobId, { status: JobExecutionStatus.DEAD_LETTER, deliveredRetryCount: job.retryCount ?? 0, error: result.error });\n } catch (error) {\n this.logger.error('Finished job tracking failed', { jobId: job.jobId, ...projectCaughtErrorLogFields(error) });\n }\n await this.dispatchCompletion(job, result);\n const { replyTo, correlationId } = msg.properties;\n if (replyTo && correlationId) {\n try {\n await this.adapter.publishResult(replyTo, correlationId, result);\n } catch (error) {\n this.logger.error('Finished job reply failed', { jobId: job.jobId, ...projectCaughtErrorLogFields(error) });\n }\n }\n try {\n if (succeeded) channel.ack(msg);\n // Reject without requeue; the queue's DLX owns parking this delivery.\n else channel.nack(msg, false, false);\n } catch (error) {\n this.logger.error('Finished job settlement failed', { jobId: job.jobId, ...projectCaughtErrorLogFields(error) });\n }\n }\n\n /**\n * Handle job failure when executor returns FAILED status (not an exception).\n * The executor catches errors and returns a JobResult with status FAILED.\n */\n private async handleJobFailure(\n job: JobPayload,\n result: JobResult,\n msg: ConsumeMessage,\n channel: Channel,\n config: JobConsumerConfig,\n startTime: number\n ): Promise<void> {\n const currentRetry = job.retryCount ?? 0;\n const maxRetries = job.maxRetries ?? config.retryConfig?.maxRetries ?? QUEUE_RETRY_DEFAULTS.maxRetries;\n const { replyTo, correlationId } = msg.properties;\n\n // Extract error handling strategy from the error\n const errorStrategy = result.error?.errorHandlingStrategy;\n const shouldRetry = config.enableRetry &&\n this.shouldRetryFromStrategy(errorStrategy, currentRetry, maxRetries);\n\n if (shouldRetry) {\n // Resolve backoff from the job's per-operation retryConfig, falling back to\n // the consumer config then the framework defaults (per-field, so a partial\n // authored retryConfig still gets sane values for the axes it omits).\n const backoff = job.retryConfig;\n const retryConfig: QueueRetryConfig = {\n retryPolicy: backoff?.retryPolicy ?? config.retryConfig?.retryPolicy ?? QUEUE_RETRY_DEFAULTS.retryPolicy,\n maxRetries: maxRetries,\n baseDelayMs: backoff?.baseDelayMs ?? config.retryConfig?.baseDelayMs ?? QUEUE_RETRY_DEFAULTS.baseDelayMs,\n maxDelayMs: backoff?.maxDelayMs ?? config.retryConfig?.maxDelayMs ?? QUEUE_RETRY_DEFAULTS.maxDelayMs,\n timeoutMs: job.timeoutMs ?? config.retryConfig?.timeoutMs ?? QUEUE_RETRY_DEFAULTS.timeoutMs,\n };\n\n const delay = JobRetryUtils.calculateDelay(retryConfig, currentRetry);\n\n // Create updated job with incremented retry count\n const retryJob: JobPayload = {\n ...job,\n retryCount: currentRetry + 1,\n };\n\n // Durable backoff: hand the retry to the broker (delay queue holds it, then\n // dead-letters it back) instead of an in-process setTimeout that would be\n // lost if this worker crashes during the wait.\n const operationsQueue = QueueNamingUtils.buildQueueName(this.platformApplicationId, 'operations');\n try {\n await this.adapter.scheduleDelayedRetry(operationsQueue, retryJob, delay, {\n replyTo,\n correlationId,\n });\n } catch (scheduleError) {\n // Could not hand the retry to the broker — requeue the ORIGINAL (do not\n // ACK) so it is redelivered rather than silently lost.\n this.logger.error('Failed to schedule durable retry; requeueing original', {\n jobId: job.jobId,\n ...projectCaughtErrorLogFields(scheduleError),\n });\n channel.nack(msg, false, true);\n return;\n }\n\n // The retry is already broker-owned. Neither tracking nor ACK failure may\n // return to execution-error handling and publish a second retry.\n try {\n await this.jobStatusTracking.recordFailure(job.jobId, {\n status: JobExecutionStatus.RETRYING, deliveredRetryCount: currentRetry, error: result.error,\n });\n } catch (trackingError) {\n this.logger.error('Failed to record retry outcome', { jobId: job.jobId, ...projectCaughtErrorLogFields(trackingError) });\n }\n try { channel.ack(msg); } catch (settlementError) {\n this.logger.error('Retry original settlement failed', { jobId: job.jobId, ...projectCaughtErrorLogFields(settlementError) });\n }\n\n this.logger.warn('Job retry scheduled (durable delay queue)', {\n jobId: job.jobId,\n retryCount: currentRetry + 1,\n maxRetries,\n delayMs: delay,\n // The queue is a non-HTTP boundary and owns its own operational level (a\n // scheduled retry is a `warn`, not classified from the error's severity).\n // Reuse the canonical field projection to restore the full error detail\n // that no longer self-logs at construction.\n ...(result.error ? projectWildoBackendErrorLogFields(result.error) : {}),\n });\n\n } else {\n await this.finishJob(job, result, msg, channel);\n\n this.logger.error('Job failed permanently', {\n jobId: job.jobId,\n retryCount: currentRetry,\n maxRetries,\n // Permanent (dead-lettered) failure is operationally an `error`\n // regardless of the underlying error's business severity, so the level\n // stays explicit; the projection restores the full error detail (type,\n // status, context) and the stack.\n ...(result.error ? projectWildoBackendErrorLogFields(result.error) : {}),\n ...(result.error?.stack ? { stack: result.error.stack } : {}),\n });\n }\n }\n\n /**\n * Check if retry should happen based on error strategy.\n */\n private shouldRetryFromStrategy(\n strategy: ErrorHandling_Strategy | undefined,\n currentRetry: number,\n maxRetries: number\n ): boolean {\n // Check retry count limit\n if (currentRetry >= maxRetries) {\n return false;\n }\n\n // Only retry if strategy is explicitly RETRY or undefined (default to retry)\n return strategy === undefined || strategy === ErrorHandling_Strategy.RETRY;\n }\n\n /**\n * Handle unexpected errors (not job execution failures).\n * This handles errors from execution and pre-execution tracking.\n * Terminal notification and settlement failures are isolated by finishJob.\n */\n private async handleJobError(\n job: JobPayload,\n error: unknown,\n msg: ConsumeMessage,\n channel: Channel,\n config: JobConsumerConfig,\n startTime: number\n ): Promise<void> {\n // Returned and thrown failures use one retry decision and one tracking path.\n const failure = isWildoBackendError(error) ? error : {\n type: ErrorType.INTERNAL, severity: ErrorSeverity.HIGH, timestamp: new Date(),\n context: { message: describeCaughtError(error) }, backendActions: [],\n customMessageReference: ErrorCustomMessageReference.INTERNAL, statusCode: 500,\n };\n await this.handleJobFailure(job, {\n jobId: job.jobId, status: JobStatus.FAILED, error: failure,\n startedAt: new Date(startTime), completedAt: new Date(), durationMs: Date.now() - startTime,\n }, msg, channel, config, startTime);\n }\n\n /** Registry resolution is side-effect free: diagnose misspelled targets before accepting scheduled deliveries. */\n private async diagnoseScheduledEvidenceTargets(): Promise<void> {\n const configured = this.appConfigService.config?.scheduledEvidence;\n if (!configured) return;\n for (const target of [\n ...Object.keys(configured.batches ?? {}).map(batchRef => ({ batchRef })),\n ...Object.keys(configured.operations ?? {}).map(operationPathKey => ({ operationPathKey })),\n ]) {\n const probe = JobPayloadSchema.parse({ jobId: uuidv4(), applicationId: this.platformApplicationId,\n jobType: JobType.SCHEDULED_CRON, createdAt: new Date(), ...target });\n if (!await this.jobExecutor.getScheduledContract(probe)) {\n this.logger.warn('Scheduled evidence policy has no registered executable target; no evidence will be collected for this key', target);\n }\n }\n for (const minionName of Object.keys(configured.minions ?? {})) {\n if (!Object.hasOwn(this.appConfigService.config.minions ?? {}, minionName)) {\n this.logger.warn('Scheduled evidence policy names an undeclared minion; no evidence will be collected for this key', { minionName });\n }\n }\n }\n\n /** One resolver owns policy selection for first delivery, scanner recovery and operator review. */\n private async resolveScheduledContract(job: JobPayload): Promise<ScheduledExecutionContract | undefined> {\n if (Boolean(job.batchRef) === Boolean(job.operationPathKey)) {\n this.logger.warn('Scheduled evidence target is ambiguous or missing', { jobId: job.jobId });\n return undefined;\n }\n const contract = await this.jobExecutor.getScheduledContract(job);\n if (!contract) return undefined;\n const configured = this.appConfigService.config?.scheduledEvidence;\n const policies = job.batchRef ? configured?.batches : configured?.operations;\n const target = job.batchRef ?? job.operationPathKey!;\n const evidencePolicy = policies && Object.hasOwn(policies, target) ? policies[target] : undefined;\n return { ...contract, evidencePolicy };\n }\n\n /**\n * Handle a scheduled message (JWT-signed from crontabs-batches-manager).\n */\n private async handleScheduledMessage(\n msg: ConsumeMessage,\n channel: Channel,\n config: JobConsumerConfig\n ): Promise<void> {\n this.shutdownManager.jobStarted();\n let accepted = false;\n let admitted: JobExecution | undefined;\n try {\n const delivery = await this.scheduledMessageVerifier.verifyAndConvert(msg.content.toString());\n const job = delivery.value;\n // A WIRE check: the crontabs-manager signs the platform id it registered this application\n // under, so the platform id is the right thing to compare the message against. The row the\n // receipt then creates is anchored by the tracker to the record id, not to this value. It\n // applies to a LATE delivery too: a genuine token addressed to another application is foreign\n // whether or not it is on time, and recording it here would plant another tenant's miss.\n if (job.applicationId !== this.platformApplicationId) throw this.errorBuilder.buildError(\n ErrorType.AUTHENTICATION, undefined, {\n customMessageReference: ErrorCustomMessageReference.AUTHENTICATION_INVALID_TOKEN,\n context: { reason: 'Scheduled message targets a different application' },\n },\n );\n this.scheduledRunner ??= new ScheduledExecutionRunner(this.jobStatusTracking, this.logger, this.payloadStorage, {\n started: () => this.shutdownManager.jobStarted(), completed: () => this.shutdownManager.jobCompleted(),\n });\n const resolveContract = (payload: JobPayload) => this.resolveScheduledContract(payload);\n const queueName = QueueNamingUtils.buildQueueName(this.platformApplicationId, 'scheduled');\n if (delivery.verdict === ScheduledDeliveryVerdict.LATE) {\n // Genuine but past its admission deadline: the occurrence was missed — usually because nothing\n // consumed this queue, though the scheduler can share the delay (see `ScheduledDeliveryLateness`).\n // Record the miss and acknowledge; the runner reports the whole drain ONCE\n // (#2212). Only a delivery it could not record is dead-lettered, so its copy survives.\n accepted = await this.scheduledRunner.recordLateDelivery(job, queueName, resolveContract, delivery.lateness);\n } else {\n // Durable receipt, then acknowledge, THEN run: the delivery is released as soon as the occurrence\n // is in the database, so a long run can no longer hold every later delivery unreceived until its\n // five-minute token lapses (`ScheduledExecutionRunner.admit`).\n admitted = await this.scheduledRunner.admit(job, queueName, resolveContract);\n accepted = true;\n }\n } catch (error) {\n this.logger.error('Scheduled receipt failed', { ...projectCaughtErrorLogFields(error) });\n }\n // Settlement cannot re-enter business execution. Durable recovery owns accepted failures.\n try {\n if (accepted) channel.ack(msg);\n else channel.nack(msg, false, false);\n } catch (error) {\n this.logger.error('Scheduled receipt settlement failed', { ...projectCaughtErrorLogFields(error) });\n } finally { this.shutdownManager.jobCompleted(); }\n // Started only after the delivery is settled; the runner tracks the run's own activity.\n if (admitted && this.scheduledRunner) this.scheduledRunner.launch(admitted, payload => this.resolveScheduledContract(payload));\n }\n\n /** Trusted backend administration entry: the caller authorizes its operator and supplies attribution. */\n async resolveScheduledReview(input: Omit<Parameters<ScheduledExecutionRunner['resolveReview']>[0], 'queueName'>): Promise<void> {\n this.scheduledRunner ??= new ScheduledExecutionRunner(this.jobStatusTracking, this.logger, this.payloadStorage, {\n started: () => this.shutdownManager.jobStarted(), completed: () => this.shutdownManager.jobCompleted(),\n });\n await this.scheduledRunner.resolveReview({ ...input,\n queueName: QueueNamingUtils.buildQueueName(this.platformApplicationId, 'scheduled') }, job => this.resolveScheduledContract(job));\n }\n\n /**\n * Get worker identity for external access.\n */\n getWorkerIdentity(): WorkerIdentity {\n return { ...this.workerIdentity };\n }\n\n /**\n * Check if consumer is running.\n */\n isRunning(): boolean {\n return this.isConsuming;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"job-status-tracking.backend.service.d.ts","sourceRoot":"","sources":["../../../../src/queue/job-status-tracking.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,OAAO,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAC;AAE7F,OAAO,EAAE,yCAAyC,EAAE,MAAM,qGAAqG,CAAC;AAChK,OAAO,EAAE,qCAAqC,EAAE,MAAM,+EAA+E,CAAC;AACtI,OAAO,EAAE,iCAAiC,EAAE,MAAM,+EAA+E,CAAC;AAClI,OAAO,EAAE,iBAAiB,EAAE,MAAM,qEAAqE,CAAC;AACxG,OAAO,EACL,UAAU,EACV,YAAY,EACZ,kBAAkB,EAElB,uBAAuB,EAQvB,gBAAgB,EAEjB,MAAM,uBAAuB,CAAC;AAG/B,gGAAgG;AAChG,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,kBAAkB,CAAC,QAAQ,GAAG,kBAAkB,CAAC,MAAM,GAAG,kBAAkB,CAAC,WAAW,CAAC;IACjG,2FAA2F;IAC3F,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,qBACa,+BAA+B;IAKxC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,oBAAoB;IAErC,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IAExC,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IAVtC,SAAS,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;gBAI9D,MAAM,EAAE,aAAa,EAErB,oBAAoB,EAAE,yCAAyC,EAE/D,uBAAuB,EAAE,qCAAqC,EAE9D,mBAAmB,EAAE,iCAAiC;IAMzE;;OAEG;IACH,MAAM,KAAK,YAAY,IAAI,gBAAgB,CAE1C;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACU,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC;IAItD;;;OAGG;IACH,OAAO,KAAK,sBAAsB,GAKjC;IAED;;;;;;;;;OASG;YACW,qBAAqB;IASnC;;;;;;;OAOG;IACG,eAAe,CACnB,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,iBAAiB,EAC3B,cAAc,CAAC,EAAE,uBAAuB,GACvC,OAAO,CAAC,MAAM,CAAC;IA+DlB;;;;;OAKG;IACG,wBAAwB,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC;IAwDnI;;;;OAIG;IACG,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB,EAAE,KAAK,GAAE,OAAO,CAAC,YAAY,CAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAYrK;;;;;OAKG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAY7E,gGAAgG;IAC1F,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAWrF,4GAA4G;IACtG,+BAA+B,CACnC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,EAChG,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,SAAQ,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,YAAY,EAAE,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IAwBhG;;;;;;;OAOG;IACG,WAAW,CACf,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC;IAqBhB;;;;;;;OAOG;IACG,aAAa,CACjB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,sBAAsB,CAAC,EAAE,MAAM,EAC/B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC;IAkChB;;;;;;;;OAQG;IACG,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IA0C1G;;;;;OAKG;IACG,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB9E;;;;;;;OAOG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;CAW3F"}
1
+ {"version":3,"file":"job-status-tracking.backend.service.d.ts","sourceRoot":"","sources":["../../../../src/queue/job-status-tracking.backend.service.ts"],"names":[],"mappings":"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"}
@@ -191,8 +191,11 @@ let JobStatusTrackingBackendService = class JobStatusTrackingBackendService {
191
191
  return row;
192
192
  const terminal = row.status === JobExecutionStatus.COMPLETED || row.status === JobExecutionStatus.FAILED
193
193
  || row.status === JobExecutionStatus.DEAD_LETTER || row.status === JobExecutionStatus.CANCELLED;
194
+ // `lateness` describes a delivery THIS receipt could not admit; a legacy row it adopts has
195
+ // its own, unknown history, so the late-delivery marker must not be stamped onto it (#2212).
196
+ const { lateness: _receiptLateness, ...adoptableState } = scheduledState;
194
197
  const adoptedState = {
195
- ...scheduledState,
198
+ ...adoptableState,
196
199
  phase: terminal ? ScheduledExecutionPhase.FINISHED : ScheduledExecutionPhase.REVIEW,
197
200
  attemptCount: Math.max(1, scheduledState.attemptCount),
198
201
  attempts: [],
@@ -1 +1 @@
1
- {"version":3,"file":"job-status-tracking.backend.service.js","sourceRoot":"","sources":["../../../../src/queue/job-status-tracking.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Job Status Tracking Backend Service\n *\n * Tracks job lifecycle through the configured resource repository for observability and querying.\n *\n * Uses the same pattern as FilesBackendService:\n * - Get repository via RepositoriesRegistryHandlerBackendService\n * - Create internal execution context via\n * ExecutionContextCreatorBackendService.createForInternalRepositoryOperation\n * (the variant-correct, REPOSITORY_ONLY-preferred seam)\n * - Use direct repository methods (create, read, update)\n *\n * This ensures proper authorization flow while keeping the implementation simple.\n */\n\nimport { injectable, inject } from 'inversify';\nimport * as os from 'os';\nimport { isDeepStrictEqual } from 'node:util';\nimport { ORDINARY_JOB_EXECUTION_RETENTION_MS } from './job-execution-retention.mongo';\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport { LoggerService } from '~wildo-backend-lib/monitoring/logger/services/logger.service';\nimport type { BackendResourceRepository } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport { ExecutionContextCreatorBackendService } from '~wildo-backend-lib/runtime/services/execution-context-creator.backend.service';\nimport { ApplicationIdentityBackendService } from '~wildo-backend-lib/applications/services/application-identity.backend.service';\nimport { RepositoryOptions } from '~wildo-backend-lib/base-classes/models/repositories.backend.schemas';\nimport {\n JobPayload,\n JobExecution,\n JobExecutionStatus,\n JobType,\n ScheduledExecutionState,\n ScheduledExecutionStateSchema,\n ScheduledExecutionPhase,\n ResourceSerializationUtils,\n isWildoBackendError,\n ErrorType,\n ErrorSeverity,\n ErrorCustomMessageReference,\n CoreResourceType,\n CoreResourceOperation,\n} from '@wildo-ai/saas-models';\nimport { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\n\n/** The consumer supplies its chosen settlement, never a budget for the tracker to interpret. */\nexport interface JobFailureOutcome {\n status: JobExecutionStatus.RETRYING | JobExecutionStatus.FAILED | JobExecutionStatus.DEAD_LETTER;\n /** Zero-based retry index of the delivery that failed; RETRYING records the next index. */\n deliveredRetryCount: number;\n error: unknown;\n}\n\n@injectable()\nexport class JobStatusTrackingBackendService {\n protected logDebug: (message: string, context?: Record<string, unknown>) => void;\n\n constructor(\n @inject(SAAS_SERVICE_TYPES.Logger)\n private readonly logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService)\n private readonly repositoriesRegistry: RepositoriesRegistryHandlerBackendService,\n @inject(SAAS_SERVICE_TYPES.ExecutionContextCreatorBackendService)\n private readonly executionContextCreator: ExecutionContextCreatorBackendService,\n @inject(SAAS_SERVICE_TYPES.ApplicationIdentityService)\n private readonly applicationIdentity: ApplicationIdentityBackendService,\n ) {\n this.logDebug = this.logger.debugByType('JobStatusTrackingBackendService');\n this.logger.setDebugTypeLogging('JobStatusTrackingBackendService', false);\n }\n\n /**\n * Get the resource type for this service.\n */\n static get resourceType(): CoreResourceType {\n return CoreResourceType.JOB_EXECUTIONS;\n }\n\n /**\n * The id every `jobExecutions` row this service writes is anchored to, and the only id its\n * application-scoped scans filter on: `applications._id`, the APPLICATION RESOURCE SCOPE's key.\n *\n * ## The wire / row boundary this service IS\n *\n * A job travels on the wire — a RabbitMQ message, or a JWT signed by the crontabs-manager — carrying\n * `JobPayload.applicationId`, and on the wire that value is the PLATFORM's id: it is what the queue\n * names are built from, what the crontabs-manager knows this application as, and what every consumer\n * verifies a scheduled message against before accepting it. That is addressing, and it is correct.\n *\n * The moment the payload becomes a durable ROW it stops being an address and becomes an attribution\n * that scope-filtered reads will match against, and there the platform id is the wrong identity: no\n * scope predicate matches it. Until 2026-09-18 `createJobRecord` copied the wire value into the row,\n * and Wonder Todos held 10,314 `jobexecutions` and 3,595 `jobpayloadstorage` rows under the platform\n * id while every other `applicationId` column in the database carried the record id. This service is\n * the boundary: the PAYLOAD keeps the platform id, the ROW is stamped here from the canonical\n * identity, and nothing outside this file gets to choose.\n *\n * Public rather than private because the scheduled runner's operator-review door checks a row's\n * ownership against it; every caller that needs the row identity asks here and passes nothing in.\n */\n public async canonicalApplicationId(): Promise<string> {\n return this.applicationIdentity.getCanonicalApplicationId();\n }\n\n /**\n * Get repository for job executions.\n * Lazy getter to ensure repository is initialized.\n */\n private get jobExecutionRepository(): BackendResourceRepository<any, any, any> {\n return this.repositoriesRegistry.getRepositoryOrThrow(\n CoreResourceType.JOB_EXECUTIONS,\n {} as ExecutionContext<any>\n );\n }\n\n /**\n * Create an internal execution context for job tracking operations.\n *\n * `JOB_EXECUTIONS` declares only `REPOSITORY_ONLY` variants (managed off the\n * HTTP surface). Resolution goes through the shared internal-repository builder\n * — exactly as `FilesBackendService` does — which resolves the operation path\n * `REPOSITORY_ONLY`-preferred with a URL fallback. The URL-only\n * `getOperationPathDefault` filters for `API_CALL` / `API_CALL_WITH_CALLBACK`\n * and would throw `RESOURCES_REGISTRY_OPERATION_PATH_NOT_FOUND` for these ops.\n */\n private async createInternalContext(\n operation: CoreResourceOperation\n ): Promise<ExecutionContext<any>> {\n return this.executionContextCreator.createForInternalRepositoryOperation({\n resourceType: CoreResourceType.JOB_EXECUTIONS,\n operationIdentifier: operation,\n });\n }\n\n /**\n * Create job execution record when job is enqueued.\n *\n * @param job - Job payload with metadata\n * @param queueName - Name of the target queue\n * @param options - Optional repository options (for transactions)\n * @returns Persisted record ID, falling back to its job ID\n */\n async createJobRecord(\n job: JobPayload,\n queueName: string,\n options?: RepositoryOptions,\n scheduledState?: ScheduledExecutionState\n ): Promise<string> {\n // Extract identifiers from execution context for querying\n let organizationId: string | undefined;\n let userId: string | undefined;\n\n if (job.executionContextJson) {\n try {\n const ctxData = ResourceSerializationUtils.deserializeExecutionContextData(job.executionContextJson);\n organizationId = ctxData.initiatorIds?.organizationId;\n userId = ctxData.initiatorIds?.userId;\n } catch {\n this.logger.warn('Failed to deserialize execution context for job tracking', { jobId: job.jobId });\n }\n }\n\n const now = new Date();\n\n // Build record data\n const createData: Partial<JobExecution> = {\n jobId: job.jobId,\n // The ROW's identity, never the payload's: `job.applicationId` is the platform id the wire is\n // addressed with, and copying it here is what anchored 10,314 rows to an id no scope predicate\n // matches. See `canonicalApplicationId()` for the boundary this line enforces.\n applicationId: await this.canonicalApplicationId(),\n jobType: job.jobType,\n operationPathKey: job.operationPathKey,\n batchRef: job.batchRef,\n minionName: job.minionName,\n scheduledState,\n ...((job.jobType === JobType.SCHEDULED_CRON || job.jobType === JobType.MINION_TICK) ? {} : { expiresAt: new Date(now.getTime() + ORDINARY_JOB_EXECUTION_RETENTION_MS) }),\n domainCategory: job.domainCategory,\n organizationId,\n userId,\n initiatedBy: job.initiatedBy,\n status: scheduledState?.phase === ScheduledExecutionPhase.REVIEW ? JobExecutionStatus.FAILED : JobExecutionStatus.QUEUED,\n queueName,\n priority: job.priority,\n maxRetries: job.maxRetries,\n retryCount: 0,\n createdAt: now,\n queuedAt: job.createdAt ?? now,\n inputPayloadStorageId: job.inputPayloadStorageId,\n };\n\n // Create internal context and execute\n const context = await this.createInternalContext(CoreResourceOperation.CREATE);\n const created = await this.jobExecutionRepository.create<JobExecution>(\n context,\n createData as JobExecution,\n options\n );\n\n const insertedId = (created as any)._id?.toString() ?? created.jobId;\n\n this.logDebug('Job execution record created', {\n jobId: job.jobId,\n insertedId,\n queueName,\n });\n\n return insertedId;\n }\n\n /**\n * The scheduler publishes directly, so verified receipt owns record creation.\n * The jobId unique constraint arbitrates concurrent receipts. Read-after-create\n * failure accepts only a matching existing identity; it never resets history\n * and never treats a failed persistence operation as successful absence.\n */\n async ensureScheduledJobRecord(job: JobPayload, queueName: string, scheduledState?: ScheduledExecutionState): Promise<JobExecution> {\n const sameInput = (row: JobExecution): boolean => {\n if (!row.scheduledState) return true; // Legacy receipt has no durable input snapshot to compare.\n const original: JobPayload = JSON.parse(row.scheduledState.payloadJson);\n const input = (value: string | undefined): unknown => value === undefined ? undefined : JSON.parse(value);\n return isDeepStrictEqual(input(original.inputDataJson), input(job.inputDataJson));\n };\n // A receipt's row is compared against the id this service STAMPS, not against the payload's\n // platform id — the two differ, and comparing the row to the wire would refuse every receipt.\n const applicationId = await this.canonicalApplicationId();\n const matches = (row: JobExecution) => row.applicationId === applicationId\n && row.jobType === job.jobType && row.batchRef === job.batchRef\n && row.operationPathKey === job.operationPathKey && row.minionName === job.minionName && sameInput(row);\n const acceptExisting = async (initial: JobExecution): Promise<JobExecution> => {\n let row = initial;\n while (true) {\n if (!matches(row)) throw new Error('Scheduled job identity conflicts with existing history');\n if (row.scheduledState || !scheduledState) return row;\n const terminal = row.status === JobExecutionStatus.COMPLETED || row.status === JobExecutionStatus.FAILED\n || row.status === JobExecutionStatus.DEAD_LETTER || row.status === JobExecutionStatus.CANCELLED;\n const adoptedState: ScheduledExecutionState = {\n ...scheduledState,\n phase: terminal ? ScheduledExecutionPhase.FINISHED : ScheduledExecutionPhase.REVIEW,\n attemptCount: Math.max(1, scheduledState.attemptCount),\n attempts: [],\n reason: terminal ? 'Legacy receipt already has a terminal outcome' : `Legacy ${row.status} receipt has no attempt ownership; previous effects unknown`,\n };\n const adopted = await this.repositoriesRegistry.atomicGuardedMutation<JobExecution>(CoreResourceType.JOB_EXECUTIONS,\n { jobId: row.jobId, applicationId: row.applicationId, jobType: row.jobType,\n batchRef: row.batchRef ?? { $exists: false }, operationPathKey: row.operationPathKey ?? { $exists: false },\n minionName: row.minionName ?? { $exists: false }, status: row.status, scheduledState: { $exists: false } }, {\n set: { scheduledState: adoptedState, status: terminal ? row.status : JobExecutionStatus.FAILED, ...(terminal ? { expiresAt: row.expiresAt ?? new Date(Date.now() + ORDINARY_JOB_EXECUTION_RETENTION_MS) } : {}) },\n ...(terminal ? {} : { clear: ['expiresAt'] }),\n });\n if (adopted) return adopted;\n const concurrent = await this.getByJobId(job.jobId);\n if (!concurrent) throw new Error('Legacy scheduled receipt disappeared during adoption');\n row = concurrent; // A legacy status writer or another receipt won; re-evaluate its actual outcome.\n }\n };\n const existing = await this.getByJobId(job.jobId);\n if (existing) return acceptExisting(existing);\n try {\n await this.createJobRecord(job, queueName, undefined, scheduledState);\n } catch (error) {\n // Another receipt may have won the unique insert. Preserve genuine failures\n // unless a positively matching record now proves creation succeeded.\n const concurrent = await this.getByJobId(job.jobId);\n if (concurrent && matches(concurrent)) return acceptExisting(concurrent);\n throw error;\n }\n const created = await this.getByJobId(job.jobId);\n if (!created || !matches(created)) throw new Error('Scheduled job history was not persisted');\n return created;\n }\n\n /**\n * One atomic state replacement is the scheduled runner's ownership boundary. A stale revision\n * cannot change state or terminal history. Patch fields are explicitly copied so callers cannot\n * overwrite identity, signed input, policy or queue routing through an untyped object.\n */\n async compareScheduledState(jobId: string, expectedRevision: number, state: ScheduledExecutionState, patch: Partial<JobExecution> = {}): Promise<JobExecution | null> {\n if (!Number.isInteger(expectedRevision) || expectedRevision < 0 || state.revision !== expectedRevision + 1) {\n throw new Error('Scheduled state compare-and-swap requires exactly the next revision');\n }\n const set: Partial<JobExecution> = { scheduledState: ScheduledExecutionStateSchema.parse(state) };\n for (const key of ['status', 'startedAt', 'completedAt', 'retryCount', 'workerId', 'outputPayloadStorageId', 'error', 'expiresAt'] as const) {\n if (patch[key] !== undefined) Object.assign(set, { [key]: patch[key] });\n }\n return this.repositoriesRegistry.atomicGuardedMutation<JobExecution>(CoreResourceType.JOB_EXECUTIONS,\n { jobId, 'scheduledState.revision': expectedRevision }, { set });\n }\n\n /**\n * Oldest due work first; a fixed bound prevents a recovery poll from scanning all history.\n *\n * Scoped to this application's rows by the id this service stamps — callers name the QUEUE and\n * never the application, so no caller can scan under the platform id the wire carries.\n */\n async listScheduledDue(queueName: string, now: Date): Promise<JobExecution[]> {\n const context = await this.createInternalContext(CoreResourceOperation.READ);\n const options: RepositoryOptions & { listOptions: { page: number; limit: number; sort: Record<string, 1 | -1> } } = {\n paginated: false, listOptions: { page: 1, limit: 100, sort: { 'scheduledState.nextAttemptAt': 1, jobId: 1 } },\n };\n return this.jobExecutionRepository.listForInternalScan<JobExecution>(context, {\n applicationId: await this.canonicalApplicationId(), queueName,\n 'scheduledState.nextAttemptAt': { $lte: now },\n 'scheduledState.phase': { $in: [ScheduledExecutionPhase.READY, ScheduledExecutionPhase.WAITING, ScheduledExecutionPhase.RUNNING, ScheduledExecutionPhase.RECONCILING] },\n }, options);\n }\n\n /** Separate bounded archive outbox; storage failure cannot consume execution-recovery slots. */\n async listScheduledArchivesDue(queueName: string, now: Date): Promise<JobExecution[]> {\n const context = await this.createInternalContext(CoreResourceOperation.READ);\n const options: RepositoryOptions & { listOptions: { page: number; limit: number; sort: Record<string, 1 | -1> } } =\n { paginated: false, listOptions: { page: 1, limit: 20, sort: { 'scheduledState.evidenceArchiveAfter': 1, jobId: 1 } } };\n return this.jobExecutionRepository.listForInternalScan<JobExecution>(context, {\n applicationId: await this.canonicalApplicationId(), queueName, 'scheduledState.phase': ScheduledExecutionPhase.FINISHED,\n 'scheduledState.evidence': { $exists: true }, 'scheduledState.evidenceArchived': { $ne: true },\n 'scheduledState.evidenceArchiveAfter': { $lte: now }, expiresAt: { $gt: now },\n }, options);\n }\n\n /** Live fallback exposes unresolved/pending invocations, never treats them as retained archive evidence. */\n async listScheduledEvidenceCandidates(\n target: { queueName: string; batchRef?: string; operationPathKey?: string; minionName?: string },\n from: Date, to: Date, limit = 10000): Promise<{ records: JobExecution[]; truncated: boolean }> {\n if (!Number.isInteger(limit) || limit < 1 || limit > 10000) throw new Error('Invalid evidence scan limit');\n const context = await this.createInternalContext(CoreResourceOperation.READ);\n const filter: Record<string, unknown> = { applicationId: await this.canonicalApplicationId(),\n ...Object.fromEntries(Object.entries(target).filter(([, value]) => value !== undefined)),\n $or: [{ expiresAt: { $exists: false } }, { expiresAt: { $gt: new Date() } }],\n // Signed first admission may precede an instant by 30s or follow it by 5min.\n queuedAt: { $gte: new Date(from.getTime() - 30000), $lt: new Date(to.getTime() + 300000) },\n jobType: { $in: [JobType.SCHEDULED_CRON, JobType.MINION_TICK] },\n };\n const records: JobExecution[] = [];\n for (let page = 1; records.length < limit; page++) {\n const options: RepositoryOptions & { listOptions: { page: number; limit: number; sort: Record<string, 1 | -1> } } =\n { paginated: false, listOptions: { page, limit: 100, sort: { jobId: 1 } } };\n const rows = await this.jobExecutionRepository.listForInternalScan<JobExecution>(context, filter, options);\n for (const row of rows) {\n if (records.length === limit) return { records, truncated: true };\n records.push(row);\n }\n if (rows.length < 100) return { records, truncated: false };\n }\n return { records, truncated: true };\n }\n\n /**\n * Mark job as started when worker begins processing.\n *\n * @param jobId - Job identifier\n * @param workerId - Worker/pod identifier\n * @param retryCount - Current delivery retry index from the payload\n * @param options - Optional repository options\n */\n async markStarted(\n jobId: string,\n workerId: string,\n retryCount: number,\n options?: RepositoryOptions\n ): Promise<void> {\n const context = await this.createInternalContext(CoreResourceOperation.UPDATE);\n\n const updateData: Partial<JobExecution> = {\n status: JobExecutionStatus.PROCESSING,\n retryCount,\n startedAt: new Date(),\n workerId,\n workerHostname: os.hostname(),\n };\n\n await this.jobExecutionRepository.update<JobExecution>(\n context,\n { jobId, scheduledState: { $exists: false }, retryCount: { $lte: retryCount }, status: { $in: [JobExecutionStatus.QUEUED, JobExecutionStatus.PROCESSING, JobExecutionStatus.RETRYING] } },\n updateData,\n options\n );\n\n this.logDebug('Job marked as started', { jobId, workerId });\n }\n\n /**\n * Mark job as completed successfully.\n *\n * @param jobId - Job identifier\n * @param retryCount - Current delivery retry index from the payload\n * @param outputPayloadStorageId - Optional storage ID for large output\n * @param options - Optional repository options\n */\n async markCompleted(\n jobId: string,\n retryCount: number,\n outputPayloadStorageId?: string,\n options?: RepositoryOptions\n ): Promise<void> {\n const now = new Date();\n\n // Read current state for duration calculation\n const readContext = await this.createInternalContext(CoreResourceOperation.READ);\n const execution = await this.jobExecutionRepository.read<JobExecution>(\n readContext,\n { jobId, scheduledState: { $exists: false }, retryCount, status: JobExecutionStatus.PROCESSING },\n options\n );\n\n const durationMs = execution?.startedAt\n ? now.getTime() - new Date(execution.startedAt).getTime()\n : undefined;\n\n // Update with completion data\n const updateContext = await this.createInternalContext(CoreResourceOperation.UPDATE);\n const updateData: Partial<JobExecution> = {\n status: JobExecutionStatus.COMPLETED,\n completedAt: now,\n durationMs,\n outputPayloadStorageId,\n };\n\n await this.jobExecutionRepository.update<JobExecution>(\n updateContext,\n { jobId, scheduledState: { $exists: false }, retryCount, status: JobExecutionStatus.PROCESSING },\n updateData,\n options\n );\n\n this.logDebug('Job marked as completed', { jobId, durationMs });\n }\n\n /**\n * Record the failure outcome already selected by a consumer. RETRYING is written\n * only after confirmed retry publication, with the next payload's retry index.\n * Terminal failures retain the current index: failures are not new attempts.\n *\n * The attempt/status predicate prevents a delayed retry-history write from\n * overwriting a newer attempt that has already started or completed. Persistence\n * is not a broker receipt and cannot decide whether execution should run again.\n */\n async recordFailure(jobId: string, outcome: JobFailureOutcome, options?: RepositoryOptions): Promise<void> {\n const now = new Date();\n const readContext = await this.createInternalContext(CoreResourceOperation.READ);\n const execution = await this.jobExecutionRepository.read<JobExecution>(readContext, { jobId }, options);\n if (!execution) {\n this.logger.warn('Job execution record not found for failure', { jobId });\n return;\n }\n const retrying = outcome.status === JobExecutionStatus.RETRYING;\n const error = isWildoBackendError(outcome.error) ? outcome.error : {\n type: ErrorType.INTERNAL,\n severity: ErrorSeverity.HIGH,\n timestamp: now,\n backendActions: [],\n customMessageReference: ErrorCustomMessageReference.INTERNAL,\n statusCode: 500,\n context: { message: outcome.error instanceof Error ? outcome.error.message : String(outcome.error) },\n stack: outcome.error instanceof Error ? outcome.error.stack : undefined,\n };\n const updateContext = await this.createInternalContext(CoreResourceOperation.UPDATE);\n await this.jobExecutionRepository.update<JobExecution>(updateContext, {\n jobId,\n scheduledState: { $exists: false },\n retryCount: outcome.deliveredRetryCount,\n status: { $in: [JobExecutionStatus.QUEUED, JobExecutionStatus.PROCESSING, JobExecutionStatus.RETRYING] },\n }, {\n status: outcome.status,\n retryCount: outcome.deliveredRetryCount + (retrying ? 1 : 0),\n ...(retrying ? { lastRetryAt: now } : { completedAt: now }),\n durationMs: execution.startedAt ? now.getTime() - new Date(execution.startedAt).getTime() : undefined,\n error: {\n type: error.type, severity: error.severity, timestamp: error.timestamp,\n operationPathKey: error.operationPathKey, context: error.context,\n backendActions: error.backendActions, customMessageReference: error.customMessageReference,\n statusCode: error.statusCode, stack: error.stack,\n errorHandlingStrategy: error.errorHandlingStrategy, retryPolicy: error.retryPolicy,\n maxRetries: error.maxRetries, initialDelay: error.initialDelay, baseDelay: error.baseDelay,\n },\n }, options);\n this.logDebug('Consumer failure outcome recorded', { jobId, status: outcome.status, retryCount: outcome.deliveredRetryCount });\n }\n\n /**\n * Mark job as cancelled.\n *\n * @param jobId - Job identifier\n * @param options - Optional repository options\n */\n async markCancelled(jobId: string, options?: RepositoryOptions): Promise<void> {\n const context = await this.createInternalContext(CoreResourceOperation.UPDATE);\n\n const updateData: Partial<JobExecution> = {\n status: JobExecutionStatus.CANCELLED,\n completedAt: new Date(),\n };\n\n await this.jobExecutionRepository.update<JobExecution>(\n context,\n { jobId, scheduledState: { $exists: false } },\n updateData,\n options\n );\n\n this.logDebug('Job marked as cancelled', { jobId });\n }\n\n /**\n * Get job execution record by jobId.\n * Useful for status queries and debugging.\n *\n * @param jobId - Job identifier\n * @param options - Optional repository options\n * @returns Job execution record or null if not found\n */\n async getByJobId(jobId: string, options?: RepositoryOptions): Promise<JobExecution | null> {\n const context = await this.createInternalContext(CoreResourceOperation.READ);\n\n const execution = await this.jobExecutionRepository.read<JobExecution>(\n context,\n { jobId },\n options\n );\n\n return execution;\n }\n}\n"]}
1
+ {"version":3,"file":"job-status-tracking.backend.service.js","sourceRoot":"","sources":["../../../../src/queue/job-status-tracking.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Job Status Tracking Backend Service\n *\n * Tracks job lifecycle through the configured resource repository for observability and querying.\n *\n * Uses the same pattern as FilesBackendService:\n * - Get repository via RepositoriesRegistryHandlerBackendService\n * - Create internal execution context via\n * ExecutionContextCreatorBackendService.createForInternalRepositoryOperation\n * (the variant-correct, REPOSITORY_ONLY-preferred seam)\n * - Use direct repository methods (create, read, update)\n *\n * This ensures proper authorization flow while keeping the implementation simple.\n */\n\nimport { injectable, inject } from 'inversify';\nimport * as os from 'os';\nimport { isDeepStrictEqual } from 'node:util';\nimport { ORDINARY_JOB_EXECUTION_RETENTION_MS } from './job-execution-retention.mongo';\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport { LoggerService } from '~wildo-backend-lib/monitoring/logger/services/logger.service';\nimport type { BackendResourceRepository } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport { ExecutionContextCreatorBackendService } from '~wildo-backend-lib/runtime/services/execution-context-creator.backend.service';\nimport { ApplicationIdentityBackendService } from '~wildo-backend-lib/applications/services/application-identity.backend.service';\nimport { RepositoryOptions } from '~wildo-backend-lib/base-classes/models/repositories.backend.schemas';\nimport {\n JobPayload,\n JobExecution,\n JobExecutionStatus,\n JobType,\n ScheduledExecutionState,\n ScheduledExecutionStateSchema,\n ScheduledExecutionPhase,\n ResourceSerializationUtils,\n isWildoBackendError,\n ErrorType,\n ErrorSeverity,\n ErrorCustomMessageReference,\n CoreResourceType,\n CoreResourceOperation,\n} from '@wildo-ai/saas-models';\nimport { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\n\n/** The consumer supplies its chosen settlement, never a budget for the tracker to interpret. */\nexport interface JobFailureOutcome {\n status: JobExecutionStatus.RETRYING | JobExecutionStatus.FAILED | JobExecutionStatus.DEAD_LETTER;\n /** Zero-based retry index of the delivery that failed; RETRYING records the next index. */\n deliveredRetryCount: number;\n error: unknown;\n}\n\n@injectable()\nexport class JobStatusTrackingBackendService {\n protected logDebug: (message: string, context?: Record<string, unknown>) => void;\n\n constructor(\n @inject(SAAS_SERVICE_TYPES.Logger)\n private readonly logger: LoggerService,\n @inject(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService)\n private readonly repositoriesRegistry: RepositoriesRegistryHandlerBackendService,\n @inject(SAAS_SERVICE_TYPES.ExecutionContextCreatorBackendService)\n private readonly executionContextCreator: ExecutionContextCreatorBackendService,\n @inject(SAAS_SERVICE_TYPES.ApplicationIdentityService)\n private readonly applicationIdentity: ApplicationIdentityBackendService,\n ) {\n this.logDebug = this.logger.debugByType('JobStatusTrackingBackendService');\n this.logger.setDebugTypeLogging('JobStatusTrackingBackendService', false);\n }\n\n /**\n * Get the resource type for this service.\n */\n static get resourceType(): CoreResourceType {\n return CoreResourceType.JOB_EXECUTIONS;\n }\n\n /**\n * The id every `jobExecutions` row this service writes is anchored to, and the only id its\n * application-scoped scans filter on: `applications._id`, the APPLICATION RESOURCE SCOPE's key.\n *\n * ## The wire / row boundary this service IS\n *\n * A job travels on the wire — a RabbitMQ message, or a JWT signed by the crontabs-manager — carrying\n * `JobPayload.applicationId`, and on the wire that value is the PLATFORM's id: it is what the queue\n * names are built from, what the crontabs-manager knows this application as, and what every consumer\n * verifies a scheduled message against before accepting it. That is addressing, and it is correct.\n *\n * The moment the payload becomes a durable ROW it stops being an address and becomes an attribution\n * that scope-filtered reads will match against, and there the platform id is the wrong identity: no\n * scope predicate matches it. Until 2026-09-18 `createJobRecord` copied the wire value into the row,\n * and Wonder Todos held 10,314 `jobexecutions` and 3,595 `jobpayloadstorage` rows under the platform\n * id while every other `applicationId` column in the database carried the record id. This service is\n * the boundary: the PAYLOAD keeps the platform id, the ROW is stamped here from the canonical\n * identity, and nothing outside this file gets to choose.\n *\n * Public rather than private because the scheduled runner's operator-review door checks a row's\n * ownership against it; every caller that needs the row identity asks here and passes nothing in.\n */\n public async canonicalApplicationId(): Promise<string> {\n return this.applicationIdentity.getCanonicalApplicationId();\n }\n\n /**\n * Get repository for job executions.\n * Lazy getter to ensure repository is initialized.\n */\n private get jobExecutionRepository(): BackendResourceRepository<any, any, any> {\n return this.repositoriesRegistry.getRepositoryOrThrow(\n CoreResourceType.JOB_EXECUTIONS,\n {} as ExecutionContext<any>\n );\n }\n\n /**\n * Create an internal execution context for job tracking operations.\n *\n * `JOB_EXECUTIONS` declares only `REPOSITORY_ONLY` variants (managed off the\n * HTTP surface). Resolution goes through the shared internal-repository builder\n * — exactly as `FilesBackendService` does — which resolves the operation path\n * `REPOSITORY_ONLY`-preferred with a URL fallback. The URL-only\n * `getOperationPathDefault` filters for `API_CALL` / `API_CALL_WITH_CALLBACK`\n * and would throw `RESOURCES_REGISTRY_OPERATION_PATH_NOT_FOUND` for these ops.\n */\n private async createInternalContext(\n operation: CoreResourceOperation\n ): Promise<ExecutionContext<any>> {\n return this.executionContextCreator.createForInternalRepositoryOperation({\n resourceType: CoreResourceType.JOB_EXECUTIONS,\n operationIdentifier: operation,\n });\n }\n\n /**\n * Create job execution record when job is enqueued.\n *\n * @param job - Job payload with metadata\n * @param queueName - Name of the target queue\n * @param options - Optional repository options (for transactions)\n * @returns Persisted record ID, falling back to its job ID\n */\n async createJobRecord(\n job: JobPayload,\n queueName: string,\n options?: RepositoryOptions,\n scheduledState?: ScheduledExecutionState\n ): Promise<string> {\n // Extract identifiers from execution context for querying\n let organizationId: string | undefined;\n let userId: string | undefined;\n\n if (job.executionContextJson) {\n try {\n const ctxData = ResourceSerializationUtils.deserializeExecutionContextData(job.executionContextJson);\n organizationId = ctxData.initiatorIds?.organizationId;\n userId = ctxData.initiatorIds?.userId;\n } catch {\n this.logger.warn('Failed to deserialize execution context for job tracking', { jobId: job.jobId });\n }\n }\n\n const now = new Date();\n\n // Build record data\n const createData: Partial<JobExecution> = {\n jobId: job.jobId,\n // The ROW's identity, never the payload's: `job.applicationId` is the platform id the wire is\n // addressed with, and copying it here is what anchored 10,314 rows to an id no scope predicate\n // matches. See `canonicalApplicationId()` for the boundary this line enforces.\n applicationId: await this.canonicalApplicationId(),\n jobType: job.jobType,\n operationPathKey: job.operationPathKey,\n batchRef: job.batchRef,\n minionName: job.minionName,\n scheduledState,\n ...((job.jobType === JobType.SCHEDULED_CRON || job.jobType === JobType.MINION_TICK) ? {} : { expiresAt: new Date(now.getTime() + ORDINARY_JOB_EXECUTION_RETENTION_MS) }),\n domainCategory: job.domainCategory,\n organizationId,\n userId,\n initiatedBy: job.initiatedBy,\n status: scheduledState?.phase === ScheduledExecutionPhase.REVIEW ? JobExecutionStatus.FAILED : JobExecutionStatus.QUEUED,\n queueName,\n priority: job.priority,\n maxRetries: job.maxRetries,\n retryCount: 0,\n createdAt: now,\n queuedAt: job.createdAt ?? now,\n inputPayloadStorageId: job.inputPayloadStorageId,\n };\n\n // Create internal context and execute\n const context = await this.createInternalContext(CoreResourceOperation.CREATE);\n const created = await this.jobExecutionRepository.create<JobExecution>(\n context,\n createData as JobExecution,\n options\n );\n\n const insertedId = (created as any)._id?.toString() ?? created.jobId;\n\n this.logDebug('Job execution record created', {\n jobId: job.jobId,\n insertedId,\n queueName,\n });\n\n return insertedId;\n }\n\n /**\n * The scheduler publishes directly, so verified receipt owns record creation.\n * The jobId unique constraint arbitrates concurrent receipts. Read-after-create\n * failure accepts only a matching existing identity; it never resets history\n * and never treats a failed persistence operation as successful absence.\n */\n async ensureScheduledJobRecord(job: JobPayload, queueName: string, scheduledState?: ScheduledExecutionState): Promise<JobExecution> {\n const sameInput = (row: JobExecution): boolean => {\n if (!row.scheduledState) return true; // Legacy receipt has no durable input snapshot to compare.\n const original: JobPayload = JSON.parse(row.scheduledState.payloadJson);\n const input = (value: string | undefined): unknown => value === undefined ? undefined : JSON.parse(value);\n return isDeepStrictEqual(input(original.inputDataJson), input(job.inputDataJson));\n };\n // A receipt's row is compared against the id this service STAMPS, not against the payload's\n // platform id — the two differ, and comparing the row to the wire would refuse every receipt.\n const applicationId = await this.canonicalApplicationId();\n const matches = (row: JobExecution) => row.applicationId === applicationId\n && row.jobType === job.jobType && row.batchRef === job.batchRef\n && row.operationPathKey === job.operationPathKey && row.minionName === job.minionName && sameInput(row);\n const acceptExisting = async (initial: JobExecution): Promise<JobExecution> => {\n let row = initial;\n while (true) {\n if (!matches(row)) throw new Error('Scheduled job identity conflicts with existing history');\n if (row.scheduledState || !scheduledState) return row;\n const terminal = row.status === JobExecutionStatus.COMPLETED || row.status === JobExecutionStatus.FAILED\n || row.status === JobExecutionStatus.DEAD_LETTER || row.status === JobExecutionStatus.CANCELLED;\n // `lateness` describes a delivery THIS receipt could not admit; a legacy row it adopts has\n // its own, unknown history, so the late-delivery marker must not be stamped onto it (#2212).\n const { lateness: _receiptLateness, ...adoptableState } = scheduledState;\n const adoptedState: ScheduledExecutionState = {\n ...adoptableState,\n phase: terminal ? ScheduledExecutionPhase.FINISHED : ScheduledExecutionPhase.REVIEW,\n attemptCount: Math.max(1, scheduledState.attemptCount),\n attempts: [],\n reason: terminal ? 'Legacy receipt already has a terminal outcome' : `Legacy ${row.status} receipt has no attempt ownership; previous effects unknown`,\n };\n const adopted = await this.repositoriesRegistry.atomicGuardedMutation<JobExecution>(CoreResourceType.JOB_EXECUTIONS,\n { jobId: row.jobId, applicationId: row.applicationId, jobType: row.jobType,\n batchRef: row.batchRef ?? { $exists: false }, operationPathKey: row.operationPathKey ?? { $exists: false },\n minionName: row.minionName ?? { $exists: false }, status: row.status, scheduledState: { $exists: false } }, {\n set: { scheduledState: adoptedState, status: terminal ? row.status : JobExecutionStatus.FAILED, ...(terminal ? { expiresAt: row.expiresAt ?? new Date(Date.now() + ORDINARY_JOB_EXECUTION_RETENTION_MS) } : {}) },\n ...(terminal ? {} : { clear: ['expiresAt'] }),\n });\n if (adopted) return adopted;\n const concurrent = await this.getByJobId(job.jobId);\n if (!concurrent) throw new Error('Legacy scheduled receipt disappeared during adoption');\n row = concurrent; // A legacy status writer or another receipt won; re-evaluate its actual outcome.\n }\n };\n const existing = await this.getByJobId(job.jobId);\n if (existing) return acceptExisting(existing);\n try {\n await this.createJobRecord(job, queueName, undefined, scheduledState);\n } catch (error) {\n // Another receipt may have won the unique insert. Preserve genuine failures\n // unless a positively matching record now proves creation succeeded.\n const concurrent = await this.getByJobId(job.jobId);\n if (concurrent && matches(concurrent)) return acceptExisting(concurrent);\n throw error;\n }\n const created = await this.getByJobId(job.jobId);\n if (!created || !matches(created)) throw new Error('Scheduled job history was not persisted');\n return created;\n }\n\n /**\n * One atomic state replacement is the scheduled runner's ownership boundary. A stale revision\n * cannot change state or terminal history. Patch fields are explicitly copied so callers cannot\n * overwrite identity, signed input, policy or queue routing through an untyped object.\n */\n async compareScheduledState(jobId: string, expectedRevision: number, state: ScheduledExecutionState, patch: Partial<JobExecution> = {}): Promise<JobExecution | null> {\n if (!Number.isInteger(expectedRevision) || expectedRevision < 0 || state.revision !== expectedRevision + 1) {\n throw new Error('Scheduled state compare-and-swap requires exactly the next revision');\n }\n const set: Partial<JobExecution> = { scheduledState: ScheduledExecutionStateSchema.parse(state) };\n for (const key of ['status', 'startedAt', 'completedAt', 'retryCount', 'workerId', 'outputPayloadStorageId', 'error', 'expiresAt'] as const) {\n if (patch[key] !== undefined) Object.assign(set, { [key]: patch[key] });\n }\n return this.repositoriesRegistry.atomicGuardedMutation<JobExecution>(CoreResourceType.JOB_EXECUTIONS,\n { jobId, 'scheduledState.revision': expectedRevision }, { set });\n }\n\n /**\n * Oldest due work first; a fixed bound prevents a recovery poll from scanning all history.\n *\n * Scoped to this application's rows by the id this service stamps — callers name the QUEUE and\n * never the application, so no caller can scan under the platform id the wire carries.\n */\n async listScheduledDue(queueName: string, now: Date): Promise<JobExecution[]> {\n const context = await this.createInternalContext(CoreResourceOperation.READ);\n const options: RepositoryOptions & { listOptions: { page: number; limit: number; sort: Record<string, 1 | -1> } } = {\n paginated: false, listOptions: { page: 1, limit: 100, sort: { 'scheduledState.nextAttemptAt': 1, jobId: 1 } },\n };\n return this.jobExecutionRepository.listForInternalScan<JobExecution>(context, {\n applicationId: await this.canonicalApplicationId(), queueName,\n 'scheduledState.nextAttemptAt': { $lte: now },\n 'scheduledState.phase': { $in: [ScheduledExecutionPhase.READY, ScheduledExecutionPhase.WAITING, ScheduledExecutionPhase.RUNNING, ScheduledExecutionPhase.RECONCILING] },\n }, options);\n }\n\n /** Separate bounded archive outbox; storage failure cannot consume execution-recovery slots. */\n async listScheduledArchivesDue(queueName: string, now: Date): Promise<JobExecution[]> {\n const context = await this.createInternalContext(CoreResourceOperation.READ);\n const options: RepositoryOptions & { listOptions: { page: number; limit: number; sort: Record<string, 1 | -1> } } =\n { paginated: false, listOptions: { page: 1, limit: 20, sort: { 'scheduledState.evidenceArchiveAfter': 1, jobId: 1 } } };\n return this.jobExecutionRepository.listForInternalScan<JobExecution>(context, {\n applicationId: await this.canonicalApplicationId(), queueName, 'scheduledState.phase': ScheduledExecutionPhase.FINISHED,\n 'scheduledState.evidence': { $exists: true }, 'scheduledState.evidenceArchived': { $ne: true },\n 'scheduledState.evidenceArchiveAfter': { $lte: now }, expiresAt: { $gt: now },\n }, options);\n }\n\n /** Live fallback exposes unresolved/pending invocations, never treats them as retained archive evidence. */\n async listScheduledEvidenceCandidates(\n target: { queueName: string; batchRef?: string; operationPathKey?: string; minionName?: string },\n from: Date, to: Date, limit = 10000): Promise<{ records: JobExecution[]; truncated: boolean }> {\n if (!Number.isInteger(limit) || limit < 1 || limit > 10000) throw new Error('Invalid evidence scan limit');\n const context = await this.createInternalContext(CoreResourceOperation.READ);\n const filter: Record<string, unknown> = { applicationId: await this.canonicalApplicationId(),\n ...Object.fromEntries(Object.entries(target).filter(([, value]) => value !== undefined)),\n $or: [{ expiresAt: { $exists: false } }, { expiresAt: { $gt: new Date() } }],\n // Signed first admission may precede an instant by 30s or follow it by 5min.\n queuedAt: { $gte: new Date(from.getTime() - 30000), $lt: new Date(to.getTime() + 300000) },\n jobType: { $in: [JobType.SCHEDULED_CRON, JobType.MINION_TICK] },\n };\n const records: JobExecution[] = [];\n for (let page = 1; records.length < limit; page++) {\n const options: RepositoryOptions & { listOptions: { page: number; limit: number; sort: Record<string, 1 | -1> } } =\n { paginated: false, listOptions: { page, limit: 100, sort: { jobId: 1 } } };\n const rows = await this.jobExecutionRepository.listForInternalScan<JobExecution>(context, filter, options);\n for (const row of rows) {\n if (records.length === limit) return { records, truncated: true };\n records.push(row);\n }\n if (rows.length < 100) return { records, truncated: false };\n }\n return { records, truncated: true };\n }\n\n /**\n * Mark job as started when worker begins processing.\n *\n * @param jobId - Job identifier\n * @param workerId - Worker/pod identifier\n * @param retryCount - Current delivery retry index from the payload\n * @param options - Optional repository options\n */\n async markStarted(\n jobId: string,\n workerId: string,\n retryCount: number,\n options?: RepositoryOptions\n ): Promise<void> {\n const context = await this.createInternalContext(CoreResourceOperation.UPDATE);\n\n const updateData: Partial<JobExecution> = {\n status: JobExecutionStatus.PROCESSING,\n retryCount,\n startedAt: new Date(),\n workerId,\n workerHostname: os.hostname(),\n };\n\n await this.jobExecutionRepository.update<JobExecution>(\n context,\n { jobId, scheduledState: { $exists: false }, retryCount: { $lte: retryCount }, status: { $in: [JobExecutionStatus.QUEUED, JobExecutionStatus.PROCESSING, JobExecutionStatus.RETRYING] } },\n updateData,\n options\n );\n\n this.logDebug('Job marked as started', { jobId, workerId });\n }\n\n /**\n * Mark job as completed successfully.\n *\n * @param jobId - Job identifier\n * @param retryCount - Current delivery retry index from the payload\n * @param outputPayloadStorageId - Optional storage ID for large output\n * @param options - Optional repository options\n */\n async markCompleted(\n jobId: string,\n retryCount: number,\n outputPayloadStorageId?: string,\n options?: RepositoryOptions\n ): Promise<void> {\n const now = new Date();\n\n // Read current state for duration calculation\n const readContext = await this.createInternalContext(CoreResourceOperation.READ);\n const execution = await this.jobExecutionRepository.read<JobExecution>(\n readContext,\n { jobId, scheduledState: { $exists: false }, retryCount, status: JobExecutionStatus.PROCESSING },\n options\n );\n\n const durationMs = execution?.startedAt\n ? now.getTime() - new Date(execution.startedAt).getTime()\n : undefined;\n\n // Update with completion data\n const updateContext = await this.createInternalContext(CoreResourceOperation.UPDATE);\n const updateData: Partial<JobExecution> = {\n status: JobExecutionStatus.COMPLETED,\n completedAt: now,\n durationMs,\n outputPayloadStorageId,\n };\n\n await this.jobExecutionRepository.update<JobExecution>(\n updateContext,\n { jobId, scheduledState: { $exists: false }, retryCount, status: JobExecutionStatus.PROCESSING },\n updateData,\n options\n );\n\n this.logDebug('Job marked as completed', { jobId, durationMs });\n }\n\n /**\n * Record the failure outcome already selected by a consumer. RETRYING is written\n * only after confirmed retry publication, with the next payload's retry index.\n * Terminal failures retain the current index: failures are not new attempts.\n *\n * The attempt/status predicate prevents a delayed retry-history write from\n * overwriting a newer attempt that has already started or completed. Persistence\n * is not a broker receipt and cannot decide whether execution should run again.\n */\n async recordFailure(jobId: string, outcome: JobFailureOutcome, options?: RepositoryOptions): Promise<void> {\n const now = new Date();\n const readContext = await this.createInternalContext(CoreResourceOperation.READ);\n const execution = await this.jobExecutionRepository.read<JobExecution>(readContext, { jobId }, options);\n if (!execution) {\n this.logger.warn('Job execution record not found for failure', { jobId });\n return;\n }\n const retrying = outcome.status === JobExecutionStatus.RETRYING;\n const error = isWildoBackendError(outcome.error) ? outcome.error : {\n type: ErrorType.INTERNAL,\n severity: ErrorSeverity.HIGH,\n timestamp: now,\n backendActions: [],\n customMessageReference: ErrorCustomMessageReference.INTERNAL,\n statusCode: 500,\n context: { message: outcome.error instanceof Error ? outcome.error.message : String(outcome.error) },\n stack: outcome.error instanceof Error ? outcome.error.stack : undefined,\n };\n const updateContext = await this.createInternalContext(CoreResourceOperation.UPDATE);\n await this.jobExecutionRepository.update<JobExecution>(updateContext, {\n jobId,\n scheduledState: { $exists: false },\n retryCount: outcome.deliveredRetryCount,\n status: { $in: [JobExecutionStatus.QUEUED, JobExecutionStatus.PROCESSING, JobExecutionStatus.RETRYING] },\n }, {\n status: outcome.status,\n retryCount: outcome.deliveredRetryCount + (retrying ? 1 : 0),\n ...(retrying ? { lastRetryAt: now } : { completedAt: now }),\n durationMs: execution.startedAt ? now.getTime() - new Date(execution.startedAt).getTime() : undefined,\n error: {\n type: error.type, severity: error.severity, timestamp: error.timestamp,\n operationPathKey: error.operationPathKey, context: error.context,\n backendActions: error.backendActions, customMessageReference: error.customMessageReference,\n statusCode: error.statusCode, stack: error.stack,\n errorHandlingStrategy: error.errorHandlingStrategy, retryPolicy: error.retryPolicy,\n maxRetries: error.maxRetries, initialDelay: error.initialDelay, baseDelay: error.baseDelay,\n },\n }, options);\n this.logDebug('Consumer failure outcome recorded', { jobId, status: outcome.status, retryCount: outcome.deliveredRetryCount });\n }\n\n /**\n * Mark job as cancelled.\n *\n * @param jobId - Job identifier\n * @param options - Optional repository options\n */\n async markCancelled(jobId: string, options?: RepositoryOptions): Promise<void> {\n const context = await this.createInternalContext(CoreResourceOperation.UPDATE);\n\n const updateData: Partial<JobExecution> = {\n status: JobExecutionStatus.CANCELLED,\n completedAt: new Date(),\n };\n\n await this.jobExecutionRepository.update<JobExecution>(\n context,\n { jobId, scheduledState: { $exists: false } },\n updateData,\n options\n );\n\n this.logDebug('Job marked as cancelled', { jobId });\n }\n\n /**\n * Get job execution record by jobId.\n * Useful for status queries and debugging.\n *\n * @param jobId - Job identifier\n * @param options - Optional repository options\n * @returns Job execution record or null if not found\n */\n async getByJobId(jobId: string, options?: RepositoryOptions): Promise<JobExecution | null> {\n const context = await this.createInternalContext(CoreResourceOperation.READ);\n\n const execution = await this.jobExecutionRepository.read<JobExecution>(\n context,\n { jobId },\n options\n );\n\n return execution;\n }\n}\n"]}
@@ -81,6 +81,20 @@ export declare class QueueBackendService {
81
81
  initializeForWorker(options?: {
82
82
  ownsSharedJobTopology?: boolean;
83
83
  }): Promise<void>;
84
+ /**
85
+ * Say, once at boot, which dead-letter queues hold parked messages (#2214).
86
+ *
87
+ * Dead-letter queues have no consumer by decision (#469): an operator inspects and replays a parked
88
+ * message with the broker's own tooling, because a job payload may carry personal data. What that
89
+ * decision left out is any way to learn that something IS parked — `scheduled.deadletter` reached
90
+ * 359 messages in one day of local restarts and nothing said so. #469 named queue DEPTH as the
91
+ * first thing to revisit, and this is that: a count and a queue name, never a payload.
92
+ *
93
+ * At boot, because a restart is exactly when a backlog lands, and in the runtime that just declared
94
+ * these queues (so they exist: a passive check of a missing queue closes the channel). Best-effort:
95
+ * a depth that cannot be read is skipped, never a reason to fail initialization.
96
+ */
97
+ private reportParkedDeadLetters;
84
98
  /**
85
99
  * Enqueue operation (fire and forget).
86
100
  * Returns immediately after publishing.
@@ -1 +1 @@
1
- {"version":3,"file":"queue.backend.service.d.ts","sourceRoot":"","sources":["../../../../src/queue/queue.backend.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAC;AAC7F,OAAO,EAAE,uBAAuB,EAAE,MAAM,sEAAsE,CAAC;AAC/G,OAAO,EAAE,4BAA4B,EAAE,MAAM,oFAAoF,CAAC;AAGlI,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAC;AAC/E,OAAO,EAAE,+BAA+B,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,EAAE,+BAA+B,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,MAAM,qEAAqE,CAAC;AAGvG,OAAO,EAIL,KAAK,gCAAgC,EACrC,KAAK,0BAA0B,EAG/B,WAAW,EAIX,uBAAuB,EAOxB,MAAM,uBAAuB,CAAC;AAW/B;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;AAExD,oFAAoF;AACpF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAExF;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,EAAE,GAAG,SAAS,CAEzF;AAED,qBACa,mBAAmB;IAa5B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAEjC,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IAEtC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAExB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAElC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAtBjC,SAAS,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACjF,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAIhB;IACf,OAAO,CAAC,WAAW,CAAS;gBAIT,gBAAgB,EAAE,uBAAuB,EAEzC,qBAAqB,EAAE,4BAA4B,EAEnD,MAAM,EAAE,aAAa,EAErB,OAAO,EAAE,YAAY,EAErB,iBAAiB,EAAE,+BAA+B,EAElD,cAAc,EAAE,+BAA+B;IAOlE,6EAA6E;IAC7E,OAAO,KAAK,KAAK,GAKhB;IAED;;;OAGG;IACU,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAuEjD;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACU,mBAAmB,CAAC,OAAO,GAAE;QAAE,qBAAqB,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAoIlG;;;OAGG;IACU,gBAAgB,CAC3B,gBAAgB,EAAE,gBAAgB,CAAC,GAAG,CAAC,EACvC,SAAS,EAAE,OAAO,EAClB,OAAO,CAAC,EAAE,cAAc,EACxB,eAAe,CAAC,EAAE,0BAA0B,EAC5C,qBAAqB,CAAC,EAAE,gCAAgC,GACvD,OAAO,CAAC,aAAa,CAAC;IA4BzB;;;;;;;OAOG;IACU,cAAc,CAAC,CAAC,EAC3B,gBAAgB,EAAE,gBAAgB,CAAC,GAAG,CAAC,EACvC,SAAS,EAAE,OAAO,EAClB,OAAO,CAAC,EAAE,cAAc,EACxB,SAAS,CAAC,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,0BAA0B,EAC5C,qBAAqB,CAAC,EAAE,gCAAgC,GACvD,OAAO,CAAC,CAAC,CAAC;IA+Db;;;OAGG;IACU,mBAAmB,CAC9B,gBAAgB,EAAE,gBAAgB,CAAC,GAAG,CAAC,EACvC,SAAS,EAAE,OAAO,EAClB,OAAO,CAAC,EAAE,cAAc,EACxB,eAAe,CAAC,EAAE,0BAA0B,EAC5C,qBAAqB,CAAC,EAAE,gCAAgC,GACvD,OAAO,CAAC,aAAa,CAAC;IAwBzB;;;OAGG;YACW,eAAe;IAsF7B;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAO9B;;OAEG;IACH,OAAO,CAAC,WAAW;IAmBnB;;;;;;;;;;OAUG;IACU,kBAAkB,CAC7B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,WAAW,CAAC;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,iGAAiG;QACjG,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,mEAAmE;QACnE,WAAW,CAAC,EAAE,uBAAuB,CAAC;QACtC;;;;;;;;WAQG;QACH,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GACA,OAAO,CAAC,aAAa,CAAC;IAqFzB;;OAEG;IACI,UAAU,IAAI,YAAY;IAIjC;;OAEG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAcpC"}
1
+ {"version":3,"file":"queue.backend.service.d.ts","sourceRoot":"","sources":["../../../../src/queue/queue.backend.service.ts"],"names":[],"mappings":"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"}