@shivaedev/jobs 0.0.0-stage → 0.19.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 (219) hide show
  1. package/CHANGELOG.md +319 -0
  2. package/LICENSE +21 -0
  3. package/README.md +528 -2
  4. package/dist/server/client.d.ts +25 -0
  5. package/dist/server/client.d.ts.map +1 -0
  6. package/dist/server/client.js +3 -0
  7. package/dist/server/client.js.map +1 -0
  8. package/dist/server/definition.d.ts +96 -0
  9. package/dist/server/definition.d.ts.map +1 -0
  10. package/dist/server/definition.js +40 -0
  11. package/dist/server/definition.js.map +1 -0
  12. package/dist/server/error.d.ts +51 -0
  13. package/dist/server/error.d.ts.map +1 -0
  14. package/dist/server/error.js +37 -0
  15. package/dist/server/error.js.map +1 -0
  16. package/dist/server/health.d.ts +51 -0
  17. package/dist/server/health.d.ts.map +1 -0
  18. package/dist/server/health.js +4 -0
  19. package/dist/server/health.js.map +1 -0
  20. package/dist/server/internal/batchHandler.d.ts +5 -0
  21. package/dist/server/internal/batchHandler.d.ts.map +1 -0
  22. package/dist/server/internal/batchHandler.js +51 -0
  23. package/dist/server/internal/batchHandler.js.map +1 -0
  24. package/dist/server/internal/clientCache.d.ts +8 -0
  25. package/dist/server/internal/clientCache.d.ts.map +1 -0
  26. package/dist/server/internal/clientCache.js +61 -0
  27. package/dist/server/internal/clientCache.js.map +1 -0
  28. package/dist/server/internal/clientErrors.d.ts +8 -0
  29. package/dist/server/internal/clientErrors.d.ts.map +1 -0
  30. package/dist/server/internal/clientErrors.js +49 -0
  31. package/dist/server/internal/clientErrors.js.map +1 -0
  32. package/dist/server/internal/countsFor.d.ts +5 -0
  33. package/dist/server/internal/countsFor.d.ts.map +1 -0
  34. package/dist/server/internal/countsFor.js +28 -0
  35. package/dist/server/internal/countsFor.js.map +1 -0
  36. package/dist/server/internal/deadlineOf.d.ts +3 -0
  37. package/dist/server/internal/deadlineOf.d.ts.map +1 -0
  38. package/dist/server/internal/deadlineOf.js +7 -0
  39. package/dist/server/internal/deadlineOf.js.map +1 -0
  40. package/dist/server/internal/deferrableAttempt.d.ts +7 -0
  41. package/dist/server/internal/deferrableAttempt.d.ts.map +1 -0
  42. package/dist/server/internal/deferrableAttempt.js +28 -0
  43. package/dist/server/internal/deferrableAttempt.js.map +1 -0
  44. package/dist/server/internal/deferral.d.ts +15 -0
  45. package/dist/server/internal/deferral.d.ts.map +1 -0
  46. package/dist/server/internal/deferral.js +14 -0
  47. package/dist/server/internal/deferral.js.map +1 -0
  48. package/dist/server/internal/deferralStorePlan.d.ts +2 -0
  49. package/dist/server/internal/deferralStorePlan.d.ts.map +1 -0
  50. package/dist/server/internal/deferralStorePlan.js +35 -0
  51. package/dist/server/internal/deferralStorePlan.js.map +1 -0
  52. package/dist/server/internal/definitionOptions.d.ts +17 -0
  53. package/dist/server/internal/definitionOptions.d.ts.map +1 -0
  54. package/dist/server/internal/definitionOptions.js +12 -0
  55. package/dist/server/internal/definitionOptions.js.map +1 -0
  56. package/dist/server/internal/enqueueFor.d.ts +4 -0
  57. package/dist/server/internal/enqueueFor.d.ts.map +1 -0
  58. package/dist/server/internal/enqueueFor.js +23 -0
  59. package/dist/server/internal/enqueueFor.js.map +1 -0
  60. package/dist/server/internal/ensureQueue.d.ts +4 -0
  61. package/dist/server/internal/ensureQueue.d.ts.map +1 -0
  62. package/dist/server/internal/ensureQueue.js +44 -0
  63. package/dist/server/internal/ensureQueue.js.map +1 -0
  64. package/dist/server/internal/expireAttempt.d.ts +3 -0
  65. package/dist/server/internal/expireAttempt.d.ts.map +1 -0
  66. package/dist/server/internal/expireAttempt.js +17 -0
  67. package/dist/server/internal/expireAttempt.js.map +1 -0
  68. package/dist/server/internal/healthFor.d.ts +5 -0
  69. package/dist/server/internal/healthFor.d.ts.map +1 -0
  70. package/dist/server/internal/healthFor.js +27 -0
  71. package/dist/server/internal/healthFor.js.map +1 -0
  72. package/dist/server/internal/jobControl.d.ts +5 -0
  73. package/dist/server/internal/jobControl.d.ts.map +1 -0
  74. package/dist/server/internal/jobControl.js +35 -0
  75. package/dist/server/internal/jobControl.js.map +1 -0
  76. package/dist/server/internal/lifecycle.d.ts +17 -0
  77. package/dist/server/internal/lifecycle.d.ts.map +1 -0
  78. package/dist/server/internal/lifecycle.js +55 -0
  79. package/dist/server/internal/lifecycle.js.map +1 -0
  80. package/dist/server/internal/listJobs.d.ts +5 -0
  81. package/dist/server/internal/listJobs.d.ts.map +1 -0
  82. package/dist/server/internal/listJobs.js +69 -0
  83. package/dist/server/internal/listJobs.js.map +1 -0
  84. package/dist/server/internal/makeService.d.ts +4 -0
  85. package/dist/server/internal/makeService.d.ts.map +1 -0
  86. package/dist/server/internal/makeService.js +17 -0
  87. package/dist/server/internal/makeService.js.map +1 -0
  88. package/dist/server/internal/nativeClient.d.ts +3 -0
  89. package/dist/server/internal/nativeClient.d.ts.map +1 -0
  90. package/dist/server/internal/nativeClient.js +28 -0
  91. package/dist/server/internal/nativeClient.js.map +1 -0
  92. package/dist/server/internal/observeTestingSettlements.d.ts +6 -0
  93. package/dist/server/internal/observeTestingSettlements.d.ts.map +1 -0
  94. package/dist/server/internal/observeTestingSettlements.js +35 -0
  95. package/dist/server/internal/observeTestingSettlements.js.map +1 -0
  96. package/dist/server/internal/register.d.ts +8 -0
  97. package/dist/server/internal/register.d.ts.map +1 -0
  98. package/dist/server/internal/register.js +98 -0
  99. package/dist/server/internal/register.js.map +1 -0
  100. package/dist/server/internal/registerReleasedJobs.d.ts +5 -0
  101. package/dist/server/internal/registerReleasedJobs.d.ts.map +1 -0
  102. package/dist/server/internal/registerReleasedJobs.js +35 -0
  103. package/dist/server/internal/registerReleasedJobs.js.map +1 -0
  104. package/dist/server/internal/registerWorker.d.ts +5 -0
  105. package/dist/server/internal/registerWorker.d.ts.map +1 -0
  106. package/dist/server/internal/registerWorker.js +33 -0
  107. package/dist/server/internal/registerWorker.js.map +1 -0
  108. package/dist/server/internal/runSchemaPlan.d.ts +7 -0
  109. package/dist/server/internal/runSchemaPlan.d.ts.map +1 -0
  110. package/dist/server/internal/runSchemaPlan.js +25 -0
  111. package/dist/server/internal/runSchemaPlan.js.map +1 -0
  112. package/dist/server/internal/scheduleDefinition.d.ts +3 -0
  113. package/dist/server/internal/scheduleDefinition.d.ts.map +1 -0
  114. package/dist/server/internal/scheduleDefinition.js +19 -0
  115. package/dist/server/internal/scheduleDefinition.js.map +1 -0
  116. package/dist/server/internal/schemaIndexBuilds.d.ts +4 -0
  117. package/dist/server/internal/schemaIndexBuilds.d.ts.map +1 -0
  118. package/dist/server/internal/schemaIndexBuilds.js +34 -0
  119. package/dist/server/internal/schemaIndexBuilds.js.map +1 -0
  120. package/dist/server/internal/settleDeferral.d.ts +7 -0
  121. package/dist/server/internal/settleDeferral.d.ts.map +1 -0
  122. package/dist/server/internal/settleDeferral.js +48 -0
  123. package/dist/server/internal/settleDeferral.js.map +1 -0
  124. package/dist/server/internal/storedRows.d.ts +6 -0
  125. package/dist/server/internal/storedRows.d.ts.map +1 -0
  126. package/dist/server/internal/storedRows.js +10 -0
  127. package/dist/server/internal/storedRows.js.map +1 -0
  128. package/dist/server/internal/testingClient.d.ts +13 -0
  129. package/dist/server/internal/testingClient.d.ts.map +1 -0
  130. package/dist/server/internal/testingClient.js +117 -0
  131. package/dist/server/internal/testingClient.js.map +1 -0
  132. package/dist/server/internal/testingDeferrals.d.ts +11 -0
  133. package/dist/server/internal/testingDeferrals.d.ts.map +1 -0
  134. package/dist/server/internal/testingDeferrals.js +29 -0
  135. package/dist/server/internal/testingDeferrals.js.map +1 -0
  136. package/dist/server/internal/testingExpirations.d.ts +6 -0
  137. package/dist/server/internal/testingExpirations.d.ts.map +1 -0
  138. package/dist/server/internal/testingExpirations.js +27 -0
  139. package/dist/server/internal/testingExpirations.js.map +1 -0
  140. package/dist/server/internal/testingIdle.d.ts +16 -0
  141. package/dist/server/internal/testingIdle.d.ts.map +1 -0
  142. package/dist/server/internal/testingIdle.js +31 -0
  143. package/dist/server/internal/testingIdle.js.map +1 -0
  144. package/dist/server/internal/testingReadout.d.ts +44 -0
  145. package/dist/server/internal/testingReadout.d.ts.map +1 -0
  146. package/dist/server/internal/testingReadout.js +13 -0
  147. package/dist/server/internal/testingReadout.js.map +1 -0
  148. package/dist/server/internal/testingSignal.d.ts +7 -0
  149. package/dist/server/internal/testingSignal.d.ts.map +1 -0
  150. package/dist/server/internal/testingSignal.js +29 -0
  151. package/dist/server/internal/testingSignal.js.map +1 -0
  152. package/dist/server/internal/testingSnapshot.d.ts +6 -0
  153. package/dist/server/internal/testingSnapshot.d.ts.map +1 -0
  154. package/dist/server/internal/testingSnapshot.js +32 -0
  155. package/dist/server/internal/testingSnapshot.js.map +1 -0
  156. package/dist/server/internal/tracing.d.ts +6 -0
  157. package/dist/server/internal/tracing.d.ts.map +1 -0
  158. package/dist/server/internal/tracing.js +37 -0
  159. package/dist/server/internal/tracing.js.map +1 -0
  160. package/dist/server/internal/waitForBatchExpiry.d.ts +6 -0
  161. package/dist/server/internal/waitForBatchExpiry.d.ts.map +1 -0
  162. package/dist/server/internal/waitForBatchExpiry.js +28 -0
  163. package/dist/server/internal/waitForBatchExpiry.js.map +1 -0
  164. package/dist/server/schema.d.ts +10 -0
  165. package/dist/server/schema.d.ts.map +1 -0
  166. package/dist/server/schema.js +67 -0
  167. package/dist/server/schema.js.map +1 -0
  168. package/dist/server/service.d.ts +29 -0
  169. package/dist/server/service.d.ts.map +1 -0
  170. package/dist/server/service.js +33 -0
  171. package/dist/server/service.js.map +1 -0
  172. package/dist/server/testing.d.ts +77 -0
  173. package/dist/server/testing.d.ts.map +1 -0
  174. package/dist/server/testing.js +90 -0
  175. package/dist/server/testing.js.map +1 -0
  176. package/package.json +74 -3
  177. package/src/server/client.ts +40 -0
  178. package/src/server/definition.ts +140 -0
  179. package/src/server/error.ts +73 -0
  180. package/src/server/health.ts +60 -0
  181. package/src/server/internal/batchHandler.ts +71 -0
  182. package/src/server/internal/clientCache.ts +73 -0
  183. package/src/server/internal/clientErrors.ts +64 -0
  184. package/src/server/internal/countsFor.ts +34 -0
  185. package/src/server/internal/deadlineOf.ts +8 -0
  186. package/src/server/internal/deferrableAttempt.ts +41 -0
  187. package/src/server/internal/deferral.ts +19 -0
  188. package/src/server/internal/deferralStorePlan.ts +35 -0
  189. package/src/server/internal/definitionOptions.ts +14 -0
  190. package/src/server/internal/enqueueFor.ts +39 -0
  191. package/src/server/internal/ensureQueue.ts +47 -0
  192. package/src/server/internal/expireAttempt.ts +21 -0
  193. package/src/server/internal/healthFor.ts +35 -0
  194. package/src/server/internal/jobControl.ts +44 -0
  195. package/src/server/internal/lifecycle.ts +68 -0
  196. package/src/server/internal/listJobs.ts +98 -0
  197. package/src/server/internal/makeService.ts +19 -0
  198. package/src/server/internal/nativeClient.ts +30 -0
  199. package/src/server/internal/observeTestingSettlements.ts +36 -0
  200. package/src/server/internal/register.ts +145 -0
  201. package/src/server/internal/registerReleasedJobs.ts +44 -0
  202. package/src/server/internal/registerWorker.ts +56 -0
  203. package/src/server/internal/runSchemaPlan.ts +32 -0
  204. package/src/server/internal/scheduleDefinition.ts +21 -0
  205. package/src/server/internal/schemaIndexBuilds.ts +44 -0
  206. package/src/server/internal/settleDeferral.ts +54 -0
  207. package/src/server/internal/storedRows.ts +17 -0
  208. package/src/server/internal/testingClient.ts +134 -0
  209. package/src/server/internal/testingDeferrals.ts +44 -0
  210. package/src/server/internal/testingExpirations.ts +31 -0
  211. package/src/server/internal/testingIdle.ts +52 -0
  212. package/src/server/internal/testingReadout.ts +19 -0
  213. package/src/server/internal/testingSignal.ts +30 -0
  214. package/src/server/internal/testingSnapshot.ts +53 -0
  215. package/src/server/internal/tracing.ts +44 -0
  216. package/src/server/internal/waitForBatchExpiry.ts +30 -0
  217. package/src/server/schema.ts +84 -0
  218. package/src/server/service.ts +100 -0
  219. package/src/server/testing.ts +118 -0
