@satorio/machinery 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +71 -0
  3. package/dictionary/all.json +4656 -0
  4. package/dictionary/all.toon +639 -0
  5. package/dictionary/core.json +221 -0
  6. package/dictionary/core.toon +33 -0
  7. package/dictionary/graphql.json +212 -0
  8. package/dictionary/graphql.toon +32 -0
  9. package/dictionary/http.json +113 -0
  10. package/dictionary/http.toon +21 -0
  11. package/dictionary/identifiers.json +266 -0
  12. package/dictionary/identifiers.toon +38 -0
  13. package/dictionary/index.json +96 -0
  14. package/dictionary/index.toon +18 -0
  15. package/dictionary/integration.json +131 -0
  16. package/dictionary/integration.toon +23 -0
  17. package/dictionary/money.json +383 -0
  18. package/dictionary/money.toon +51 -0
  19. package/dictionary/ports.json +392 -0
  20. package/dictionary/ports.toon +52 -0
  21. package/dictionary/postgres.json +473 -0
  22. package/dictionary/postgres.toon +61 -0
  23. package/dictionary/publishing.json +131 -0
  24. package/dictionary/publishing.toon +23 -0
  25. package/dictionary/queue.json +365 -0
  26. package/dictionary/queue.toon +49 -0
  27. package/dictionary/reference/api.mdx +843 -0
  28. package/dictionary/reference/uk/api.mdx +844 -0
  29. package/dictionary/storage.json +194 -0
  30. package/dictionary/storage.toon +30 -0
  31. package/dictionary/testing.json +707 -0
  32. package/dictionary/testing.toon +87 -0
  33. package/dictionary/time.json +311 -0
  34. package/dictionary/time.toon +43 -0
  35. package/dictionary/vitest.json +356 -0
  36. package/dictionary/vitest.toon +48 -0
  37. package/dictionary/workflow.json +185 -0
  38. package/dictionary/workflow.toon +29 -0
  39. package/dist/bin/command.d.ts +45 -0
  40. package/dist/bin/command.js +113 -0
  41. package/dist/bin.d.ts +2 -0
  42. package/dist/bin.js +11 -0
  43. package/dist/core/bigint-json.d.ts +6 -0
  44. package/dist/core/bigint-json.js +6 -0
  45. package/dist/core/closed-set.d.ts +14 -0
  46. package/dist/core/closed-set.js +8 -0
  47. package/dist/core/domain-error.d.ts +8 -0
  48. package/dist/core/domain-error.js +11 -0
  49. package/dist/core/environment.d.ts +124 -0
  50. package/dist/core/environment.js +115 -0
  51. package/dist/core/index.d.ts +13 -0
  52. package/dist/core/index.js +13 -0
  53. package/dist/core/ulid.d.ts +27 -0
  54. package/dist/core/ulid.js +27 -0
  55. package/dist/graphql/builder.d.ts +36 -0
  56. package/dist/graphql/builder.js +35 -0
  57. package/dist/graphql/context.d.ts +36 -0
  58. package/dist/graphql/context.js +69 -0
  59. package/dist/graphql/failure-classification.d.ts +11 -0
  60. package/dist/graphql/failure-classification.js +1 -0
  61. package/dist/graphql/failures.d.ts +62 -0
  62. package/dist/graphql/failures.js +30 -0
  63. package/dist/graphql/graphiql.d.ts +45 -0
  64. package/dist/graphql/graphiql.js +56 -0
  65. package/dist/graphql/index.d.ts +15 -0
  66. package/dist/graphql/index.js +14 -0
  67. package/dist/graphql/layer.d.ts +15 -0
  68. package/dist/graphql/layer.js +23 -0
  69. package/dist/graphql/request-handler.d.ts +26 -0
  70. package/dist/graphql/request-handler.js +33 -0
  71. package/dist/graphql/server.d.ts +19 -0
  72. package/dist/graphql/server.js +16 -0
  73. package/dist/graphql/settings.d.ts +55 -0
  74. package/dist/graphql/settings.js +82 -0
  75. package/dist/http/health.d.ts +70 -0
  76. package/dist/http/health.js +60 -0
  77. package/dist/http/index.d.ts +5 -0
  78. package/dist/http/index.js +5 -0
  79. package/dist/identifiers/client-code.d.ts +37 -0
  80. package/dist/identifiers/client-code.js +41 -0
  81. package/dist/identifiers/creditor-reference.d.ts +38 -0
  82. package/dist/identifiers/creditor-reference.js +32 -0
  83. package/dist/identifiers/damm.d.ts +22 -0
  84. package/dist/identifiers/damm.js +50 -0
  85. package/dist/identifiers/document-number.d.ts +68 -0
  86. package/dist/identifiers/document-number.js +73 -0
  87. package/dist/identifiers/document-numbers.d.ts +27 -0
  88. package/dist/identifiers/document-numbers.js +16 -0
  89. package/dist/identifiers/failures.d.ts +46 -0
  90. package/dist/identifiers/failures.js +48 -0
  91. package/dist/identifiers/index.d.ts +14 -0
  92. package/dist/identifiers/index.js +13 -0
  93. package/dist/identifiers/next-document-number.d.ts +26 -0
  94. package/dist/identifiers/next-document-number.js +31 -0
  95. package/dist/identifiers/ulid.d.ts +28 -0
  96. package/dist/identifiers/ulid.js +71 -0
  97. package/dist/integration/external-http-client.d.ts +22 -0
  98. package/dist/integration/external-http-client.js +74 -0
  99. package/dist/integration/index.d.ts +12 -0
  100. package/dist/integration/index.js +12 -0
  101. package/dist/integration/layer.d.ts +19 -0
  102. package/dist/integration/layer.js +30 -0
  103. package/dist/integration/retry.d.ts +65 -0
  104. package/dist/integration/retry.js +54 -0
  105. package/dist/integration/settings.d.ts +73 -0
  106. package/dist/integration/settings.js +92 -0
  107. package/dist/money/amount.d.ts +60 -0
  108. package/dist/money/amount.js +67 -0
  109. package/dist/money/arithmetic.d.ts +60 -0
  110. package/dist/money/arithmetic.js +73 -0
  111. package/dist/money/currency.d.ts +25 -0
  112. package/dist/money/currency.js +24 -0
  113. package/dist/money/decimal.d.ts +29 -0
  114. package/dist/money/decimal.js +39 -0
  115. package/dist/money/exchange-rate.d.ts +32 -0
  116. package/dist/money/exchange-rate.js +28 -0
  117. package/dist/money/failures.d.ts +86 -0
  118. package/dist/money/failures.js +97 -0
  119. package/dist/money/index.d.ts +15 -0
  120. package/dist/money/index.js +15 -0
  121. package/dist/money/percent.d.ts +35 -0
  122. package/dist/money/percent.js +50 -0
  123. package/dist/money/schema.d.ts +25 -0
  124. package/dist/money/schema.js +41 -0
  125. package/dist/ports/blob-store.d.ts +42 -0
  126. package/dist/ports/blob-store.js +13 -0
  127. package/dist/ports/document-number-counter.d.ts +36 -0
  128. package/dist/ports/document-number-counter.js +12 -0
  129. package/dist/ports/event-publisher.d.ts +29 -0
  130. package/dist/ports/event-publisher.js +13 -0
  131. package/dist/ports/external-http-client.d.ts +60 -0
  132. package/dist/ports/external-http-client.js +25 -0
  133. package/dist/ports/index.d.ts +17 -0
  134. package/dist/ports/index.js +17 -0
  135. package/dist/ports/integration-event-outbox.d.ts +44 -0
  136. package/dist/ports/integration-event-outbox.js +13 -0
  137. package/dist/ports/port-unavailable.d.ts +21 -0
  138. package/dist/ports/port-unavailable.js +30 -0
  139. package/dist/ports/processed-event-registry.d.ts +57 -0
  140. package/dist/ports/processed-event-registry.js +24 -0
  141. package/dist/ports/queue-message-producer.d.ts +26 -0
  142. package/dist/ports/queue-message-producer.js +12 -0
  143. package/dist/ports/queue-message-source.d.ts +39 -0
  144. package/dist/ports/queue-message-source.js +13 -0
  145. package/dist/ports/readiness-probe.d.ts +27 -0
  146. package/dist/ports/readiness-probe.js +13 -0
  147. package/dist/ports/transaction-boundary.d.ts +28 -0
  148. package/dist/ports/transaction-boundary.js +13 -0
  149. package/dist/postgres/client.d.ts +51 -0
  150. package/dist/postgres/client.js +81 -0
  151. package/dist/postgres/document-number-counter.d.ts +14 -0
  152. package/dist/postgres/document-number-counter.js +27 -0
  153. package/dist/postgres/failures.d.ts +28 -0
  154. package/dist/postgres/failures.js +18 -0
  155. package/dist/postgres/index.d.ts +18 -0
  156. package/dist/postgres/index.js +18 -0
  157. package/dist/postgres/integration-event-outbox.d.ts +15 -0
  158. package/dist/postgres/integration-event-outbox.js +60 -0
  159. package/dist/postgres/jsonb-value.d.ts +10 -0
  160. package/dist/postgres/jsonb-value.js +9 -0
  161. package/dist/postgres/layer.d.ts +57 -0
  162. package/dist/postgres/layer.js +72 -0
  163. package/dist/postgres/migrations/advisory-lock.d.ts +47 -0
  164. package/dist/postgres/migrations/advisory-lock.js +59 -0
  165. package/dist/postgres/migrations/runner.d.ts +56 -0
  166. package/dist/postgres/migrations/runner.js +69 -0
  167. package/dist/postgres/migrations/sql-file-loader.d.ts +59 -0
  168. package/dist/postgres/migrations/sql-file-loader.js +99 -0
  169. package/dist/postgres/processed-event-registry.d.ts +13 -0
  170. package/dist/postgres/processed-event-registry.js +44 -0
  171. package/dist/postgres/readiness-probe.d.ts +27 -0
  172. package/dist/postgres/readiness-probe.js +33 -0
  173. package/dist/postgres/settings.d.ts +134 -0
  174. package/dist/postgres/settings.js +210 -0
  175. package/dist/postgres/sql/0001_processed_event.sql +4 -0
  176. package/dist/postgres/sql/0002_integration_event_outbox.sql +13 -0
  177. package/dist/postgres/sql/0003_document_number_counter.sql +6 -0
  178. package/dist/postgres/sql-failure.d.ts +19 -0
  179. package/dist/postgres/sql-failure.js +22 -0
  180. package/dist/postgres/store-failure.d.ts +17 -0
  181. package/dist/postgres/store-failure.js +16 -0
  182. package/dist/postgres/transaction-boundary.d.ts +13 -0
  183. package/dist/postgres/transaction-boundary.js +21 -0
  184. package/dist/publishing/event-publisher.sns.d.ts +66 -0
  185. package/dist/publishing/event-publisher.sns.js +75 -0
  186. package/dist/publishing/event-publisher.stdout.d.ts +15 -0
  187. package/dist/publishing/event-publisher.stdout.js +24 -0
  188. package/dist/publishing/index.d.ts +10 -0
  189. package/dist/publishing/index.js +10 -0
  190. package/dist/publishing/layer.d.ts +25 -0
  191. package/dist/publishing/layer.js +39 -0
  192. package/dist/publishing/settings.d.ts +60 -0
  193. package/dist/publishing/settings.js +85 -0
  194. package/dist/queue/consumer.d.ts +91 -0
  195. package/dist/queue/consumer.js +92 -0
  196. package/dist/queue/envelope.d.ts +39 -0
  197. package/dist/queue/envelope.js +39 -0
  198. package/dist/queue/failures.d.ts +33 -0
  199. package/dist/queue/failures.js +15 -0
  200. package/dist/queue/index.d.ts +14 -0
  201. package/dist/queue/index.js +14 -0
  202. package/dist/queue/layer.d.ts +33 -0
  203. package/dist/queue/layer.js +58 -0
  204. package/dist/queue/message-codec.d.ts +43 -0
  205. package/dist/queue/message-codec.js +33 -0
  206. package/dist/queue/queue-message-producer.d.ts +61 -0
  207. package/dist/queue/queue-message-producer.js +52 -0
  208. package/dist/queue/queue-message-source.d.ts +93 -0
  209. package/dist/queue/queue-message-source.js +86 -0
  210. package/dist/queue/readiness.d.ts +78 -0
  211. package/dist/queue/readiness.js +86 -0
  212. package/dist/queue/settings.d.ts +106 -0
  213. package/dist/queue/settings.js +160 -0
  214. package/dist/storage/blob-store.d.ts +84 -0
  215. package/dist/storage/blob-store.js +109 -0
  216. package/dist/storage/index.d.ts +9 -0
  217. package/dist/storage/index.js +9 -0
  218. package/dist/storage/layer.d.ts +17 -0
  219. package/dist/storage/layer.js +30 -0
  220. package/dist/storage/settings.d.ts +48 -0
  221. package/dist/storage/settings.js +65 -0
  222. package/dist/testing/blob-store.d.ts +27 -0
  223. package/dist/testing/blob-store.js +45 -0
  224. package/dist/testing/clock.d.ts +29 -0
  225. package/dist/testing/clock.js +41 -0
  226. package/dist/testing/dna-perturbator/attention.d.ts +55 -0
  227. package/dist/testing/dna-perturbator/attention.js +49 -0
  228. package/dist/testing/dna-perturbator/chains.d.ts +31 -0
  229. package/dist/testing/dna-perturbator/chains.js +53 -0
  230. package/dist/testing/dna-perturbator/report.d.ts +12 -0
  231. package/dist/testing/dna-perturbator/report.js +22 -0
  232. package/dist/testing/dna-perturbator/verdict.d.ts +26 -0
  233. package/dist/testing/dna-perturbator/verdict.js +28 -0
  234. package/dist/testing/dna-perturbator.d.ts +48 -0
  235. package/dist/testing/dna-perturbator.js +145 -0
  236. package/dist/testing/document-number-counter.d.ts +29 -0
  237. package/dist/testing/document-number-counter.js +39 -0
  238. package/dist/testing/event-publisher.d.ts +28 -0
  239. package/dist/testing/event-publisher.js +33 -0
  240. package/dist/testing/external-http-client.d.ts +29 -0
  241. package/dist/testing/external-http-client.js +49 -0
  242. package/dist/testing/index.d.ts +24 -0
  243. package/dist/testing/index.js +24 -0
  244. package/dist/testing/integration-event-outbox.d.ts +37 -0
  245. package/dist/testing/integration-event-outbox.js +67 -0
  246. package/dist/testing/mutation-settings.d.ts +71 -0
  247. package/dist/testing/mutation-settings.js +57 -0
  248. package/dist/testing/postgres-rows.d.ts +12 -0
  249. package/dist/testing/postgres-rows.js +19 -0
  250. package/dist/testing/processed-event-registry.d.ts +25 -0
  251. package/dist/testing/processed-event-registry.js +39 -0
  252. package/dist/testing/queue-message-producer.d.ts +27 -0
  253. package/dist/testing/queue-message-producer.js +41 -0
  254. package/dist/testing/queue-message-source.d.ts +54 -0
  255. package/dist/testing/queue-message-source.js +71 -0
  256. package/dist/testing/quiet-reporter.d.ts +86 -0
  257. package/dist/testing/quiet-reporter.js +81 -0
  258. package/dist/testing/readiness-probe.d.ts +27 -0
  259. package/dist/testing/readiness-probe.js +33 -0
  260. package/dist/testing/scenario.d.ts +94 -0
  261. package/dist/testing/scenario.js +81 -0
  262. package/dist/testing/transaction-boundary.d.ts +30 -0
  263. package/dist/testing/transaction-boundary.js +36 -0
  264. package/dist/testing/typed-failure.d.ts +8 -0
  265. package/dist/testing/typed-failure.js +15 -0
  266. package/dist/time/calendar-day.d.ts +83 -0
  267. package/dist/time/calendar-day.js +112 -0
  268. package/dist/time/failures.d.ts +51 -0
  269. package/dist/time/failures.js +56 -0
  270. package/dist/time/index.d.ts +11 -0
  271. package/dist/time/index.js +11 -0
  272. package/dist/time/instant.d.ts +64 -0
  273. package/dist/time/instant.js +67 -0
  274. package/dist/time/period.d.ts +45 -0
  275. package/dist/time/period.js +55 -0
  276. package/dist/vitest/container-reuse.d.ts +14 -0
  277. package/dist/vitest/container-reuse.js +15 -0
  278. package/dist/vitest/dotenv.d.ts +16 -0
  279. package/dist/vitest/dotenv.js +48 -0
  280. package/dist/vitest/effect-single-instance.d.ts +36 -0
  281. package/dist/vitest/effect-single-instance.js +125 -0
  282. package/dist/vitest/fast-check-single-instance.d.ts +11 -0
  283. package/dist/vitest/fast-check-single-instance.js +26 -0
  284. package/dist/vitest/index.d.ts +31 -0
  285. package/dist/vitest/index.js +30 -0
  286. package/dist/vitest/localstack-container.d.ts +32 -0
  287. package/dist/vitest/localstack-container.js +55 -0
  288. package/dist/vitest/port-contract-tester.d.ts +8 -0
  289. package/dist/vitest/port-contract-tester.js +1 -0
  290. package/dist/vitest/port-contracts/blob-store.contract.d.ts +22 -0
  291. package/dist/vitest/port-contracts/blob-store.contract.js +108 -0
  292. package/dist/vitest/port-contracts/document-number-counter.contract.d.ts +18 -0
  293. package/dist/vitest/port-contracts/document-number-counter.contract.js +90 -0
  294. package/dist/vitest/port-contracts/event-publisher.contract.d.ts +35 -0
  295. package/dist/vitest/port-contracts/event-publisher.contract.js +67 -0
  296. package/dist/vitest/port-contracts/external-http-client.contract.d.ts +35 -0
  297. package/dist/vitest/port-contracts/external-http-client.contract.js +52 -0
  298. package/dist/vitest/port-contracts/integration-event-outbox.contract.d.ts +23 -0
  299. package/dist/vitest/port-contracts/integration-event-outbox.contract.js +75 -0
  300. package/dist/vitest/port-contracts/processed-event-registry.contract.d.ts +18 -0
  301. package/dist/vitest/port-contracts/processed-event-registry.contract.js +84 -0
  302. package/dist/vitest/port-contracts/queue-message-producer.contract.d.ts +26 -0
  303. package/dist/vitest/port-contracts/queue-message-producer.contract.js +48 -0
  304. package/dist/vitest/port-contracts/queue-message-source.contract.d.ts +29 -0
  305. package/dist/vitest/port-contracts/queue-message-source.contract.js +71 -0
  306. package/dist/vitest/port-contracts/readiness-probe.contract.d.ts +18 -0
  307. package/dist/vitest/port-contracts/readiness-probe.contract.js +41 -0
  308. package/dist/vitest/port-contracts/transaction-boundary.contract.d.ts +21 -0
  309. package/dist/vitest/port-contracts/transaction-boundary.contract.js +64 -0
  310. package/dist/vitest/postgres-container.d.ts +57 -0
  311. package/dist/vitest/postgres-container.js +118 -0
  312. package/dist/vitest/reader-port-contract.d.ts +41 -0
  313. package/dist/vitest/reader-port-contract.js +43 -0
  314. package/dist/vitest/repo-source-files.d.ts +37 -0
  315. package/dist/vitest/repo-source-files.js +61 -0
  316. package/dist/vitest/reset-tables.d.ts +18 -0
  317. package/dist/vitest/reset-tables.js +30 -0
  318. package/dist/vitest/settings-contract.d.ts +38 -0
  319. package/dist/vitest/settings-contract.js +77 -0
  320. package/dist/vitest/stub-server.d.ts +43 -0
  321. package/dist/vitest/stub-server.js +60 -0
  322. package/dist/vitest/term-registry.json +730 -0
  323. package/dist/vitest/testclock-fork-isolated-files.d.ts +13 -0
  324. package/dist/vitest/testclock-fork-isolated-files.js +18 -0
  325. package/dist/vitest/testclock-fork-isolation.d.ts +77 -0
  326. package/dist/vitest/testclock-fork-isolation.js +188 -0
  327. package/dist/workflow/claim-once.d.ts +16 -0
  328. package/dist/workflow/claim-once.js +9 -0
  329. package/dist/workflow/failures.d.ts +47 -0
  330. package/dist/workflow/failures.js +22 -0
  331. package/dist/workflow/index.d.ts +12 -0
  332. package/dist/workflow/index.js +12 -0
  333. package/dist/workflow/on-claim.d.ts +17 -0
  334. package/dist/workflow/on-claim.js +8 -0
  335. package/dist/workflow/publish-pending-events.d.ts +31 -0
  336. package/dist/workflow/publish-pending-events.js +31 -0
  337. package/dist/workflow/transactionally.d.ts +8 -0
  338. package/dist/workflow/transactionally.js +8 -0
  339. package/dist/workflow/versioned-payload.d.ts +35 -0
  340. package/dist/workflow/versioned-payload.js +43 -0
  341. package/package.json +309 -0
