effect-jobs 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +22 -0
  3. package/README.md +142 -0
  4. package/dist/Job.d.ts +33 -0
  5. package/dist/Job.d.ts.map +1 -0
  6. package/dist/Job.js +66 -0
  7. package/dist/Job.js.map +1 -0
  8. package/dist/JobConsumer.d.ts +34 -0
  9. package/dist/JobConsumer.d.ts.map +1 -0
  10. package/dist/JobConsumer.js +28 -0
  11. package/dist/JobConsumer.js.map +1 -0
  12. package/dist/JobContract.d.ts +128 -0
  13. package/dist/JobContract.d.ts.map +1 -0
  14. package/dist/JobContract.js +15 -0
  15. package/dist/JobContract.js.map +1 -0
  16. package/dist/JobFailure.d.ts +51 -0
  17. package/dist/JobFailure.d.ts.map +1 -0
  18. package/dist/JobFailure.js +34 -0
  19. package/dist/JobFailure.js.map +1 -0
  20. package/dist/JobId.d.ts +5 -0
  21. package/dist/JobId.d.ts.map +1 -0
  22. package/dist/JobId.js +4 -0
  23. package/dist/JobId.js.map +1 -0
  24. package/dist/JobIdentity.d.ts +54 -0
  25. package/dist/JobIdentity.d.ts.map +1 -0
  26. package/dist/JobIdentity.js +82 -0
  27. package/dist/JobIdentity.js.map +1 -0
  28. package/dist/JobLifecycle.d.ts +173 -0
  29. package/dist/JobLifecycle.d.ts.map +1 -0
  30. package/dist/JobLifecycle.js +234 -0
  31. package/dist/JobLifecycle.js.map +1 -0
  32. package/dist/JobPayload.d.ts +18 -0
  33. package/dist/JobPayload.d.ts.map +1 -0
  34. package/dist/JobPayload.js +10 -0
  35. package/dist/JobPayload.js.map +1 -0
  36. package/dist/JobPayloadCodec.d.ts +14 -0
  37. package/dist/JobPayloadCodec.d.ts.map +1 -0
  38. package/dist/JobPayloadCodec.js +78 -0
  39. package/dist/JobPayloadCodec.js.map +1 -0
  40. package/dist/JobPolicy.d.ts +50 -0
  41. package/dist/JobPolicy.d.ts.map +1 -0
  42. package/dist/JobPolicy.js +85 -0
  43. package/dist/JobPolicy.js.map +1 -0
  44. package/dist/JobProducer.d.ts +14 -0
  45. package/dist/JobProducer.d.ts.map +1 -0
  46. package/dist/JobProducer.js +23 -0
  47. package/dist/JobProducer.js.map +1 -0
  48. package/dist/JobQueue.d.ts +16 -0
  49. package/dist/JobQueue.d.ts.map +1 -0
  50. package/dist/JobQueue.js +16 -0
  51. package/dist/JobQueue.js.map +1 -0
  52. package/dist/JobRegistry.d.ts +37 -0
  53. package/dist/JobRegistry.d.ts.map +1 -0
  54. package/dist/JobRegistry.js +47 -0
  55. package/dist/JobRegistry.js.map +1 -0
  56. package/dist/JobStore.d.ts +348 -0
  57. package/dist/JobStore.d.ts.map +1 -0
  58. package/dist/JobStore.js +19 -0
  59. package/dist/JobStore.js.map +1 -0
  60. package/dist/JobTelemetry.d.ts +7 -0
  61. package/dist/JobTelemetry.d.ts.map +1 -0
  62. package/dist/JobTelemetry.js +61 -0
  63. package/dist/JobTelemetry.js.map +1 -0
  64. package/dist/JobTransaction.d.ts +24 -0
  65. package/dist/JobTransaction.d.ts.map +1 -0
  66. package/dist/JobTransaction.js +7 -0
  67. package/dist/JobTransaction.js.map +1 -0
  68. package/dist/JobWorker.d.ts +24 -0
  69. package/dist/JobWorker.d.ts.map +1 -0
  70. package/dist/JobWorker.js +155 -0
  71. package/dist/JobWorker.js.map +1 -0
  72. package/dist/JobWorkerRuntime.d.ts +18 -0
  73. package/dist/JobWorkerRuntime.d.ts.map +1 -0
  74. package/dist/JobWorkerRuntime.js +5 -0
  75. package/dist/JobWorkerRuntime.js.map +1 -0
  76. package/dist/PollingJobWorker.d.ts +9 -0
  77. package/dist/PollingJobWorker.d.ts.map +1 -0
  78. package/dist/PollingJobWorker.js +54 -0
  79. package/dist/PollingJobWorker.js.map +1 -0
  80. package/dist/PostgreSqlDrizzleSchema.d.ts +432 -0
  81. package/dist/PostgreSqlDrizzleSchema.d.ts.map +1 -0
  82. package/dist/PostgreSqlDrizzleSchema.js +72 -0
  83. package/dist/PostgreSqlDrizzleSchema.js.map +1 -0
  84. package/dist/PostgreSqlJobs.d.ts +25 -0
  85. package/dist/PostgreSqlJobs.d.ts.map +1 -0
  86. package/dist/PostgreSqlJobs.js +38 -0
  87. package/dist/PostgreSqlJobs.js.map +1 -0
  88. package/dist/PostgreSqlSchema.d.ts +30 -0
  89. package/dist/PostgreSqlSchema.d.ts.map +1 -0
  90. package/dist/PostgreSqlSchema.js +63 -0
  91. package/dist/PostgreSqlSchema.js.map +1 -0
  92. package/dist/PostgreSqlTransaction.d.ts +42 -0
  93. package/dist/PostgreSqlTransaction.d.ts.map +1 -0
  94. package/dist/PostgreSqlTransaction.js +9 -0
  95. package/dist/PostgreSqlTransaction.js.map +1 -0
  96. package/dist/index.d.ts +7 -0
  97. package/dist/index.d.ts.map +1 -0
  98. package/dist/index.js +7 -0
  99. package/dist/index.js.map +1 -0
  100. package/dist/internal/JobTransaction.d.ts +16 -0
  101. package/dist/internal/JobTransaction.d.ts.map +1 -0
  102. package/dist/internal/JobTransaction.js +21 -0
  103. package/dist/internal/JobTransaction.js.map +1 -0
  104. package/dist/internal/codec/CanonicalJson.d.ts +9 -0
  105. package/dist/internal/codec/CanonicalJson.d.ts.map +1 -0
  106. package/dist/internal/codec/CanonicalJson.js +184 -0
  107. package/dist/internal/codec/CanonicalJson.js.map +1 -0
  108. package/dist/internal/codec/ProtectedProjection.d.ts +12 -0
  109. package/dist/internal/codec/ProtectedProjection.d.ts.map +1 -0
  110. package/dist/internal/codec/ProtectedProjection.js +121 -0
  111. package/dist/internal/codec/ProtectedProjection.js.map +1 -0
  112. package/dist/internal/lifecycle/Artifacts.d.ts +6 -0
  113. package/dist/internal/lifecycle/Artifacts.d.ts.map +1 -0
  114. package/dist/internal/lifecycle/Artifacts.js +49 -0
  115. package/dist/internal/lifecycle/Artifacts.js.map +1 -0
  116. package/dist/internal/lifecycle/Reconciliation.d.ts +82 -0
  117. package/dist/internal/lifecycle/Reconciliation.d.ts.map +1 -0
  118. package/dist/internal/lifecycle/Reconciliation.js +98 -0
  119. package/dist/internal/lifecycle/Reconciliation.js.map +1 -0
  120. package/dist/internal/postgresql/Producer.d.ts +14 -0
  121. package/dist/internal/postgresql/Producer.d.ts.map +1 -0
  122. package/dist/internal/postgresql/Producer.js +55 -0
  123. package/dist/internal/postgresql/Producer.js.map +1 -0
  124. package/dist/internal/postgresql/Readiness.d.ts +5 -0
  125. package/dist/internal/postgresql/Readiness.d.ts.map +1 -0
  126. package/dist/internal/postgresql/Readiness.js +53 -0
  127. package/dist/internal/postgresql/Readiness.js.map +1 -0
  128. package/dist/internal/postgresql/Rows.d.ts +45 -0
  129. package/dist/internal/postgresql/Rows.d.ts.map +1 -0
  130. package/dist/internal/postgresql/Rows.js +75 -0
  131. package/dist/internal/postgresql/Rows.js.map +1 -0
  132. package/dist/internal/postgresql/Store.d.ts +5 -0
  133. package/dist/internal/postgresql/Store.d.ts.map +1 -0
  134. package/dist/internal/postgresql/Store.js +211 -0
  135. package/dist/internal/postgresql/Store.js.map +1 -0
  136. package/dist/internal/worker/Capability.d.ts +106 -0
  137. package/dist/internal/worker/Capability.d.ts.map +1 -0
  138. package/dist/internal/worker/Capability.js +11 -0
  139. package/dist/internal/worker/Capability.js.map +1 -0
  140. package/dist/internal/worker/Drain.d.ts +22 -0
  141. package/dist/internal/worker/Drain.d.ts.map +1 -0
  142. package/dist/internal/worker/Drain.js +59 -0
  143. package/dist/internal/worker/Drain.js.map +1 -0
  144. package/dist/internal/worker/Execution.d.ts +7 -0
  145. package/dist/internal/worker/Execution.d.ts.map +1 -0
  146. package/dist/internal/worker/Execution.js +125 -0
  147. package/dist/internal/worker/Execution.js.map +1 -0
  148. package/dist/internal/worker/Results.d.ts +108 -0
  149. package/dist/internal/worker/Results.d.ts.map +1 -0
  150. package/dist/internal/worker/Results.js +3 -0
  151. package/dist/internal/worker/Results.js.map +1 -0
  152. package/package.json +169 -0
  153. package/specs/architecture-decisions.md +841 -0
  154. package/specs/core-contract.md +323 -0
  155. package/specs/drizzle-compatibility.md +167 -0
  156. package/specs/postgresql-backend.md +291 -0
  157. package/specs/release-qualification.md +107 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0-alpha.0