@@ -0,0 +1,67 @@
1
+ import { Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ import { getConstructionPlans, getMigrationPlans, PgBoss } from "pg-boss";
4
+ import pgBossPackage from "pg-boss/package.json" with { type: "json" };
5
+ import { toPgBossError } from "#error.ts";
6
+ import { deferralStorePlan } from "#internal/deferralStorePlan.ts";
7
+ import { runSchemaPlan } from "#internal/runSchemaPlan.ts";
8
+ import { resumeSchemaIndexes } from "#internal/schemaIndexBuilds.ts";
9
+ async function installSchema(connection, options, run) {
10
+ const schema = options.schema ?? "pgboss";
11
+ const construction = getConstructionPlans(schema);
12
+ const client = new PgBoss({
13
+ db: { executeSql: async (text, values = []) => ({ rows: Array.from(await run(connection.executeUnprepared(text, values, undefined))) }) },
14
+ schema,
15
+ });
16
+ if (!(await client.isInstalled())) {
17
+ await runSchemaPlan(connection, construction, run);
18
+ return;
19
+ }
20
+ const version = await client.schemaVersion();
21
+ if (version === null) {
22
+ throw new Error("The pg-boss version table is empty");
23
+ }
24
+ if (version > pgBossPackage.pgboss.schema) {
25
+ return;
26
+ }
27
+ if (version >= 27) {
28
+ await resumeSchemaIndexes(client, schema);
29
+ }
30
+ if (version < pgBossPackage.pgboss.schema) {
31
+ const partitionTables = Array.from(await run(connection.executeUnprepared(`SELECT table_name AS "tableName", policy FROM ${schema}.queue WHERE partition = true`, [], undefined)));
32
+ await runSchemaPlan(connection, getMigrationPlans(schema, version, { partitionTables }), run, { schema, version: pgBossPackage.pgboss.schema });
33
+ await resumeSchemaIndexes(client, schema);
34
+ }
35
+ }
36
+ export function installPgBossSchema(options = {}) {
37
+ return Effect.scoped(Effect.gen(function* () {
38
+ const sql = yield* SqlClient.SqlClient;
39
+ const connection = yield* sql.reserve;
40
+ const run = Effect.runPromiseWith(yield* Effect.context());
41
+ yield* Effect.tryPromise({
42
+ catch: (error) => error,
43
+ try: async () => {
44
+ await installSchema(connection, options, run);
45
+ await run(connection.executeRaw(deferralStorePlan(options.schema ?? "pgboss"), []));
46
+ },
47
+ });
48
+ }).pipe(Effect.mapError((error) => toPgBossError("install", error)))).pipe(Effect.uninterruptible);
49
+ }
50
+ export function pgBossSchema(options = {}) {
51
+ const schema = options.schema ?? "pgboss";
52
+ return {
53
+ apply: installPgBossSchema(options),
54
+ name: `pg-boss:${schema}`,
55
+ pending: Effect.gen(function* () {
56
+ const sql = yield* SqlClient.SqlClient;
57
+ const table = sql `${sql(schema)}.${sql("version")}`;
58
+ const [installed] = yield* sql `select to_regclass(${table.compile()[0]})::text as name`.withoutTransform;
59
+ const [row] = installed === undefined || installed.name === null ? [] : yield* sql `select version from ${table}`.withoutTransform;
60
+ const required = pgBossPackage.pgboss.schema;
61
+ return row === undefined || row.version < required
62
+ ? `schema ${schema}, installed version ${row?.version ?? "missing"}, required version ${required}`
63
+ : undefined;
64
+ }),
65
+ };
66
+ }
67
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/server/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { Context, Effect, Layer, type Option, type Schema } from "effect";
2
+ import type { ConstructorOptions, JobWithMetadata, SendOptions, StopOptions } from "pg-boss";
3
+ import type { PgBossClientFactory } from "#client.ts";
4
+ import type { JobPayloadSchema, JobRegistration, QueueDefinition, RegistrationRequirements } from "#definition.ts";
5
+ import type { PgBossClientOptionsError, PgBossError, PgBossPayloadError, PgBossQueueOptionsError } from "#error.ts";
6
+ import type { DeadLetteredJob, JobPage, JobPageOptions, JobsHealth, ListedJob, QueueCounts } from "#health.ts";
7
+ export interface PgBossService {
8
+ readonly counts: (queue: Pick<QueueDefinition, "name">) => Effect.Effect<QueueCounts, PgBossError>;
9
+ readonly deadLetteredJobs: <const TName extends string, const TPayload extends JobPayloadSchema>(queue: Pick<QueueDefinition<TName, TPayload>, "name" | "schema">, options: JobPageOptions) => Effect.Effect<JobPage<DeadLetteredJob<TPayload["Type"]>>, PgBossError | PgBossPayloadError, TPayload["DecodingServices"]>;
10
+ readonly enqueue: <const TName extends string, const TPayload extends JobPayloadSchema, const TQueue extends QueueDefinition<TName, TPayload>>(queue: QueueDefinition<TName, TPayload> & TQueue, payload: NoInfer<Schema.Schema.Type<TPayload>>, options?: NoInfer<TQueue["key"] extends undefined ? SendOptions : Omit<SendOptions, "singletonKey"> & {
11
+ readonly singletonKey?: never;
12
+ }>) => Effect.Effect<Option.Option<string>, PgBossError | PgBossPayloadError, TPayload["EncodingServices"]>;
13
+ readonly failedJobs: <const TName extends string, const TPayload extends JobPayloadSchema>(queue: Pick<QueueDefinition<TName, TPayload>, "name" | "schema">, options: JobPageOptions) => Effect.Effect<JobPage<ListedJob<TPayload["Type"]>>, PgBossError | PgBossPayloadError, TPayload["DecodingServices"]>;
14
+ readonly getJob: <const TName extends string, const TPayload extends JobPayloadSchema>(queue: Pick<QueueDefinition<TName, TPayload>, "name" | "schema">, id: string) => Effect.Effect<Option.Option<JobWithMetadata<TPayload["Type"]>>, PgBossError | PgBossPayloadError, TPayload["DecodingServices"]>;
15
+ readonly health: Effect.Effect<JobsHealth, PgBossError>;
16
+ readonly retry: (queue: Pick<QueueDefinition, "name">, id: string) => Effect.Effect<void, PgBossError>;
17
+ }
18
+ export type PgBossLayerOptions<TRegistrations extends readonly JobRegistration[], TErrorRequirements> = ConstructorOptions & {
19
+ readonly clientFactory?: PgBossClientFactory;
20
+ readonly clientCacheKey?: string | symbol | undefined;
21
+ readonly jobs: TRegistrations;
22
+ readonly onError?: (error: Error) => Effect.Effect<unknown, never, TErrorRequirements>;
23
+ readonly stop?: StopOptions;
24
+ };
25
+ export interface PgBossDefinition<TIdentifier extends string = string> extends Context.Service<TIdentifier, PgBossService> {
26
+ readonly layer: <const TRegistrations extends readonly JobRegistration[], TErrorRequirements = never>(options: PgBossLayerOptions<TRegistrations, TErrorRequirements>) => Layer.Layer<TIdentifier, PgBossError | PgBossQueueOptionsError | PgBossClientOptionsError, Exclude<RegistrationRequirements<TRegistrations>, TIdentifier> | TErrorRequirements>;
27
+ }
28
+ export declare function makePgBoss<const TIdentifier extends string>(identifier: TIdentifier): PgBossDefinition<TIdentifier>;
29
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/server/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { Context, Effect, Layer } from "effect";
2
+ import { logClientError, subscribeClientErrors } from "#internal/clientErrors.ts";
3
+ import { acquireClient, releaseClient } from "#internal/lifecycle.ts";
4
+ import { makeService } from "#internal/makeService.ts";
5
+ import { registrationName } from "#internal/register.ts";
6
+ import { registerReleasedJobs } from "#internal/registerReleasedJobs.ts";
7
+ export function makePgBoss(identifier) {
8
+ const Service = Context.Service(identifier);
9
+ function layer(options) {
10
+ const names = options.jobs.map(registrationName);
11
+ const { clientFactory, clientCacheKey, jobs, onError, stop, ...constructorOptions } = options;
12
+ const acquire = Effect.acquireRelease(Effect.gen(function* () {
13
+ const dependencies = yield* Effect.context();
14
+ const acquired = yield* acquireClient({
15
+ clientCacheKey,
16
+ clientFactory,
17
+ constructor: constructorOptions,
18
+ });
19
+ const service = makeService(acquired.client, names, constructorOptions.schema);
20
+ const context = Context.add(dependencies, Service, service);
21
+ const reportError = onError ?? logClientError;
22
+ function errorListener(error) {
23
+ void Effect.runPromise(Effect.exit(Effect.provide(reportError(error), context)));
24
+ }
25
+ const unsubscribe = subscribeClientErrors(acquired.client, errorListener);
26
+ const registration = registerReleasedJobs(acquired.client, jobs, context, acquired.reused, constructorOptions.schema);
27
+ return yield* registration.pipe(Effect.as({ acquired, service, unsubscribe }), Effect.onError(() => releaseClient(acquired, stop).pipe(Effect.ensuring(Effect.sync(unsubscribe)))));
28
+ }), (resource) => releaseClient(resource.acquired, stop).pipe(Effect.ensuring(Effect.sync(resource.unsubscribe))));
29
+ return Layer.effect(Service, Effect.map(acquire, ({ service }) => service));
30
+ }
31
+ return Object.assign(Service, { layer });
32
+ }
33
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/server/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ import { type DateTime, Duration, Effect } from "effect";
2
+ import type { PgBossClientFactory } from "#client.ts";
3
+ import type { JobPayloadSchema, QueueDefinition } from "#definition.ts";
4
+ import { PgBossTestingError } from "#error.ts";
5
+ export type SnapshotQueue = Pick<QueueDefinition<string, JobPayloadSchema>, "name" | "schema">;
6
+ export interface UnfinishedJob<TQueue extends SnapshotQueue> {
7
+ readonly data: TQueue["schema"]["Type"];
8
+ readonly id: string;
9
+ readonly queue: TQueue["name"];
10
+ readonly startAfter: DateTime.Utc;
11
+ readonly state: "active" | "created" | "failed" | "retry";
12
+ }
13
+ export declare const testRetryPolicy: Readonly<{
14
+ retryBackoff: false;
15
+ retryDelay: 0;
16
+ }>;
17
+ export interface PgBossTestingOptions {
18
+ readonly retryPolicy?: typeof testRetryPolicy;
19
+ }
20
+ export declare function makePgBossTesting(options?: PgBossTestingOptions): {
21
+ deferred: (queue: Pick<QueueDefinition, "name">) => Effect.Effect<{
22
+ at: DateTime.Utc;
23
+ reason: string;
24
+ }[], PgBossTestingError, never>;
25
+ runDeferredNow: (queue: Pick<QueueDefinition, "name">) => Effect.Effect<void, PgBossTestingError, never>;
26
+ checkBatchWindow: (queue: Pick<QueueDefinition, "name" | "workerOptions">, millisecondsPerJob: number) => Effect.Effect<void, PgBossTestingError, never>;
27
+ checkSchemaVersion: (expected: number) => Effect.Effect<void, PgBossTestingError, never>;
28
+ clientFactory: PgBossClientFactory;
29
+ expireAfter: (queue: Pick<QueueDefinition, "name">, attempts: number) => Effect.Effect<void, PgBossTestingError, never>;
30
+ expireIn: (queue: Pick<QueueDefinition, "name">, duration: Duration.Input) => Effect.Effect<void, PgBossTestingError, never>;
31
+ failNextSend: (queue: Pick<QueueDefinition, "name">) => Effect.Effect<void, never, never>;
32
+ jobs: <TName extends string, TPayload extends JobPayloadSchema>(queue: QueueDefinition<TName, TPayload>, options?: import("pg-boss").FindJobsOptions) => Effect.Effect<{
33
+ id: string;
34
+ name: string;
35
+ retryCount: number;
36
+ signal: AbortSignal;
37
+ groupId?: string | null;
38
+ groupTier?: string | null;
39
+ priority: number;
40
+ state: 'created' | 'retry' | 'active' | 'completed' | 'cancelled' | 'failed';
41
+ retryLimit: number;
42
+ retryDelay: number;
43
+ retryBackoff: boolean;
44
+ retryDelayMax?: number;
45
+ startAfter: Date;
46
+ startedOn: Date;
47
+ singletonKey: string | null;
48
+ singletonOn: Date | null;
49
+ expireInSeconds: number;
50
+ deleteAfterSeconds: number;
51
+ createdOn: Date;
52
+ completedOn: Date | null;
53
+ keepUntil: Date;
54
+ policy: import("pg-boss").QueuePolicy;
55
+ heartbeatOn: Date | null;
56
+ heartbeatSeconds: number | null;
57
+ blocked: boolean;
58
+ blocking: boolean;
59
+ pendingDependencies: number;
60
+ deadLetter: string;
61
+ output: object;
62
+ sourceName: string | null;
63
+ sourceId: string | null;
64
+ sourceCreatedOn: Date | null;
65
+ sourceRetryCount: number | null;
66
+ sourceOutput: object | null;
67
+ sourceRootId: string | null;
68
+ data: TPayload["Type"];
69
+ }[], import("#error.ts").PgBossPayloadError | PgBossTestingError, TPayload["DecodingServices"]>;
70
+ revision: Effect.Effect<number, never, never>;
71
+ schemaVersion: Effect.Effect<number | null, PgBossTestingError, never>;
72
+ snapshot: <const TQueues extends readonly SnapshotQueue[]>(queues: TQueues) => Effect.Effect<readonly UnfinishedJob<TQueues[number]>[], import("#error.ts").PgBossPayloadError | PgBossTestingError, TQueues[number]["schema"]["DecodingServices"]>;
73
+ waitForChange: (after: number) => Effect.Effect<number>;
74
+ waitForIdle: Effect.Effect<void, PgBossTestingError, never>;
75
+ };
76
+ export type PgBossTesting = ReturnType<typeof makePgBossTesting>;
77
+ //# sourceMappingURL=testing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/server/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAY,MAAM,QAAQ,CAAC;AAEnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAS/C,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC;AAE/F,MAAM,WAAW,aAAa,CAAC,MAAM,SAAS,aAAa;IAC1D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;IACxC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;CAC1D;AAED,eAAO,MAAM,eAAe;;;EAAwD,CAAC;AAErF,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,eAAe,CAAC;CAC9C;AAED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,oBAAyB;;;;;;8BA6BxC,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,eAAe,CAAC,sBAAsB,MAAM;mCAqBtE,MAAM;;yBAOhB,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,YAAY,MAAM;sBAUlD,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,YAAY,QAAQ,CAAC,KAAK;0BAWnD,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQpD;AAED,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
@@ -0,0 +1,90 @@
1
+ import { Duration, Effect, Redacted } from "effect";
2
+ import { PgBossTestingError } from "#error.ts";
3
+ import { nativeClient } from "#internal/nativeClient.ts";
4
+ import { testingClient } from "#internal/testingClient.ts";
5
+ import { testingDeferrals } from "#internal/testingDeferrals.ts";
6
+ import { testingIdle } from "#internal/testingIdle.ts";
7
+ import { testingOperation, testingReadout } from "#internal/testingReadout.ts";
8
+ import { testingSignal } from "#internal/testingSignal.ts";
9
+ import { testingSnapshot } from "#internal/testingSnapshot.ts";
10
+ export const testRetryPolicy = Object.freeze({ retryBackoff: false, retryDelay: 0 });
11
+ export function makePgBossTesting(options = {}) {
12
+ let current;
13
+ let schema = "pgboss";
14
+ const signal = testingSignal();
15
+ const work = { batches: new Set(), queues: new Set() };
16
+ const controls = {
17
+ changed: signal.changed,
18
+ expirations: new Map(),
19
+ expirySeconds: new Map(),
20
+ failures: new Set(),
21
+ retryPolicy: options.retryPolicy ?? {},
22
+ work,
23
+ };
24
+ function client() {
25
+ if (current === undefined) {
26
+ throw new Error("Provide the testing clientFactory to a jobs Layer first");
27
+ }
28
+ return current;
29
+ }
30
+ const clientFactory = (clientOptions) => {
31
+ if (current !== undefined) {
32
+ throw new Error("A testing controller owns one jobs client; create a controller per runtime");
33
+ }
34
+ schema = clientOptions.schema ?? "pgboss";
35
+ current = nativeClient({ ...clientOptions, "__test__enableSpies": true });
36
+ return testingClient(current, clientOptions.schema ?? "pgboss", controls);
37
+ };
38
+ return {
39
+ ...testingDeferrals(client, () => schema, signal.changed),
40
+ checkBatchWindow: (queue, millisecondsPerJob) => testingOperation("checkBatchWindow", async () => {
41
+ const stored = await client().getQueue(queue.name);
42
+ if (stored === null) {
43
+ throw new Error("Queue is not registered");
44
+ }
45
+ if (stored.expireInSeconds === undefined) {
46
+ throw new Error("Queue has no expiry window");
47
+ }
48
+ if (!Number.isFinite(millisecondsPerJob) || millisecondsPerJob < 0) {
49
+ throw new RangeError("Job duration must be nonnegative and finite");
50
+ }
51
+ const required = (queue.workerOptions.batchSize ?? 10) * millisecondsPerJob;
52
+ if (required >= stored.expireInSeconds * 1000) {
53
+ throw new Error("Sequential batch work must fit within the queue expiry window");
54
+ }
55
+ }, queue.name),
56
+ checkSchemaVersion: (expected) => testingOperation("checkSchemaVersion", async () => {
57
+ if ((await client().schemaVersion()) !== expected) {
58
+ throw new Error(`Expected pg-boss schema version ${expected}`);
59
+ }
60
+ }),
61
+ clientFactory,
62
+ expireAfter: (queue, attempts) => Effect.try({
63
+ catch: (original) => new PgBossTestingError({ operation: "expireAfter", original: Redacted.make(original), queue: queue.name }),
64
+ try: () => {
65
+ if (!Number.isSafeInteger(attempts) || attempts < 1) {
66
+ throw new RangeError("Attempts must be a positive integer");
67
+ }
68
+ controls.expirations.set(queue.name, attempts);
69
+ },
70
+ }),
71
+ expireIn: (queue, duration) => Effect.try({
72
+ catch: (original) => new PgBossTestingError({ operation: "expireIn", original: Redacted.make(original), queue: queue.name }),
73
+ try: () => {
74
+ const milliseconds = Duration.toMillis(Duration.fromInputUnsafe(duration));
75
+ if (!Number.isFinite(milliseconds) || milliseconds < 1000) {
76
+ throw new RangeError("Expiry must be finite and at least one second");
77
+ }
78
+ controls.expirySeconds.set(queue.name, Math.ceil(milliseconds / 1000));
79
+ },
80
+ }),
81
+ failNextSend: (queue) => Effect.sync(() => controls.failures.add(queue.name)).pipe(Effect.asVoid),
82
+ jobs: testingReadout(client),
83
+ revision: signal.revision,
84
+ schemaVersion: testingOperation("schemaVersion", () => client().schemaVersion()),
85
+ snapshot: testingSnapshot(client, () => schema),
86
+ waitForChange: signal.waitForChange,
87
+ waitForIdle: testingIdle(client, () => schema, work, signal),
88
+ };
89
+ }
90
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../../src/server/testing.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,77 @@
1
1
  {
2
2
  "name": "@shivaedev/jobs",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.19.0",
4
+ "description": "Effect-native jobs and lifecycle management for pg-boss",
5
+ "keywords": [
6
+ "effect"
7
+ ],
8
+ "homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/jobs#readme",
9
+ "bugs": {
10
+ "url": "https://github.com/ShivaeDev/platform/issues"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/ShivaeDev/platform.git",
15
+ "directory": "packages/jobs"
16
+ },
17
+ "license": "MIT",
18
+ "sideEffects": false,
19
+ "type": "module",
20
+ "imports": {
21
+ "#test/*": "./src/test-support/*",
22
+ "#*.ts": {
23
+ "source": "./src/server/*.ts",
24
+ "types": "./dist/server/*.d.ts",
25
+ "default": "./dist/server/*.js"
26
+ }
27
+ },
28
+ "exports": {
29
+ "./*.ts": {
30
+ "source": "./src/*.ts",
31
+ "types": "./dist/*.d.ts",
32
+ "default": "./dist/*.js"
33
+ },
34
+ "./package.json": "./package.json",
35
+ "./server/internal/*": null
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "src",
40
+ "!src/**/*.test.ts",
41
+ "!src/**/*.spec.ts",
42
+ "!src/**/test-support",
43
+ "CHANGELOG.md",
44
+ "README.md"
45
+ ],
46
+ "dependencies": {
47
+ "@shivaedev/sql": "0.21.0"
48
+ },
49
+ "devDependencies": {
50
+ "@shivaedev/quality": "0.41.1",
51
+ "@shivaedev/test": "0.9.0",
52
+ "@shivaedev/test-sql": "0.9.3",
53
+ "@shivaedev/test-story": "0.20.1",
54
+ "@types/node": "24.19.2",
55
+ "effect": "4.0.5",
56
+ "pg-boss": "12.38.0",
57
+ "typescript": "7.0.2",
58
+ "vitest": "5.0.5"
59
+ },
60
+ "peerDependencies": {
61
+ "effect": "4.0.5",
62
+ "pg-boss": "12.38.0"
63
+ },
64
+ "engines": {
65
+ "node": ">=24"
66
+ },
67
+ "publishConfig": {
68
+ "access": "public",
69
+ "provenance": true
70
+ },
71
+ "scripts": {
72
+ "build": "node --eval \"import('node:fs').then(({ rmSync }) => rmSync('dist', { force: true, recursive: true }))\" && tsc --project tsconfig.build.json",
73
+ "ready": "pnpm typecheck && pnpm test && pnpm build",
74
+ "test": "vitest run",
75
+ "typecheck": "tsc --noEmit"
76
+ }
6
77
  }
@@ -0,0 +1,40 @@
1
+ import type {
2
+ ConstructorOptions,
3
+ FindJobsOptions,
4
+ Job,
5
+ JobWithMetadata,
6
+ PgBoss,
7
+ Queue,
8
+ QueueResult,
9
+ ScheduleOptions,
10
+ SendOptions,
11
+ StopOptions,
12
+ WorkOptions,
13
+ } from "pg-boss";
14
+ import { nativeClient } from "#internal/nativeClient.ts";
15
+
16
+ export interface PgBossClient {
17
+ readonly complete?: PgBoss["complete"];
18
+ readonly createQueue: (name: string, options?: Omit<Queue, "name">) => Promise<void>;
19
+ readonly fail?: PgBoss["fail"];
20
+ readonly findJobs?: (name: string, options?: FindJobsOptions) => Promise<readonly JobWithMetadata<unknown>[]>;
21
+ readonly getDb?: PgBoss["getDb"];
22
+ readonly getQueue: (name: string) => Promise<QueueResult | null>;
23
+ readonly getWipData?: PgBoss["getWipData"];
24
+ readonly notifyWorker?: PgBoss["notifyWorker"];
25
+ readonly off: (event: "error", listener: (error: Error) => void) => unknown;
26
+ readonly offWork: (name: string) => Promise<void>;
27
+ readonly on: (event: "error", listener: (error: Error) => void) => unknown;
28
+ readonly retry?: PgBoss["retry"];
29
+ readonly schedule: (name: string, cron: string, data?: object | null, options?: ScheduleOptions) => Promise<void>;
30
+ readonly send: (name: string, data?: object | null, options?: SendOptions) => Promise<string | null>;
31
+ readonly start: () => Promise<unknown>;
32
+ readonly stop: (options?: StopOptions) => Promise<void>;
33
+ readonly update?: PgBoss["update"];
34
+ readonly updateQueue?: PgBoss["updateQueue"];
35
+ readonly work: (name: string, options: WorkOptions, handler: (jobs: readonly Job<unknown>[]) => Promise<unknown>) => Promise<string>;
36
+ }
37
+
38
+ export type PgBossClientFactory = (options: ConstructorOptions) => PgBossClient;
39
+
40
+ export const defaultClientFactory: PgBossClientFactory = nativeClient;
@@ -0,0 +1,140 @@
1
+ import { Clock, Duration, Effect, Schema } from "effect";
2
+ import type { Job, policies, Queue, ScheduleOptions, WorkOptions } from "pg-boss";
3
+ import { deadlineOf } from "#internal/deadlineOf.ts";
4
+ import { maxDeferrals, nativeQueueOptions } from "#internal/definitionOptions.ts";
5
+ import { scheduleDefinition } from "#internal/scheduleDefinition.ts";
6
+
7
+ export class RetryAt extends Schema.TaggedError<RetryAt>()("RetryAt", {
8
+ at: Schema.DateTimeUtc,
9
+ reason: Schema.String,
10
+ }) {}
11
+
12
+ export type QueuePolicy = (typeof policies)[keyof typeof policies];
13
+ export type QueueOptions = Omit<Queue, "name" | "deadLetter" | "policy"> & {
14
+ readonly maxDeferrals?: number;
15
+ readonly policy?: QueuePolicy;
16
+ };
17
+
18
+ export interface JobPayloadSchema extends Schema.Top {
19
+ readonly Encoded: object;
20
+ readonly Type: object;
21
+ }
22
+
23
+ export interface JobContext {
24
+ readonly expireInSeconds: number;
25
+ readonly heartbeatSeconds: number | null;
26
+ readonly id: string;
27
+ readonly name: string;
28
+ readonly remainingBudget: Effect.Effect<Duration.Duration>;
29
+ readonly signal: AbortSignal;
30
+ }
31
+
32
+ export interface QueueDefinition<TName extends string = string, TPayload extends JobPayloadSchema = JobPayloadSchema> {
33
+ readonly _tag: "QueueDefinition";
34
+ readonly handle: <E, R>(
35
+ handler: (payload: Schema.Schema.Type<TPayload>, job: JobContext) => Effect.Effect<unknown, E, R>,
36
+ ) => QueueWorker<TPayload, R>;
37
+ readonly key?: ((payload: Schema.Schema.Type<TPayload>) => string) | undefined;
38
+ readonly maxDeferrals: number;
39
+ readonly name: TName;
40
+ readonly queueOptions: Omit<Queue, "name" | "deadLetter">;
41
+ readonly schema: TPayload;
42
+ readonly workerOptions: WorkOptions;
43
+ }
44
+
45
+ export interface QueueWorker<TPayload extends JobPayloadSchema = JobPayloadSchema, TRequirements = unknown> {
46
+ readonly _tag: "QueueWorker";
47
+ readonly handler: (payload: Schema.Schema.Type<TPayload>, job: JobContext) => Effect.Effect<unknown, unknown, TRequirements>;
48
+ readonly queue: QueueDefinition<string, TPayload>;
49
+ }
50
+
51
+ export interface JobRegistration {
52
+ readonly _tag: "QueueDefinition" | "QueueWorker" | "ScheduledWorker";
53
+ }
54
+
55
+ export interface ScheduleDefinition<TName extends string = string> {
56
+ readonly _tag: "ScheduleDefinition";
57
+ readonly cron: string;
58
+ readonly maxDeferrals: number;
59
+ readonly name: TName;
60
+ readonly queueOptions: Omit<Queue, "name" | "deadLetter">;
61
+ readonly run: <E, R>(effect: Effect.Effect<unknown, E, R>) => ScheduledWorker<R>;
62
+ readonly scheduleOptions: ScheduleOptions;
63
+ readonly workerOptions: WorkOptions;
64
+ }
65
+
66
+ export interface ScheduledWorker<TRequirements = unknown> {
67
+ readonly _tag: "ScheduledWorker";
68
+ readonly effect: Effect.Effect<unknown, unknown, TRequirements>;
69
+ readonly schedule: ScheduleDefinition;
70
+ }
71
+
72
+ export type RegistrationRequirements<TRegistrations extends readonly JobRegistration[]> = TRegistrations[number] extends infer TRegistration
73
+ ? TRegistration extends QueueWorker<infer TPayload, infer TRequirements>
74
+ ? TRequirements | TPayload["DecodingServices"]
75
+ : TRegistration extends ScheduledWorker<infer TRequirements>
76
+ ? TRequirements
77
+ : never
78
+ : never;
79
+
80
+ export type DefineQueueOptions<TName extends string, TPayload extends JobPayloadSchema> = {
81
+ readonly name: TName;
82
+ readonly schema: TPayload;
83
+ readonly worker?: WorkOptions;
84
+ } & (
85
+ | { readonly key: (payload: Schema.Schema.Type<TPayload>) => string; readonly queue: QueueOptions & { readonly policy: "singleton" } }
86
+ | { readonly key?: never; readonly queue?: QueueOptions & { readonly policy?: Exclude<QueuePolicy, "singleton"> } }
87
+ );
88
+
89
+ export function defineQueue<const TName extends string, const TPayload extends JobPayloadSchema>(
90
+ options: DefineQueueOptions<TName, TPayload> & { readonly key: (payload: Schema.Schema.Type<TPayload>) => string },
91
+ ): QueueDefinition<TName, TPayload> & { readonly key: (payload: Schema.Schema.Type<TPayload>) => string };
92
+ export function defineQueue<const TName extends string, const TPayload extends JobPayloadSchema>(
93
+ options: DefineQueueOptions<TName, TPayload> & { readonly key?: never },
94
+ ): QueueDefinition<TName, TPayload> & { readonly key?: never };
95
+ export function defineQueue<const TName extends string, const TPayload extends JobPayloadSchema>(
96
+ options: DefineQueueOptions<TName, TPayload>,
97
+ ): QueueDefinition<TName, TPayload>;
98
+ export function defineQueue<const TName extends string, const TPayload extends JobPayloadSchema>(
99
+ options: DefineQueueOptions<TName, TPayload>,
100
+ ): QueueDefinition<TName, TPayload> {
101
+ const definition: QueueDefinition<TName, TPayload> = {
102
+ _tag: "QueueDefinition",
103
+ ...(options.key === undefined ? {} : { key: options.key }),
104
+ handle: (handler) =>
105
+ Object.freeze({
106
+ _tag: "QueueWorker" as const,
107
+ handler,
108
+ queue: definition,
109
+ }),
110
+ maxDeferrals: maxDeferrals(options.queue),
111
+ name: options.name,
112
+ queueOptions: nativeQueueOptions(options.queue),
113
+ schema: options.schema,
114
+ workerOptions: Object.freeze({ batchSize: 10, burstWhenBatchFull: true, ...options.worker }),
115
+ };
116
+ return Object.freeze(definition);
117
+ }
118
+
119
+ export interface DefineScheduleOptions<TName extends string> {
120
+ readonly cron: string;
121
+ readonly name: TName;
122
+ readonly queue?: QueueOptions;
123
+ readonly schedule?: ScheduleOptions;
124
+ readonly worker?: WorkOptions;
125
+ }
126
+
127
+ export function defineSchedule<const TName extends string>(options: DefineScheduleOptions<TName>): ScheduleDefinition<TName> {
128
+ return scheduleDefinition(options);
129
+ }
130
+
131
+ export function jobContext(job: Job<unknown>): JobContext {
132
+ return {
133
+ expireInSeconds: job.expireInSeconds,
134
+ heartbeatSeconds: job.heartbeatSeconds,
135
+ id: job.id,
136
+ name: job.name,
137
+ remainingBudget: Effect.map(Clock.currentTimeMillis, (now) => Duration.millis(Math.max(0, deadlineOf(job) - now))),
138
+ signal: job.signal,
139
+ };
140
+ }