@@ -0,0 +1,58 @@
1
+ import { refusalText } from '@satorio/machinery/core';
2
+ import { QueueMessageProducer, QueueMessageSource, } from '@satorio/machinery/ports';
3
+ import { Effect, Layer, Option } from 'effect';
4
+ import { makeSqsQueueMessageProducer, openSqsSendTransport, queueMessageProducerUnavailableWithoutConfiguration, scopedSqsSendTransport, } from './queue-message-producer.js';
5
+ import { makeSqsQueueMessageSource, openSqsTransport, queueMessageSourceUnavailableWithoutConfiguration, scopedSqsTransport, } from './queue-message-source.js';
6
+ import { configuredQueueUrl, queueConsumerSettings, queueProducerSettings, queueUrlRefusal, } from './settings.js';
7
+ /**
8
+ * A message source built from environment variables with the given
9
+ * prefix. With no queue URL set it mounts the loud stand and logs the
10
+ * one refusal every later receive repeats, so startup carries on and
11
+ * nothing goes missing in silence. The transport is a parameter, so a
12
+ * test substitutes its own without touching the wiring.
13
+ *
14
+ * @internal
15
+ */
16
+ export const queueMessageSourceFromEnvironmentLive = (variablePrefix, openTransport) => Layer.unwrapEffect(Effect.gen(function* () {
17
+ const configured = yield* configuredQueueUrl(variablePrefix);
18
+ if (Option.isNone(configured)) {
19
+ const refusal = queueUrlRefusal(variablePrefix);
20
+ yield* Effect.logError(refusalText(refusal));
21
+ return Layer.succeed(QueueMessageSource, queueMessageSourceUnavailableWithoutConfiguration(refusal));
22
+ }
23
+ return Layer.scoped(QueueMessageSource, Effect.gen(function* () {
24
+ const settings = yield* queueConsumerSettings(variablePrefix);
25
+ const transport = yield* scopedSqsTransport(() => openTransport(settings));
26
+ return makeSqsQueueMessageSource(transport, settings);
27
+ }));
28
+ }));
29
+ /**
30
+ * The message source on the real AWS SDK transport, reading the
31
+ * variables this prefix names.
32
+ */
33
+ export const sqsQueueMessageSourceLive = (variablePrefix) => queueMessageSourceFromEnvironmentLive(variablePrefix, openSqsTransport);
34
+ /**
35
+ * A message producer built from environment variables with the given
36
+ * prefix, mounting the loud stand when no queue URL is set. The
37
+ * transport is a parameter for the same reason the source's is.
38
+ *
39
+ * @internal
40
+ */
41
+ export const queueMessageProducerFromEnvironmentLive = (variablePrefix, openTransport) => Layer.unwrapEffect(Effect.gen(function* () {
42
+ const configured = yield* configuredQueueUrl(variablePrefix);
43
+ if (Option.isNone(configured)) {
44
+ const refusal = queueUrlRefusal(variablePrefix);
45
+ yield* Effect.logError(refusalText(refusal));
46
+ return Layer.succeed(QueueMessageProducer, queueMessageProducerUnavailableWithoutConfiguration(refusal));
47
+ }
48
+ return Layer.scoped(QueueMessageProducer, Effect.gen(function* () {
49
+ const settings = yield* queueProducerSettings(variablePrefix);
50
+ const transport = yield* scopedSqsSendTransport(() => openTransport(settings));
51
+ return makeSqsQueueMessageProducer(transport, settings);
52
+ }));
53
+ }));
54
+ /**
55
+ * The message producer on the real AWS SDK transport, reading the
56
+ * variables this prefix names.
57
+ */
58
+ export const sqsQueueMessageProducerLive = (variablePrefix) => queueMessageProducerFromEnvironmentLive(variablePrefix, openSqsSendTransport);
@@ -0,0 +1,43 @@
1
+ import { type VersionedEventDefinition } from '@satorio/machinery/workflow';
2
+ import { Effect, Schema } from 'effect';
3
+ import { StoredEventEnvelope } from './envelope.js';
4
+ import { QueueMessageNotDecodableError } from './failures.js';
5
+ /**
6
+ * The envelope as it travels: the JSON text on the wire, read and written
7
+ * through one schema.
8
+ */
9
+ export declare const QueueMessageBody: Schema.transform<Schema.SchemaClass<unknown, string, never>, Schema.Struct<{
10
+ eventId: typeof Schema.NonEmptyTrimmedString;
11
+ eventType: typeof Schema.NonEmptyTrimmedString;
12
+ schemaVersion: Schema.brand<Schema.filter<typeof Schema.Int>, "SchemaVersion">;
13
+ occurredAt: typeof Schema.DateTimeUtc;
14
+ payload: Schema.Record$<typeof Schema.String, typeof Schema.Unknown>;
15
+ }>>;
16
+ /**
17
+ * Reads a message body into an envelope, or refuses at the envelope stage and
18
+ * says what it could not read.
19
+ */
20
+ export declare const decodeQueueMessageBody: (body: string) => Effect.Effect<StoredEventEnvelope, QueueMessageNotDecodableError>;
21
+ /**
22
+ * What turns a stored payload of some version into the event a handler works
23
+ * with.
24
+ */
25
+ export type PayloadDecoder<A> = (storedVersion: number, payload: unknown) => Effect.Effect<A, QueueMessageNotDecodableError>;
26
+ /**
27
+ * Builds the payload decoder for one event definition, climbing a stored
28
+ * payload up to the version this code knows.
29
+ */
30
+ export declare const payloadDecoderFor: <S extends Schema.Schema.AnyNoContext>(definition: VersionedEventDefinition<S>) => PayloadDecoder<Schema.Schema.Type<S>>;
31
+ /**
32
+ * Builds the same envelope contract, but for sending: the producer sets
33
+ * exactly the fields the consumer expects to read.
34
+ */
35
+ export declare const queueMessageBodyOf: (envelope: {
36
+ readonly eventId: string;
37
+ readonly eventType: string;
38
+ readonly schemaVersion: number;
39
+ readonly occurredAtIso: string;
40
+ readonly payload: {
41
+ readonly [key: string]: unknown;
42
+ };
43
+ }) => string;
@@ -0,0 +1,33 @@
1
+ import { decodeStoredPayload, } from '@satorio/machinery/workflow';
2
+ import { Effect, Schema } from 'effect';
3
+ import { StoredEventEnvelope } from './envelope.js';
4
+ import { QueueMessageNotDecodableError } from './failures.js';
5
+ /**
6
+ * The envelope as it travels: the JSON text on the wire, read and written
7
+ * through one schema.
8
+ */
9
+ export const QueueMessageBody = Schema.parseJson(StoredEventEnvelope).annotations({
10
+ identifier: 'QueueMessageBody',
11
+ });
12
+ const decodeBody = Schema.decode(QueueMessageBody);
13
+ /**
14
+ * Reads a message body into an envelope, or refuses at the envelope stage and
15
+ * says what it could not read.
16
+ */
17
+ export const decodeQueueMessageBody = (body) => decodeBody(body).pipe(Effect.mapError((cause) => new QueueMessageNotDecodableError({ stage: 'envelope', cause })));
18
+ /**
19
+ * Builds the payload decoder for one event definition, climbing a stored
20
+ * payload up to the version this code knows.
21
+ */
22
+ export const payloadDecoderFor = (definition) => (storedVersion, payload) => decodeStoredPayload(definition, storedVersion, payload).pipe(Effect.mapError((cause) => new QueueMessageNotDecodableError({ stage: 'payload', cause })));
23
+ /**
24
+ * Builds the same envelope contract, but for sending: the producer sets
25
+ * exactly the fields the consumer expects to read.
26
+ */
27
+ export const queueMessageBodyOf = (envelope) => JSON.stringify({
28
+ eventId: envelope.eventId,
29
+ eventType: envelope.eventType,
30
+ schemaVersion: envelope.schemaVersion,
31
+ occurredAt: envelope.occurredAtIso,
32
+ payload: envelope.payload,
33
+ });
@@ -0,0 +1,61 @@
1
+ import { type Refusal } from '@satorio/machinery/core';
2
+ import { type QueueMessageProducerShape } from '@satorio/machinery/ports';
3
+ import { Effect, type Scope } from 'effect';
4
+ import { type QueueProducerSettings } from './settings.js';
5
+ /**
6
+ * What one send call asks for.
7
+ *
8
+ * @internal
9
+ */
10
+ export interface SqsSendRequest {
11
+ readonly QueueUrl: string;
12
+ readonly MessageBody: string;
13
+ }
14
+ /**
15
+ * The narrowest slice of the SDK the producer uses: put one body on the
16
+ * queue.
17
+ *
18
+ * @internal
19
+ */
20
+ export interface SqsSendTransport {
21
+ readonly sendMessage: (request: SqsSendRequest, signal?: AbortSignal) => Promise<unknown>;
22
+ }
23
+ /**
24
+ * The transport plus the one call that closes the client behind it.
25
+ *
26
+ * @internal
27
+ */
28
+ export interface ClosableSqsSendTransport extends SqsSendTransport {
29
+ readonly close: () => void;
30
+ }
31
+ /**
32
+ * The producer over one SQS transport: every send goes to the queue this
33
+ * prefix named.
34
+ *
35
+ * @internal
36
+ */
37
+ export declare const makeSqsQueueMessageProducer: (transport: SqsSendTransport, settings: QueueProducerSettings) => QueueMessageProducerShape;
38
+ /**
39
+ * Holds one sending transport open for the length of a scope and closes
40
+ * it when the scope ends.
41
+ *
42
+ * @internal
43
+ */
44
+ export declare const scopedSqsSendTransport: (openTransport: () => ClosableSqsSendTransport) => Effect.Effect<SqsSendTransport, never, Scope.Scope>;
45
+ /**
46
+ * Opens the real SQS client. This is the only place the sending half of
47
+ * the SDK is constructed.
48
+ *
49
+ * @internal
50
+ */
51
+ export declare const openSqsSendTransport: (settings: QueueProducerSettings) => ClosableSqsSendTransport;
52
+ /**
53
+ * Without a configured queue, the producer does not fail service
54
+ * startup: it mounts a stand that fails `send` loudly with the same
55
+ * three-part refusal the mount desk logged. The rest of the service
56
+ * keeps running, and the procedure that wanted to send says honestly
57
+ * that the queue is not configured instead of losing what it sent.
58
+ *
59
+ * @internal
60
+ */
61
+ export declare const queueMessageProducerUnavailableWithoutConfiguration: (refusal: Refusal) => QueueMessageProducerShape;
@@ -0,0 +1,52 @@
1
+ import { SendMessageCommand, SQSClient } from '@aws-sdk/client-sqs';
2
+ import { refusalText } from '@satorio/machinery/core';
3
+ import { QueueMessageProducerUnavailableError, } from '@satorio/machinery/ports';
4
+ import { Effect } from 'effect';
5
+ import { sqsClientConfigurationOf, } from './settings.js';
6
+ /**
7
+ * The producer over one SQS transport: every send goes to the queue this
8
+ * prefix named.
9
+ *
10
+ * @internal
11
+ */
12
+ export const makeSqsQueueMessageProducer = (transport, settings) => ({
13
+ send: (body) => Effect.tryPromise({
14
+ try: (signal) => transport.sendMessage({ QueueUrl: settings.queueUrl, MessageBody: body }, signal),
15
+ catch: (cause) => new QueueMessageProducerUnavailableError({ operation: 'send', cause }),
16
+ }).pipe(Effect.asVoid),
17
+ });
18
+ /**
19
+ * Holds one sending transport open for the length of a scope and closes
20
+ * it when the scope ends.
21
+ *
22
+ * @internal
23
+ */
24
+ export const scopedSqsSendTransport = (openTransport) => Effect.acquireRelease(Effect.sync(openTransport), (transport) => Effect.sync(() => transport.close()));
25
+ /**
26
+ * Opens the real SQS client. This is the only place the sending half of
27
+ * the SDK is constructed.
28
+ *
29
+ * @internal
30
+ */
31
+ export const openSqsSendTransport = (settings) => {
32
+ const client = new SQSClient(sqsClientConfigurationOf(settings));
33
+ return {
34
+ sendMessage: (request, signal) => client.send(new SendMessageCommand(request), signal === undefined ? {} : { abortSignal: signal }),
35
+ close: () => client.destroy(),
36
+ };
37
+ };
38
+ /**
39
+ * Without a configured queue, the producer does not fail service
40
+ * startup: it mounts a stand that fails `send` loudly with the same
41
+ * three-part refusal the mount desk logged. The rest of the service
42
+ * keeps running, and the procedure that wanted to send says honestly
43
+ * that the queue is not configured instead of losing what it sent.
44
+ *
45
+ * @internal
46
+ */
47
+ export const queueMessageProducerUnavailableWithoutConfiguration = (refusal) => ({
48
+ send: () => Effect.fail(new QueueMessageProducerUnavailableError({
49
+ operation: 'send',
50
+ cause: refusalText(refusal),
51
+ })),
52
+ });
@@ -0,0 +1,93 @@
1
+ import { type Refusal } from '@satorio/machinery/core';
2
+ import { type QueueMessageSourceShape } from '@satorio/machinery/ports';
3
+ import { Effect, type Scope } from 'effect';
4
+ import { type QueueConsumerSettings } from './settings.js';
5
+ /**
6
+ * One message as SQS hands it over, before anything checks that the
7
+ * fields a consumer needs are there.
8
+ *
9
+ * @internal
10
+ */
11
+ export interface SqsReceivedMessage {
12
+ readonly MessageId?: string | undefined;
13
+ readonly ReceiptHandle?: string | undefined;
14
+ readonly Body?: string | undefined;
15
+ }
16
+ /**
17
+ * What one receive call answers with.
18
+ *
19
+ * @internal
20
+ */
21
+ export interface SqsReceiveResult {
22
+ readonly Messages?: readonly SqsReceivedMessage[] | undefined;
23
+ }
24
+ /**
25
+ * What one receive call asks for.
26
+ *
27
+ * @internal
28
+ */
29
+ export interface SqsReceiveRequest {
30
+ readonly QueueUrl: string;
31
+ readonly MaxNumberOfMessages: number;
32
+ readonly WaitTimeSeconds: number;
33
+ readonly VisibilityTimeout: number;
34
+ }
35
+ /**
36
+ * What one acknowledgement asks for.
37
+ *
38
+ * @internal
39
+ */
40
+ export interface SqsDeleteRequest {
41
+ readonly QueueUrl: string;
42
+ readonly ReceiptHandle: string;
43
+ }
44
+ /**
45
+ * The transport is the narrowest slice of the SDK the source uses:
46
+ * receive a batch and delete what was taken. A test can supply its own
47
+ * object of this shape, needing neither the network nor a mock of the
48
+ * whole client.
49
+ *
50
+ * @internal
51
+ */
52
+ export interface SqsMessageTransport {
53
+ readonly receiveMessages: (request: SqsReceiveRequest, signal?: AbortSignal) => Promise<SqsReceiveResult>;
54
+ readonly deleteMessage: (request: SqsDeleteRequest, signal?: AbortSignal) => Promise<unknown>;
55
+ }
56
+ /**
57
+ * The transport plus the one call that closes the client behind it.
58
+ *
59
+ * @internal
60
+ */
61
+ export interface ClosableSqsTransport extends SqsMessageTransport {
62
+ readonly close: () => void;
63
+ }
64
+ /**
65
+ * The message source over one SQS transport: receive a batch with the
66
+ * poll settings this prefix named, and acknowledge by deleting.
67
+ *
68
+ * @internal
69
+ */
70
+ export declare const makeSqsQueueMessageSource: (transport: SqsMessageTransport, settings: QueueConsumerSettings) => QueueMessageSourceShape;
71
+ /**
72
+ * Holds one transport open for the length of a scope and closes it when
73
+ * the scope ends.
74
+ *
75
+ * @internal
76
+ */
77
+ export declare const scopedSqsTransport: (openTransport: () => ClosableSqsTransport) => Effect.Effect<SqsMessageTransport, never, Scope.Scope>;
78
+ /**
79
+ * Opens the real SQS client. This is the only place the receiving half
80
+ * of the SDK is constructed.
81
+ *
82
+ * @internal
83
+ */
84
+ export declare const openSqsTransport: (settings: QueueConsumerSettings) => ClosableSqsTransport;
85
+ /**
86
+ * Without a configured queue, the source does not fail service startup:
87
+ * it mounts a stand that fails `receive` and `acknowledge` loudly with
88
+ * the same three-part refusal the mount desk logged. A consumer polling
89
+ * an unconfigured queue says so on every beat instead of sitting quiet.
90
+ *
91
+ * @internal
92
+ */
93
+ export declare const queueMessageSourceUnavailableWithoutConfiguration: (refusal: Refusal) => QueueMessageSourceShape;
@@ -0,0 +1,86 @@
1
+ import { DeleteMessageCommand, ReceiveMessageCommand, SQSClient, } from '@aws-sdk/client-sqs';
2
+ import { refusalText } from '@satorio/machinery/core';
3
+ import { QueueMessageSourceUnavailableError, } from '@satorio/machinery/ports';
4
+ import { Effect } from 'effect';
5
+ import { sqsClientConfigurationOf, } from './settings.js';
6
+ const MISSING_FIELD_NAMES = ['MessageId', 'ReceiptHandle', 'Body'];
7
+ const missingFieldNamesOf = (message) => MISSING_FIELD_NAMES.filter((name) => message[name] === undefined);
8
+ const rawMessageOf = (message) => {
9
+ const { MessageId, ReceiptHandle, Body } = message;
10
+ if (MessageId === undefined ||
11
+ ReceiptHandle === undefined ||
12
+ Body === undefined) {
13
+ return Effect.fail(new QueueMessageSourceUnavailableError({
14
+ operation: 'receive',
15
+ cause: `SQS returned a message missing required fields: ${missingFieldNamesOf(message).join(', ')}`,
16
+ }));
17
+ }
18
+ return Effect.succeed({
19
+ messageId: MessageId,
20
+ receiptHandle: ReceiptHandle,
21
+ body: Body,
22
+ });
23
+ };
24
+ /**
25
+ * The message source over one SQS transport: receive a batch with the
26
+ * poll settings this prefix named, and acknowledge by deleting.
27
+ *
28
+ * @internal
29
+ */
30
+ export const makeSqsQueueMessageSource = (transport, settings) => ({
31
+ receive: Effect.tryPromise({
32
+ try: (signal) => transport.receiveMessages({
33
+ QueueUrl: settings.queueUrl,
34
+ MaxNumberOfMessages: settings.maxMessagesPerReceive,
35
+ WaitTimeSeconds: settings.waitTimeSeconds,
36
+ VisibilityTimeout: settings.visibilityTimeoutSeconds,
37
+ }, signal),
38
+ catch: (cause) => new QueueMessageSourceUnavailableError({ operation: 'receive', cause }),
39
+ }).pipe(Effect.flatMap((result) => Effect.forEach(result.Messages ?? [], rawMessageOf))),
40
+ acknowledge: (receiptHandle) => Effect.tryPromise({
41
+ try: (signal) => transport.deleteMessage({ QueueUrl: settings.queueUrl, ReceiptHandle: receiptHandle }, signal),
42
+ catch: (cause) => new QueueMessageSourceUnavailableError({
43
+ operation: 'acknowledge',
44
+ cause,
45
+ }),
46
+ }).pipe(Effect.asVoid),
47
+ });
48
+ /**
49
+ * Holds one transport open for the length of a scope and closes it when
50
+ * the scope ends.
51
+ *
52
+ * @internal
53
+ */
54
+ export const scopedSqsTransport = (openTransport) => Effect.acquireRelease(Effect.sync(openTransport), (transport) => Effect.sync(() => transport.close()));
55
+ /**
56
+ * Opens the real SQS client. This is the only place the receiving half
57
+ * of the SDK is constructed.
58
+ *
59
+ * @internal
60
+ */
61
+ export const openSqsTransport = (settings) => {
62
+ const client = new SQSClient(sqsClientConfigurationOf(settings));
63
+ return {
64
+ receiveMessages: (request, signal) => client.send(new ReceiveMessageCommand(request), signal === undefined ? {} : { abortSignal: signal }),
65
+ deleteMessage: (request, signal) => client.send(new DeleteMessageCommand(request), signal === undefined ? {} : { abortSignal: signal }),
66
+ close: () => client.destroy(),
67
+ };
68
+ };
69
+ /**
70
+ * Without a configured queue, the source does not fail service startup:
71
+ * it mounts a stand that fails `receive` and `acknowledge` loudly with
72
+ * the same three-part refusal the mount desk logged. A consumer polling
73
+ * an unconfigured queue says so on every beat instead of sitting quiet.
74
+ *
75
+ * @internal
76
+ */
77
+ export const queueMessageSourceUnavailableWithoutConfiguration = (refusal) => ({
78
+ receive: Effect.fail(new QueueMessageSourceUnavailableError({
79
+ operation: 'receive',
80
+ cause: refusalText(refusal),
81
+ })),
82
+ acknowledge: () => Effect.fail(new QueueMessageSourceUnavailableError({
83
+ operation: 'acknowledge',
84
+ cause: refusalText(refusal),
85
+ })),
86
+ });
@@ -0,0 +1,78 @@
1
+ import { type GetQueueAttributesCommandInput } from '@aws-sdk/client-sqs';
2
+ import { QueueMessageSourceUnavailableError } from '@satorio/machinery/ports';
3
+ import { type ConfigError, Effect, Option, type Scope } from 'effect';
4
+ import { type QueueConsumerSettings } from './settings.js';
5
+ /**
6
+ * How long to wait for an SQS reply before treating the queue as
7
+ * unavailable. Without a deadline, a hung network keeps the readiness
8
+ * probe open indefinitely — the same class of gap as the Postgres probe.
9
+ *
10
+ * @internal
11
+ */
12
+ export declare const QUEUE_READINESS_DEADLINE_MILLIS = 2000;
13
+ /**
14
+ * What the probe asks SQS: one attribute of one queue.
15
+ * `GetQueueAttributes` reads nothing off the queue, unlike receive,
16
+ * which polls and hides messages while it does.
17
+ *
18
+ * @internal
19
+ */
20
+ export declare const probeRequestOf: (queueUrl: string) => GetQueueAttributesCommandInput;
21
+ /**
22
+ * The one call the probe makes: read an attribute of the queue. It takes
23
+ * no message off the queue, unlike receive.
24
+ *
25
+ * @internal
26
+ */
27
+ export interface SqsProbeTransport {
28
+ readonly describeQueue: (queueUrl: string, signal?: AbortSignal) => Promise<unknown>;
29
+ }
30
+ /**
31
+ * The probe transport plus the one call that closes the client behind
32
+ * it.
33
+ *
34
+ * @internal
35
+ */
36
+ export interface ClosableSqsProbeTransport extends SqsProbeTransport {
37
+ readonly close: () => void;
38
+ }
39
+ /**
40
+ * Opens the client the probe asks with. `GetQueueAttributes` is the
41
+ * cheapest call SQS offers: it reads one attribute and takes nothing off
42
+ * the queue.
43
+ *
44
+ * @internal
45
+ */
46
+ export declare const openSqsProbeTransport: (settings: QueueConsumerSettings) => ClosableSqsProbeTransport;
47
+ /**
48
+ * Holds the probe's client open for the length of a scope and closes it
49
+ * when the scope ends — including the scope an interruption ends, which
50
+ * a `finally` block around a promise does not reach.
51
+ *
52
+ * @internal
53
+ */
54
+ export declare const scopedSqsProbeTransport: (openTransport: () => ClosableSqsProbeTransport) => Effect.Effect<SqsProbeTransport, never, Scope.Scope>;
55
+ /**
56
+ * Pings queue readiness. The client lives for exactly one call — the
57
+ * probe runs rarely, so a long-lived client is not worth it. The SDK
58
+ * call carries Effect's own `abortSignal`, so an interruption cancels
59
+ * the promise through that same signal: the deadline stops the network
60
+ * call itself, not just the wait for it. The transport is a parameter,
61
+ * so a test answers without a network.
62
+ *
63
+ * @internal
64
+ */
65
+ export declare const pingQueueMessageSourceWith: (settings: QueueConsumerSettings, openTransport: (settings: QueueConsumerSettings) => ClosableSqsProbeTransport) => Effect.Effect<void, QueueMessageSourceUnavailableError>;
66
+ /**
67
+ * Pings queue readiness against the real SQS client.
68
+ *
69
+ * @internal
70
+ */
71
+ export declare const pingQueueMessageSource: (settings: QueueConsumerSettings) => Effect.Effect<void, QueueMessageSourceUnavailableError>;
72
+ /**
73
+ * The readiness check for a queue, absent when no queue is mounted at all.
74
+ *
75
+ * A queue without a URL is never mounted at all, so its readiness probe is
76
+ * `None`: readyz does not ask about something the application does not have.
77
+ */
78
+ export declare const queueReadinessCheck: (variablePrefix: string) => Effect.Effect<Option.Option<Effect.Effect<void, QueueMessageSourceUnavailableError>>, ConfigError.ConfigError>;
@@ -0,0 +1,86 @@
1
+ import { GetQueueAttributesCommand, SQSClient, } from '@aws-sdk/client-sqs';
2
+ import { QueueMessageSourceUnavailableError } from '@satorio/machinery/ports';
3
+ import { Duration, Effect, Option } from 'effect';
4
+ import { configuredQueueUrl, queueConsumerSettings, sqsClientConfigurationOf, } from './settings.js';
5
+ /**
6
+ * How long to wait for an SQS reply before treating the queue as
7
+ * unavailable. Without a deadline, a hung network keeps the readiness
8
+ * probe open indefinitely — the same class of gap as the Postgres probe.
9
+ *
10
+ * @internal
11
+ */
12
+ export const QUEUE_READINESS_DEADLINE_MILLIS = 2_000;
13
+ const QUEUE_ARN_ATTRIBUTE = 'QueueArn';
14
+ /**
15
+ * What the probe asks SQS: one attribute of one queue.
16
+ * `GetQueueAttributes` reads nothing off the queue, unlike receive,
17
+ * which polls and hides messages while it does.
18
+ *
19
+ * @internal
20
+ */
21
+ export const probeRequestOf = (queueUrl) => ({
22
+ QueueUrl: queueUrl,
23
+ AttributeNames: [QUEUE_ARN_ATTRIBUTE],
24
+ });
25
+ /**
26
+ * Opens the client the probe asks with. `GetQueueAttributes` is the
27
+ * cheapest call SQS offers: it reads one attribute and takes nothing off
28
+ * the queue.
29
+ *
30
+ * @internal
31
+ */
32
+ export const openSqsProbeTransport = (settings) => {
33
+ const client = new SQSClient(sqsClientConfigurationOf(settings));
34
+ return {
35
+ describeQueue: (queueUrl, signal) => client.send(new GetQueueAttributesCommand(probeRequestOf(queueUrl)), signal === undefined ? {} : { abortSignal: signal }),
36
+ close: () => client.destroy(),
37
+ };
38
+ };
39
+ /**
40
+ * Holds the probe's client open for the length of a scope and closes it
41
+ * when the scope ends — including the scope an interruption ends, which
42
+ * a `finally` block around a promise does not reach.
43
+ *
44
+ * @internal
45
+ */
46
+ export const scopedSqsProbeTransport = (openTransport) => Effect.acquireRelease(Effect.sync(openTransport), (transport) => Effect.sync(() => transport.close()));
47
+ const askWith = (transport, settings) => Effect.tryPromise({
48
+ try: (signal) => transport.describeQueue(settings.queueUrl, signal),
49
+ catch: (cause) => new QueueMessageSourceUnavailableError({ operation: 'ping', cause }),
50
+ }).pipe(Effect.asVoid);
51
+ /**
52
+ * Pings queue readiness. The client lives for exactly one call — the
53
+ * probe runs rarely, so a long-lived client is not worth it. The SDK
54
+ * call carries Effect's own `abortSignal`, so an interruption cancels
55
+ * the promise through that same signal: the deadline stops the network
56
+ * call itself, not just the wait for it. The transport is a parameter,
57
+ * so a test answers without a network.
58
+ *
59
+ * @internal
60
+ */
61
+ export const pingQueueMessageSourceWith = (settings, openTransport) => Effect.scoped(Effect.flatMap(scopedSqsProbeTransport(() => openTransport(settings)), (transport) => askWith(transport, settings))).pipe(Effect.timeoutFail({
62
+ duration: Duration.millis(QUEUE_READINESS_DEADLINE_MILLIS),
63
+ onTimeout: () => new QueueMessageSourceUnavailableError({
64
+ operation: 'ping',
65
+ cause: 'timed out waiting for a response',
66
+ }),
67
+ }));
68
+ /**
69
+ * Pings queue readiness against the real SQS client.
70
+ *
71
+ * @internal
72
+ */
73
+ export const pingQueueMessageSource = (settings) => pingQueueMessageSourceWith(settings, openSqsProbeTransport);
74
+ /**
75
+ * The readiness check for a queue, absent when no queue is mounted at all.
76
+ *
77
+ * A queue without a URL is never mounted at all, so its readiness probe is
78
+ * `None`: readyz does not ask about something the application does not have.
79
+ */
80
+ export const queueReadinessCheck = (variablePrefix) => Effect.gen(function* () {
81
+ const configured = yield* configuredQueueUrl(variablePrefix);
82
+ if (Option.isNone(configured))
83
+ return Option.none();
84
+ const settings = yield* queueConsumerSettings(variablePrefix);
85
+ return Option.some(pingQueueMessageSource(settings));
86
+ });