4
+
5
+ Initial alpha extraction of the Effect-native durable jobs mechanism from
6
+ MIT-licensed effect-auth, with application-owned domains and infrastructure.
7
+
8
+ - Schema-defined catalogs, typed producer slots and library-generated job IDs.
9
+ - Transaction-bound production and immutable semantic duplicate comparison.
10
+ - PostgreSQL two-table storage, fixed leases, fencing, retry and bounded recovery.
11
+ - Explicit scoped workers, bounded cleanup and protected-payload projection.
12
+ - Focused ESM exports and optional effect-native Drizzle migration declarations.
13
+
14
+ This is an alpha, not a production qualification claim. Exact versions and
15
+ unsupported cases are listed in README and the release qualification document.
16
+ No registry publication or cryptographic build provenance is claimed by this file.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 effect-jobs contributors
4
+ Copyright (c) 2026 effect-auth contributors
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # effect-jobs
2
+
3
+ Effect-native durable jobs with atomic, transaction-bound production. Initial
4
+ alpha: application-defined catalogs, semantic deduplication, fenced fixed leases,
5
+ persisted fixed-delay retries, bounded recovery and explicit scoped workers.
6
+ Applications own database pools, migrations, handlers, protection and domain receipts.
7
+
8
+ ## Install
9
+
10
+ ```sh
11
+ npm install effect-jobs@alpha effect@4.0.0
12
+ # Only when using the optional migration declarations:
13
+ npm install drizzle-orm@1.0.0-rc.5-169397b
14
+ ```
15
+
16
+ The root export is intentionally empty. Import the focused public modules:
17
+
18
+ ```ts
19
+ import { Schema } from "effect"
20
+ import * as Job from "effect-jobs/Job"
21
+ import * as JobQueue from "effect-jobs/JobQueue"
22
+ import * as JobProducer from "effect-jobs/JobProducer"
23
+ import * as JobPolicy from "effect-jobs/JobPolicy"
24
+ import { encodeJobPayload } from "effect-jobs/JobPayloadCodec"
25
+
26
+ export const BillingQueue = JobQueue.make("billing")
27
+ export const InvoiceProducer = JobProducer.make({
28
+ operation: "billing.issue-invoice",
29
+ slots: ["generate"]
30
+ })
31
+ export const GenerateInvoice = Job.make({
32
+ queue: BillingQueue,
33
+ kind: "invoice.generate",
34
+ version: 1,
35
+ payload: Schema.Struct({ invoiceId: Schema.String }),
36
+ encodePayload: encodeJobPayload
37
+ })
38
+ export const invoiceInput = (operationId: string, invoiceId: string) => ({
39
+ producer: InvoiceProducer.identity({ operationId, slot: "generate" }),
40
+ payload: { invoiceId },
41
+ policy: JobPolicy.make()
42
+ })
43
+ ```
44
+
45
+ Declare producers once and reuse a stable operation ID across business retries.
46
+ `GenerateInvoice.enqueue(jobsTx, invoiceInput(...))` requires the explicit scoped
47
+ transaction capability supplied by your backend's join callback. The library
48
+ assigns the job ID; a matching duplicate returns the original ID and retains its
49
+ first policy and availability. Changed catalog or semantic payload conflicts.
50
+ Results are provisional until the application's transaction commits.
51
+
52
+ ## PostgreSQL setup
53
+
54
+ `effect-jobs/PostgreSqlTransaction` defines the `PostgreSqlApplication` service
55
+ and trusted `ApplicationAdapter` contract. Your adapter must bind registered
56
+ handles to the exact active source, connection and lifetime. A query-shaped object
57
+ or matching DSN is insufficient. It delegates transaction ownership to your
58
+ application; joined enqueue must not borrow, open a savepoint, commit or replay.
59
+ Worker and cleanup transactions must commit before returning and reject an
60
+ ambient transaction. See the shipped [backend contract](specs/postgresql-backend.md).
61
+
62
+ ```ts
63
+ import { Effect, Layer } from "effect"
64
+ import * as PostgreSqlJobs from "effect-jobs/PostgreSqlJobs"
65
+ import * as PostgreSqlSchema from "effect-jobs/PostgreSqlSchema"
66
+ import { PostgreSqlApplication } from "effect-jobs/PostgreSqlTransaction"
67
+
68
+ const tables = PostgreSqlSchema.tables({ schema: "billing" })
69
+ // During application migration, after creating the schema:
70
+ const migrationSql = PostgreSqlSchema.migration(tables)
71
+ // applicationAdapter implements the full qualified contract above.
72
+ const jobsLayer = PostgreSqlJobs.layerNoDeps({
73
+ ...tables,
74
+ operationResponseBudgetMillis: 100
75
+ }).pipe(Layer.provide(Layer.succeed(PostgreSqlApplication, applicationAdapter)))
76
+ ```
77
+
78
+ The application executes `migrationSql` with its migration credentials, supplies
79
+ its adapter, and explicitly invokes backend `ready`. Runtime construction runs
80
+ no DDL and creates or closes no pool. Optional
81
+ `PostgreSqlDrizzleSchema.makeJobTables(tables)` supplies migration declarations;
82
+ it does not supply a universal Drizzle transaction adapter. The concrete native
83
+ qualification application is documented in
84
+ [Drizzle compatibility](specs/drizzle-compatibility.md).
85
+
86
+ ## Handlers, workers and retention
87
+
88
+ Install handlers with `definition.handlerLayer(execute, decodeJobPayload)` into
89
+ `JobRegistry.layer`. Handler input is `{ payload, context }`; context contains
90
+ job ID, catalog, producer and one-based attempt number. Provide handler services
91
+ through ordinary Layers. Map domain errors to `JobFailures.Retry`, `Dead`,
92
+ `Isolate` or `OutcomeUnknown` from `effect-jobs/JobFailure`.
93
+
94
+ Compose `JobWorker.layer(store, options)` with the registry and store, then call
95
+ `JobWorkerRuntime.drain(consumer)` for bounded work, or explicitly install
96
+ `PollingJobWorker.layerForPlan(plan, options)` in an application-owned Scope.
97
+ Use the same local concurrency for a queue across invocations. Imports and
98
+ handler installation do not start workers or cleanup.
99
+
100
+ Execution is at least once. Unknown outcomes and lease recovery can repeat a
101
+ handler; external effects need application idempotency or reconciliation. An
102
+ attempt number may repeat after recovery. Leases do not renew. No exactly-once
103
+ external delivery, server-crash coverage or Cloudflare coordinator is promised.
104
+
105
+ Default policy: 90-second lease, 30-second attempt timeout, 5-second fixed retry,
106
+ 3 finalized attempts, 1 stalled recovery, 90-day Completed retention and infinite
107
+ Dead retention. Generic cleanup is bounded and explicitly selected. Applications
108
+ with receipts or domain references must replace it with coordinated cleanup.
109
+ Pending, Active and Isolated jobs are never automatically purged. Removing all
110
+ identity evidence ends that job's deduplication window.
111
+
112
+ `JobPayload.protected(schema)` marks an already protected envelope with an own
113
+ `fingerprint` field; it does not encrypt. Applications seal/open sensitive data
114
+ and manage separate encryption and stable fingerprint keys. Preserve old
115
+ decryption keys while artifacts remain retained. Telemetry must exclude payloads,
116
+ identifiers, SQL, provider messages and secret material.
117
+
118
+ ## Support and development
119
+
120
+ Exact qualification pins: Node 24.15.0, Bun 1.4.2, Effect 4.0.0, PostgreSQL 16.15,
121
+ pg 8.23.0 and optional Drizzle 1.0.0-rc.5-169397b. Other versions are unqualified.
122
+ The npm engine range bounds installation to Node 24; it is not evidence for
123
+ every patch release. Full upstream Drizzle declarations fail strict checking;
124
+ the Drizzle consumer uses `skipLibCheck: true`. Non-Drizzle backend declarations
125
+ are separately checked with `skipLibCheck: false`.
126
+
127
+ See [release qualification](specs/release-qualification.md) for evidence scope,
128
+ reproduction and limitations, and [accepted decisions](specs/architecture-decisions.md)
129
+ for the full contracts. No recurring schedules, administration APIs, alternative
130
+ backend or deployment is included in this alpha.
131
+
132
+ ```sh
133
+ bun install --frozen-lockfile
134
+ bun run build
135
+ bun run verify
136
+ bun run check:postgresql
137
+ ```
138
+
139
+ Fixture dependencies also require frozen installs in `tests/postgresql` and
140
+ `tests/qualification/d6-pg`; native qualification installs its own exact peers.
141
+ Tools are patched explicitly by check/build/lint/test. Published consumers have
142
+ no installation lifecycle scripts. MIT; see [LICENSE](LICENSE).
package/dist/Job.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ import { Effect, Layer, Schema } from "effect";
2
+ import type { EnqueueInput, EnqueueResult, HandlerInput, JobPayloadDecoder, JobPayloadEncoder } from "./JobContract.js";
3
+ import type { JobFailure } from "./JobFailure.js";
4
+ import { CatalogIdentity } from "./JobIdentity.js";
5
+ import type { JobQueue } from "./JobQueue.js";
6
+ import { JobRegistry, type DuplicateJobHandler } from "./JobRegistry.js";
7
+ import type { JobEnqueueError, JobsTransaction } from "./JobTransaction.js";
8
+ declare const InvalidJobDefinition_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
9
+ readonly _tag: "InvalidJobDefinition";
10
+ } & Readonly<A>;
11
+ export declare class InvalidJobDefinition extends InvalidJobDefinition_base<{
12
+ readonly expected: string;
13
+ }> {
14
+ }
15
+ export interface JobDefinition<Payload extends Schema.Top = Schema.Top, Kind extends string = string, Version extends number = number, Queue extends string = string> {
16
+ readonly kind: Kind;
17
+ readonly version: Version;
18
+ readonly queue: JobQueue<Queue>;
19
+ readonly payload: Payload;
20
+ readonly catalog: CatalogIdentity<Queue, Kind, Version>;
21
+ readonly enqueue: <E, R>(tx: JobsTransaction<E, R>, input: EnqueueInput<Payload["Type"]>) => Effect.Effect<EnqueueResult, E | JobEnqueueError, R | Payload["EncodingServices"]>;
22
+ readonly handlerLayer: <R>(execute: (input: HandlerInput<Payload["Type"]>) => Effect.Effect<void, JobFailure, R>, decodePayload: JobPayloadDecoder) => Layer.Layer<never, DuplicateJobHandler, JobRegistry | R | Payload["DecodingServices"]>;
23
+ }
24
+ /** Codec dependency is explicit until serial integration supplies the qualified implementation. */
25
+ export declare const make: <Payload extends Schema.Top, const Kind extends string, const Version extends number, const Queue extends string>(options: {
26
+ readonly kind: Kind;
27
+ readonly version: Version;
28
+ readonly queue: JobQueue<Queue>;
29
+ readonly payload: Payload;
30
+ readonly encodePayload: JobPayloadEncoder;
31
+ }) => JobDefinition<Payload, Kind, Version, Queue>;
32
+ export {};
33
+ //# sourceMappingURL=Job.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Job.d.ts","sourceRoot":"","sources":["../src/Job.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAEpD,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,eAAe,EAAoB,MAAM,kBAAkB,CAAA;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7C,OAAO,EAAE,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;;;;AAG3E,qBAAa,oBAAqB,SAAQ,0BAAyC;IACjF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B,CAAC;CAAG;AAEL,MAAM,WAAW,aAAa,CAC5B,OAAO,SAAS,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,EACvC,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,OAAO,SAAS,MAAM,GAAG,MAAM,EAC/B,KAAK,SAAS,MAAM,GAAG,MAAM;IAE7B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;IACvD,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EACrB,EAAE,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,EACzB,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KACjC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,GAAG,eAAe,EAAE,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAA;IACvF,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,EACvB,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,EACrF,aAAa,EAAE,iBAAiB,KAC7B,KAAK,CAAC,KAAK,CACd,KAAK,EACL,mBAAmB,EACnB,WAAW,GAAG,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAC9C,CAAA;CACF;AAED,mGAAmG;AACnG,eAAO,MAAM,IAAI,GACf,OAAO,SAAS,MAAM,CAAC,GAAG,EAC1B,KAAK,CAAC,IAAI,SAAS,MAAM,EACzB,KAAK,CAAC,OAAO,SAAS,MAAM,EAC5B,KAAK,CAAC,KAAK,SAAS,MAAM,WACjB;IACT,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,aAAa,EAAE,iBAAiB,CAAA;CAC1C,KAAG,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAwE9C,CAAA"}
package/dist/Job.js ADDED
@@ -0,0 +1,66 @@
1
+ import { Data, Effect, Layer, Schema } from "effect";
2
+ import { InvalidJobInput } from "./JobContract.js";
3
+ import { CatalogIdentity, ProducerIdentity } from "./JobIdentity.js";
4
+ import { EpochMillis, PersistedJobPolicy } from "./JobPolicy.js";
5
+ import { JobRegistry } from "./JobRegistry.js";
6
+ import { insertPrepared } from "./internal/JobTransaction.js";
7
+ export class InvalidJobDefinition extends Data.TaggedError("InvalidJobDefinition") {
8
+ }
9
+ /** Codec dependency is explicit until serial integration supplies the qualified implementation. */
10
+ export const make = (options) => {
11
+ const { kind, version, queue, payload, encodePayload } = options;
12
+ const catalog = Object.freeze({ queue: queue.name, kind, version });
13
+ if (!Schema.is(CatalogIdentity)(catalog) || !Schema.isSchema(payload)) {
14
+ throw new InvalidJobDefinition({
15
+ expected: "valid queue/kind/version and payload Schema"
16
+ });
17
+ }
18
+ return Object.freeze({
19
+ kind,
20
+ version,
21
+ queue,
22
+ payload,
23
+ catalog,
24
+ enqueue: Effect.fnUntraced(function* (tx, input) {
25
+ if (!Schema.is(ProducerIdentity)(input.producer)) {
26
+ return yield* new InvalidJobInput({ field: "producer" });
27
+ }
28
+ if (!Schema.is(PersistedJobPolicy)(input.policy)) {
29
+ return yield* new InvalidJobInput({ field: "policy" });
30
+ }
31
+ if (input.availableAt !== undefined && !Schema.is(EpochMillis)(input.availableAt)) {
32
+ return yield* new InvalidJobInput({ field: "availableAt" });
33
+ }
34
+ // Snapshot configuration before asynchronous encoding; the backend owns IDs and equality.
35
+ const producer = Object.freeze({
36
+ operation: input.producer.operation,
37
+ operationId: input.producer.operationId,
38
+ slot: input.producer.slot
39
+ });
40
+ const policy = Object.freeze({
41
+ ...input.policy,
42
+ retrySchedule: Object.freeze({ ...input.policy.retrySchedule }),
43
+ completedRetention: Object.freeze({ ...input.policy.completedRetention }),
44
+ deadRetention: Object.freeze({ ...input.policy.deadRetention })
45
+ });
46
+ const availableAt = input.availableAt;
47
+ const encoded = yield* encodePayload(payload, input.payload);
48
+ return yield* insertPrepared(tx, Object.freeze({
49
+ catalog,
50
+ producer,
51
+ policy,
52
+ encoded,
53
+ ...(availableAt === undefined ? {} : { availableAt })
54
+ }));
55
+ }),
56
+ handlerLayer: (execute, decodePayload) => Layer.effectDiscard(Effect.gen(function* () {
57
+ const registry = yield* JobRegistry;
58
+ const services = yield* Effect.context();
59
+ yield* registry.install({
60
+ catalog,
61
+ execute: (encoded, context) => Effect.flatMap(decodePayload(payload, encoded), (decoded) => Effect.suspend(() => execute({ payload: decoded, context }))).pipe(Effect.provide(services))
62
+ });
63
+ }))
64
+ });
65
+ };
66
+ //# sourceMappingURL=Job.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Job.js","sourceRoot":"","sources":["../src/Job.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { Effect, Schema } from "effect";
2
+ import type { JobQueue } from "./JobQueue.js";
3
+ declare const ConsumerOptions: Schema.Struct<{
4
+ readonly localConcurrency: Schema.Int;
5
+ readonly claimLimitPerRun: Schema.Int;
6
+ readonly recoveryLimitPerRun: Schema.Int;
7
+ }>;
8
+ export interface JobConsumer<Q extends JobQueue = JobQueue> extends ConsumerOptions {
9
+ readonly queue: Q;
10
+ }
11
+ type ConsumerOptions = typeof ConsumerOptions.Type;
12
+ declare const InvalidJobConsumer_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
13
+ readonly _tag: "InvalidJobConsumer";
14
+ } & Readonly<A>;
15
+ export declare class InvalidJobConsumer extends InvalidJobConsumer_base<{
16
+ readonly reason: "invalid-options";
17
+ }> {
18
+ }
19
+ declare const DuplicateJobConsumer_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
20
+ readonly _tag: "DuplicateJobConsumer";
21
+ } & Readonly<A>;
22
+ export declare class DuplicateJobConsumer extends DuplicateJobConsumer_base<{
23
+ readonly queue: string;
24
+ }> {
25
+ get message(): string;
26
+ }
27
+ /** Bounded configuration, not a running worker. */
28
+ export declare const make: <Q extends JobQueue>(queue: Q, options: ConsumerOptions) => Effect.Effect<JobConsumer<Q>, InvalidJobConsumer>;
29
+ export interface JobPlan<Consumers extends ReadonlyArray<JobConsumer> = ReadonlyArray<JobConsumer>> {
30
+ readonly consumers: Readonly<Consumers>;
31
+ }
32
+ export declare const plan: <const Consumers extends ReadonlyArray<JobConsumer>>(...consumers: Consumers) => Effect.Effect<JobPlan<Consumers>, DuplicateJobConsumer>;
33
+ export {};
34
+ //# sourceMappingURL=JobConsumer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobConsumer.d.ts","sourceRoot":"","sources":["../src/JobConsumer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7C,QAAA,MAAM,eAAe;;;;EAUnB,CAAA;AAEF,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,CAAE,SAAQ,eAAe;IACjF,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAClB;AACD,KAAK,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAA;;;;AAElD,qBAAa,kBAAmB,SAAQ,wBAAuC;IAC7E,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAA;CACnC,CAAC;CAAG;;;;AACL,qBAAa,oBAAqB,SAAQ,0BAAyC;IACjF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,CAAC;IACA,IAAa,OAAO,IAAI,MAAM,CAE7B;CACF;AAED,mDAAmD;AACnD,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,QAAQ,SAC9B,CAAC,WACC,eAAe,KACvB,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,kBAAkB,CAIhD,CAAA;AAEH,MAAM,WAAW,OAAO,CACtB,SAAS,SAAS,aAAa,CAAC,WAAW,CAAC,GAAG,aAAa,CAAC,WAAW,CAAC;IAEzE,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAA;CACxC;AAED,eAAO,MAAM,IAAI,GAAI,KAAK,CAAC,SAAS,SAAS,aAAa,CAAC,WAAW,CAAC,gBACvD,SAAS,KACtB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,oBAAoB,CAcrD,CAAA"}
@@ -0,0 +1,28 @@
1
+ import { Data, Effect, Schema } from "effect";
2
+ const ConsumerOptions = Schema.Struct({
3
+ localConcurrency: Schema.Int.pipe(Schema.check(Schema.isBetween({ minimum: 1, maximum: 64 }))),
4
+ claimLimitPerRun: Schema.Int.pipe(Schema.check(Schema.isBetween({ minimum: 1, maximum: 10_000 }))),
5
+ recoveryLimitPerRun: Schema.Int.pipe(Schema.check(Schema.isBetween({ minimum: 1, maximum: 10_000 })))
6
+ });
7
+ export class InvalidJobConsumer extends Data.TaggedError("InvalidJobConsumer") {
8
+ }
9
+ export class DuplicateJobConsumer extends Data.TaggedError("DuplicateJobConsumer") {
10
+ get message() {
11
+ return `Duplicate consumer for ${this.queue}; configure one consumer per logical queue`;
12
+ }
13
+ }
14
+ /** Bounded configuration, not a running worker. */
15
+ export const make = (queue, options) => Schema.decodeEffect(ConsumerOptions)(options, { onExcessProperty: "error" }).pipe(Effect.map((decoded) => Object.freeze({ queue, ...decoded })), Effect.mapError(() => new InvalidJobConsumer({ reason: "invalid-options" })));
16
+ export const plan = (...consumers) => Effect.suspend(() => {
17
+ const queues = new Set();
18
+ for (const consumer of consumers) {
19
+ if (queues.has(consumer.queue.name)) {
20
+ return Effect.fail(new DuplicateJobConsumer({ queue: consumer.queue.name }));
21
+ }
22
+ queues.add(consumer.queue.name);
23
+ }
24
+ return Effect.succeed(Object.freeze({
25
+ consumers: Object.freeze([...consumers])
26
+ }));
27
+ });
28
+ //# sourceMappingURL=JobConsumer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobConsumer.js","sourceRoot":"","sources":["../src/JobConsumer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAG7C,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC;IACpC,gBAAgB,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAC/B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAC5D;IACD,gBAAgB,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAC/B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAChE;IACD,mBAAmB,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAClC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAChE;CACF,CAAC,CAAA;AAOF,MAAM,OAAO,kBAAmB,SAAQ,IAAI,CAAC,WAAW,CAAC,oBAAoB,CAE3E;CAAG;AACL,MAAM,OAAO,oBAAqB,SAAQ,IAAI,CAAC,WAAW,CAAC,sBAAsB,CAE/E;IACA,IAAa,OAAO;QAClB,OAAO,0BAA0B,IAAI,CAAC,KAAK,4CAA4C,CAAA;IACzF,CAAC;CACF;AAED,mDAAmD;AACnD,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,KAAQ,EACR,OAAwB,EAC2B,EAAE,CACrD,MAAM,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC,OAAO,EAAE,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,CAC/E,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,EAC7D,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,kBAAkB,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAC7E,CAAA;AAQH,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,GAAG,SAAoB,EACkC,EAAE,CAC3D,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE;IAClB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAA;IAChC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,oBAAoB,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QAC9E,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CACnB,MAAM,CAAC,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC,CAAmC;KAC3E,CAAC,CACH,CAAA;AACH,CAAC,CAAC,CAAA"}
@@ -0,0 +1,128 @@
1
+ import { Data } from "effect";
2
+ import type { Effect, Schema } from "effect";
3
+ import type { JobId } from "./JobId.js";
4
+ import type { CatalogIdentity, ProducerIdentity } from "./JobIdentity.js";
5
+ import type { JobPolicy } from "./JobPolicy.js";
6
+ export interface HandlerContext {
7
+ readonly jobId: JobId;
8
+ readonly catalog: CatalogIdentity;
9
+ readonly producer: ProducerIdentity;
10
+ /** attemptsMade + 1; may repeat after unknown outcomes and stalled recovery. */
11
+ readonly attemptNumber: number;
12
+ }
13
+ export interface HandlerInput<Payload> {
14
+ readonly payload: Payload;
15
+ readonly context: HandlerContext;
16
+ }
17
+ export interface EnqueueInput<Payload> {
18
+ readonly producer: ProducerIdentity;
19
+ readonly payload: Payload;
20
+ readonly policy: JobPolicy;
21
+ /** Omitted means database time on first insertion, never on matching duplicate. */
22
+ readonly availableAt?: number;
23
+ }
24
+ export type EnqueueResult = Data.TaggedEnum<{
25
+ Inserted: {
26
+ readonly jobId: JobId;
27
+ };
28
+ AlreadyPresent: {
29
+ readonly jobId: JobId;
30
+ };
31
+ }>;
32
+ export declare const EnqueueResults: {
33
+ readonly $is: <Tag extends "AlreadyPresent" | "Inserted">(tag: Tag) => (u: unknown) => u is Extract<{
34
+ readonly _tag: "AlreadyPresent";
35
+ readonly jobId: JobId;
36
+ }, {
37
+ readonly _tag: Tag;
38
+ }> | Extract<{
39
+ readonly _tag: "Inserted";
40
+ readonly jobId: JobId;
41
+ }, {
42
+ readonly _tag: Tag;
43
+ }>;
44
+ readonly $match: {
45
+ <Cases extends { readonly [Tag in "AlreadyPresent" | "Inserted"]: (args: Extract<{
46
+ readonly _tag: "AlreadyPresent";
47
+ readonly jobId: JobId;
48
+ } | {
49
+ readonly _tag: "Inserted";
50
+ readonly jobId: JobId;
51
+ }, {
52
+ readonly _tag: Tag;
53
+ }>) => any; }>(cases: Cases): (value: {
54
+ readonly _tag: "AlreadyPresent";
55
+ readonly jobId: JobId;
56
+ } | {
57
+ readonly _tag: "Inserted";
58
+ readonly jobId: JobId;
59
+ }) => import("effect/Unify").Unify<ReturnType<Cases["AlreadyPresent" | "Inserted"]>>;
60
+ <Cases extends { readonly [Tag in "AlreadyPresent" | "Inserted"]: (args: Extract<{
61
+ readonly _tag: "AlreadyPresent";
62
+ readonly jobId: JobId;
63
+ } | {
64
+ readonly _tag: "Inserted";
65
+ readonly jobId: JobId;
66
+ }, {
67
+ readonly _tag: Tag;
68
+ }>) => any; }>(value: {
69
+ readonly _tag: "AlreadyPresent";
70
+ readonly jobId: JobId;
71
+ } | {
72
+ readonly _tag: "Inserted";
73
+ readonly jobId: JobId;
74
+ }, cases: Cases): import("effect/Unify").Unify<ReturnType<Cases["AlreadyPresent" | "Inserted"]>>;
75
+ };
76
+ readonly AlreadyPresent: Data.TaggedEnum.ConstructorFrom<{
77
+ readonly _tag: "AlreadyPresent";
78
+ readonly jobId: JobId;
79
+ }, "_tag">;
80
+ readonly Inserted: Data.TaggedEnum.ConstructorFrom<{
81
+ readonly _tag: "Inserted";
82
+ readonly jobId: JobId;
83
+ }, "_tag">;
84
+ };
85
+ export declare const jobPayloadFormatVersion = 1;
86
+ export declare const maximumJobPayloadBytes = 65536;
87
+ export declare const maximumJobSemanticProjectionBytes = 65536;
88
+ export declare const maximumProtectedJobPayloadSubtrees = 16;
89
+ export declare const maximumJobPayloadSchemaPathBytes = 256;
90
+ export declare const maximumJobPayloadDepth = 32;
91
+ /** Codec owns validated canonical bytes; receivers copy bytes before retaining them. */
92
+ export interface EncodedJobPayload {
93
+ readonly formatVersion: typeof jobPayloadFormatVersion;
94
+ readonly payloadBytes: Uint8Array;
95
+ readonly semanticProjectionBytes: Uint8Array;
96
+ }
97
+ /** Signatures implemented by the codec unit; Schema services stay explicit. */
98
+ export type JobPayloadEncoder = <S extends Schema.Top>(schema: S, payload: S["Type"]) => Effect.Effect<EncodedJobPayload, JobPayloadCodecError, S["EncodingServices"]>;
99
+ export type JobPayloadDecoder = <S extends Schema.Top>(schema: S, encoded: EncodedJobPayload) => Effect.Effect<S["Type"], JobPayloadCodecError, S["DecodingServices"]>;
100
+ /** Producer-to-backend seam: no caller-supplied JobId. */
101
+ export interface PreparedJob {
102
+ readonly catalog: CatalogIdentity;
103
+ readonly producer: ProducerIdentity;
104
+ readonly policy: JobPolicy;
105
+ readonly availableAt?: number;
106
+ readonly encoded: EncodedJobPayload;
107
+ }
108
+ declare const InvalidJobInput_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
109
+ readonly _tag: "InvalidJobInput";
110
+ } & Readonly<A>;
111
+ export declare class InvalidJobInput extends InvalidJobInput_base<{
112
+ readonly field: "catalog" | "producer" | "policy" | "availableAt" | "payload";
113
+ }> {
114
+ }
115
+ declare const JobIntegrityConflict_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
116
+ readonly _tag: "JobIntegrityConflict";
117
+ } & Readonly<A>;
118
+ export declare class JobIntegrityConflict extends JobIntegrityConflict_base<{}> {
119
+ }
120
+ declare const JobPayloadCodecError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
121
+ readonly _tag: "JobPayloadCodecError";
122
+ } & Readonly<A>;
123
+ export declare class JobPayloadCodecError extends JobPayloadCodecError_base<{
124
+ readonly reason: "invalid-json-value" | "invalid-encoding" | "invalid-schema" | "invalid-protected-value" | "payload-too-large" | "projection-too-large" | "too-many-protected-subtrees" | "schema-path-too-long" | "payload-too-deep" | "projection-mismatch";
125
+ }> {
126
+ }
127
+ export {};
128
+ //# sourceMappingURL=JobContract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobContract.d.ts","sourceRoot":"","sources":["../src/JobContract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { Data } from "effect";
2
+ export const EnqueueResults = Data.taggedEnum();
3
+ export const jobPayloadFormatVersion = 1;
4
+ export const maximumJobPayloadBytes = 65_536;
5
+ export const maximumJobSemanticProjectionBytes = 65_536;
6
+ export const maximumProtectedJobPayloadSubtrees = 16;
7
+ export const maximumJobPayloadSchemaPathBytes = 256;
8
+ export const maximumJobPayloadDepth = 32;
9
+ export class InvalidJobInput extends Data.TaggedError("InvalidJobInput") {
10
+ }
11
+ export class JobIntegrityConflict extends Data.TaggedError("JobIntegrityConflict") {
12
+ }
13
+ export class JobPayloadCodecError extends Data.TaggedError("JobPayloadCodecError") {
14
+ }
15
+ //# sourceMappingURL=JobContract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobContract.js","sourceRoot":"","sources":["../src/JobContract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AA4B7B,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,EAAiB,CAAA;AAE9D,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAA;AACxC,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAA;AAC5C,MAAM,CAAC,MAAM,iCAAiC,GAAG,MAAM,CAAA;AACvD,MAAM,CAAC,MAAM,kCAAkC,GAAG,EAAE,CAAA;AACpD,MAAM,CAAC,MAAM,gCAAgC,GAAG,GAAG,CAAA;AACnD,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAA;AAyBxC,MAAM,OAAO,eAAgB,SAAQ,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAErE;CAAG;AACL,MAAM,OAAO,oBAAqB,SAAQ,IAAI,CAAC,WAAW,CAAC,sBAAsB,CAAK;CAAG;AACzF,MAAM,OAAO,oBAAqB,SAAQ,IAAI,CAAC,WAAW,CAAC,sBAAsB,CAY/E;CAAG"}
@@ -0,0 +1,51 @@
1
+ import { Schema } from "effect";
2
+ export declare const FailureCode: Schema.String;
3
+ export declare const JobFailure: Schema.Union<readonly [Schema.TaggedStruct<"Retry", {
4
+ readonly code: Schema.String;
5
+ readonly notAfter: Schema.optional<Schema.Int>;
6
+ }>, Schema.TaggedStruct<"Dead", {
7
+ readonly code: Schema.String;
8
+ }>, Schema.TaggedStruct<"Isolate", {
9
+ readonly code: Schema.String;
10
+ }>, Schema.TaggedStruct<"OutcomeUnknown", {
11
+ readonly code: Schema.String;
12
+ }>]>;
13
+ export type JobFailure = typeof JobFailure.Type;
14
+ declare const InvalidJobFailure_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
15
+ readonly _tag: "InvalidJobFailure";
16
+ } & Readonly<A>;
17
+ export declare class InvalidJobFailure extends InvalidJobFailure_base<{
18
+ readonly field: "code" | "notAfter";
19
+ }> {
20
+ }
21
+ /** Explicit outcomes, not error-message or Cause persistence. */
22
+ export declare const JobFailures: Readonly<{
23
+ Retry: (input: {
24
+ readonly code: string;
25
+ readonly notAfter?: number;
26
+ }) => {
27
+ readonly _tag: "Retry";
28
+ readonly code: string;
29
+ readonly notAfter?: number | undefined;
30
+ };
31
+ Dead: (input: {
32
+ readonly code: string;
33
+ }) => {
34
+ readonly _tag: "Dead";
35
+ readonly code: string;
36
+ };
37
+ Isolate: (input: {
38
+ readonly code: string;
39
+ }) => {
40
+ readonly _tag: "Isolate";
41
+ readonly code: string;
42
+ };
43
+ OutcomeUnknown: (input: {
44
+ readonly code: string;
45
+ }) => {
46
+ readonly _tag: "OutcomeUnknown";
47
+ readonly code: string;
48
+ };
49
+ }>;
50
+ export {};
51
+ //# sourceMappingURL=JobFailure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobFailure.d.ts","sourceRoot":"","sources":["../src/JobFailure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,MAAM,EAAE,MAAM,QAAQ,CAAA;AAGrC,eAAO,MAAM,WAAW,eAMvB,CAAA;AACD,eAAO,MAAM,UAAU;;;;;;;;;IAQrB,CAAA;AACF,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;;;;AAG/C,qBAAa,iBAAkB,SAAQ,uBAAsC;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAAA;CACpC,CAAC;CAAG;AAcL,iEAAiE;AACjE,eAAO,MAAM,WAAW;mBACP;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;kBAEtD;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE;;;;qBACtB;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE;;;;4BAClB;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE;;;;EAEjD,CAAA"}
@@ -0,0 +1,34 @@
1
+ import { Data, Schema } from "effect";
2
+ import { EpochMillis } from "./JobPolicy.js";
3
+ export const FailureCode = Schema.String.pipe(Schema.check(Schema.isMinLength(1), Schema.isMaxLength(64), Schema.isPattern(/^[a-z0-9][a-z0-9_-]*$/u)));
4
+ export const JobFailure = Schema.Union([
5
+ Schema.TaggedStruct("Retry", {
6
+ code: FailureCode,
7
+ notAfter: Schema.optional(EpochMillis)
8
+ }),
9
+ Schema.TaggedStruct("Dead", { code: FailureCode }),
10
+ Schema.TaggedStruct("Isolate", { code: FailureCode }),
11
+ Schema.TaggedStruct("OutcomeUnknown", { code: FailureCode })
12
+ ]);
13
+ const failures = Data.taggedEnum();
14
+ export class InvalidJobFailure extends Data.TaggedError("InvalidJobFailure") {
15
+ }
16
+ const checked = (value) => {
17
+ if (!Schema.is(FailureCode)(value.code)) {
18
+ throw new InvalidJobFailure({ field: "code" });
19
+ }
20
+ if (value._tag === "Retry" &&
21
+ value.notAfter !== undefined &&
22
+ !Schema.is(EpochMillis)(value.notAfter)) {
23
+ throw new InvalidJobFailure({ field: "notAfter" });
24
+ }
25
+ return Object.freeze(value);
26
+ };
27
+ /** Explicit outcomes, not error-message or Cause persistence. */
28
+ export const JobFailures = Object.freeze({
29
+ Retry: (input) => checked(failures.Retry(input)),
30
+ Dead: (input) => checked(failures.Dead(input)),
31
+ Isolate: (input) => checked(failures.Isolate(input)),
32
+ OutcomeUnknown: (input) => checked(failures.OutcomeUnknown(input))
33
+ });
34
+ //# sourceMappingURL=JobFailure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobFailure.js","sourceRoot":"","sources":["../src/JobFailure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5C,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAC3C,MAAM,CAAC,KAAK,CACV,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EACrB,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,EACtB,MAAM,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAC3C,CACF,CAAA;AACD,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC;IACrC,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE;QAC3B,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC;KACvC,CAAC;IACF,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAClD,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IACrD,MAAM,CAAC,YAAY,CAAC,gBAAgB,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;CAC7D,CAAC,CAAA;AAEF,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAc,CAAA;AAE9C,MAAM,OAAO,iBAAkB,SAAQ,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAEzE;CAAG;AACL,MAAM,OAAO,GAAG,CAAuB,KAAQ,EAAK,EAAE;IACpD,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,iBAAiB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;IAChD,CAAC;IACD,IACE,KAAK,CAAC,IAAI,KAAK,OAAO;QACtB,KAAK,CAAC,QAAQ,KAAK,SAAS;QAC5B,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,EACvC,CAAC;QACD,MAAM,IAAI,iBAAiB,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAA;IACpD,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC7B,CAAC,CAAA;AACD,iEAAiE;AACjE,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;IACvC,KAAK,EAAE,CAAC,KAA4D,EAAE,EAAE,CACtE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,EAAE,CAAC,KAAgC,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzE,OAAO,EAAE,CAAC,KAAgC,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/E,cAAc,EAAE,CAAC,KAAgC,EAAE,EAAE,CACnD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;CAC1C,CAAC,CAAA"}
@@ -0,0 +1,5 @@
1
+ import { Schema } from "effect";
2
+ /** Opaque library-assigned identifier. Applications must not supply enqueue IDs. */
3
+ export declare const JobId: Schema.brand<Schema.String, "effect-jobs/JobId">;
4
+ export type JobId = typeof JobId.Type;
5
+ //# sourceMappingURL=JobId.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobId.d.ts","sourceRoot":"","sources":["../src/JobId.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,oFAAoF;AACpF,eAAO,MAAM,KAAK,kDAGjB,CAAA;AACD,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA"}
package/dist/JobId.js ADDED
@@ -0,0 +1,4 @@
1
+ import { Schema } from "effect";
2
+ /** Opaque library-assigned identifier. Applications must not supply enqueue IDs. */
3
+ export const JobId = Schema.String.pipe(Schema.check(Schema.isMinLength(1)), Schema.brand("effect-jobs/JobId"));
4
+ //# sourceMappingURL=JobId.js.map