glasswork 0.12.1 → 0.13.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.
- package/dist/auth/abilities.d.ts +41 -0
- package/dist/auth/abilities.d.ts.map +1 -0
- package/dist/auth/abilities.js +62 -0
- package/dist/auth/abilities.js.map +1 -0
- package/dist/auth/assert.d.ts +20 -0
- package/dist/auth/assert.d.ts.map +1 -0
- package/dist/auth/assert.js +28 -0
- package/dist/auth/assert.js.map +1 -0
- package/dist/auth/better-auth-provider.d.ts +56 -0
- package/dist/auth/better-auth-provider.d.ts.map +1 -0
- package/dist/auth/better-auth-provider.js +62 -0
- package/dist/auth/better-auth-provider.js.map +1 -0
- package/dist/auth/index.d.ts +6 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +5 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/middleware.d.ts +31 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +92 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/auth/types.d.ts +54 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +2 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/core/bootstrap.d.ts.map +1 -1
- package/dist/core/bootstrap.js +5 -2
- package/dist/core/bootstrap.js.map +1 -1
- package/dist/core/types.d.ts +14 -3
- package/dist/core/types.d.ts.map +1 -1
- package/dist/http/route-helpers.d.ts +47 -9
- package/dist/http/route-helpers.d.ts.map +1 -1
- package/dist/http/route-helpers.js +91 -40
- package/dist/http/route-helpers.js.map +1 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/jobs/define-job.d.ts +57 -0
- package/dist/jobs/define-job.d.ts.map +1 -0
- package/dist/jobs/define-job.js +12 -0
- package/dist/jobs/define-job.js.map +1 -0
- package/dist/jobs/drivers/eventbridge-scheduler-driver.d.ts +75 -0
- package/dist/jobs/drivers/eventbridge-scheduler-driver.d.ts.map +1 -0
- package/dist/jobs/drivers/eventbridge-scheduler-driver.js +135 -0
- package/dist/jobs/drivers/eventbridge-scheduler-driver.js.map +1 -0
- package/dist/jobs/drivers/mock-driver.d.ts +73 -0
- package/dist/jobs/drivers/mock-driver.d.ts.map +1 -0
- package/dist/jobs/drivers/mock-driver.js +95 -0
- package/dist/jobs/drivers/mock-driver.js.map +1 -0
- package/dist/jobs/drivers/sqs-driver.d.ts +59 -0
- package/dist/jobs/drivers/sqs-driver.d.ts.map +1 -0
- package/dist/jobs/drivers/sqs-driver.js +176 -0
- package/dist/jobs/drivers/sqs-driver.js.map +1 -0
- package/dist/jobs/errors.d.ts +44 -0
- package/dist/jobs/errors.d.ts.map +1 -0
- package/dist/jobs/errors.js +67 -0
- package/dist/jobs/errors.js.map +1 -0
- package/dist/jobs/index.d.ts +12 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +11 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/jobs/job-registry.d.ts +33 -0
- package/dist/jobs/job-registry.d.ts.map +1 -0
- package/dist/jobs/job-registry.js +56 -0
- package/dist/jobs/job-registry.js.map +1 -0
- package/dist/jobs/job-service.d.ts +44 -0
- package/dist/jobs/job-service.d.ts.map +1 -0
- package/dist/jobs/job-service.js +105 -0
- package/dist/jobs/job-service.js.map +1 -0
- package/dist/jobs/periodic-job.d.ts +6 -0
- package/dist/jobs/periodic-job.d.ts.map +1 -0
- package/dist/jobs/periodic-job.js +11 -0
- package/dist/jobs/periodic-job.js.map +1 -0
- package/dist/jobs/schedule-constants.d.ts +5 -0
- package/dist/jobs/schedule-constants.d.ts.map +1 -0
- package/dist/jobs/schedule-constants.js +5 -0
- package/dist/jobs/schedule-constants.js.map +1 -0
- package/dist/jobs/scheduler.d.ts +17 -0
- package/dist/jobs/scheduler.d.ts.map +1 -0
- package/dist/jobs/scheduler.js +83 -0
- package/dist/jobs/scheduler.js.map +1 -0
- package/dist/jobs/types.d.ts +165 -0
- package/dist/jobs/types.d.ts.map +1 -0
- package/dist/jobs/types.js +2 -0
- package/dist/jobs/types.js.map +1 -0
- package/dist/jobs/utils.d.ts +15 -0
- package/dist/jobs/utils.d.ts.map +1 -0
- package/dist/jobs/utils.js +49 -0
- package/dist/jobs/utils.js.map +1 -0
- package/dist/jobs/worker.d.ts +35 -0
- package/dist/jobs/worker.d.ts.map +1 -0
- package/dist/jobs/worker.js +361 -0
- package/dist/jobs/worker.js.map +1 -0
- package/dist/list-query/casl.d.ts +18 -19
- package/dist/list-query/casl.d.ts.map +1 -1
- package/dist/list-query/casl.js +40 -46
- package/dist/list-query/casl.js.map +1 -1
- package/dist/uploads/file-upload.d.ts +44 -0
- package/dist/uploads/file-upload.d.ts.map +1 -0
- package/dist/uploads/file-upload.js +145 -0
- package/dist/uploads/file-upload.js.map +1 -0
- package/dist/uploads/index.d.ts +6 -0
- package/dist/uploads/index.d.ts.map +1 -0
- package/dist/uploads/index.js +7 -0
- package/dist/uploads/index.js.map +1 -0
- package/dist/uploads/uploads.service.d.ts +98 -0
- package/dist/uploads/uploads.service.d.ts.map +1 -0
- package/dist/uploads/uploads.service.js +134 -0
- package/dist/uploads/uploads.service.js.map +1 -0
- package/dist/uploads/validators.d.ts +41 -0
- package/dist/uploads/validators.d.ts.map +1 -0
- package/dist/uploads/validators.js +94 -0
- package/dist/uploads/validators.js.map +1 -0
- package/package.json +34 -3
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { BaseIssue } from 'valibot';
|
|
2
|
+
/**
|
|
3
|
+
* Indicates a job should not be retried.
|
|
4
|
+
*/
|
|
5
|
+
export declare class PermanentJobError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Thrown when a job payload exceeds the allowed size.
|
|
10
|
+
*/
|
|
11
|
+
export declare class PayloadTooLargeError extends Error {
|
|
12
|
+
readonly actualSize: number;
|
|
13
|
+
readonly maxSize: number;
|
|
14
|
+
constructor(actualSize: number, maxSize: number);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Thrown when payload validation fails against the job schema.
|
|
18
|
+
*/
|
|
19
|
+
export declare class InvalidJobPayloadError extends Error {
|
|
20
|
+
readonly jobName: string;
|
|
21
|
+
readonly issues: BaseIssue<unknown>[];
|
|
22
|
+
constructor(jobName: string, issues: BaseIssue<unknown>[]);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Indicates a transient failure that should be retried.
|
|
26
|
+
* Optionally carries a retry-after duration.
|
|
27
|
+
*/
|
|
28
|
+
export declare class TransientJobError extends Error {
|
|
29
|
+
readonly retryAfter?: import('./types.js').Duration;
|
|
30
|
+
constructor(message: string, retryAfter?: import('./types.js').Duration);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Thrown internally when a job has exhausted all retry attempts.
|
|
34
|
+
* This triggers the onJobDeadLetter hook and indicates the job
|
|
35
|
+
* should be moved to the dead letter queue.
|
|
36
|
+
*/
|
|
37
|
+
export declare class RetryExhaustedError extends Error {
|
|
38
|
+
readonly jobName: string;
|
|
39
|
+
readonly attemptNumber: number;
|
|
40
|
+
readonly maxAttempts: number;
|
|
41
|
+
readonly cause: Error;
|
|
42
|
+
constructor(jobName: string, attemptNumber: number, maxAttempts: number, cause: Error);
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/jobs/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAUhD;AAED;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;gBAE1B,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,EAAE;CAM1D;AAED;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,YAAY,EAAE,QAAQ,CAAC;gBAExC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,YAAY,EAAE,QAAQ;CAKxE;AAED;;;;GAIG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;gBAEV,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK;CAQtF"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Indicates a job should not be retried.
|
|
3
|
+
*/
|
|
4
|
+
export class PermanentJobError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'PermanentJobError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Thrown when a job payload exceeds the allowed size.
|
|
12
|
+
*/
|
|
13
|
+
export class PayloadTooLargeError extends Error {
|
|
14
|
+
actualSize;
|
|
15
|
+
maxSize;
|
|
16
|
+
constructor(actualSize, maxSize) {
|
|
17
|
+
super(`Job payload size (${Math.round(actualSize / 1024)}KB) exceeds SQS limit (${Math.round(maxSize / 1024)}KB). Consider storing large data externally and passing a reference.`);
|
|
18
|
+
this.name = 'PayloadTooLargeError';
|
|
19
|
+
this.actualSize = actualSize;
|
|
20
|
+
this.maxSize = maxSize;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Thrown when payload validation fails against the job schema.
|
|
25
|
+
*/
|
|
26
|
+
export class InvalidJobPayloadError extends Error {
|
|
27
|
+
jobName;
|
|
28
|
+
issues;
|
|
29
|
+
constructor(jobName, issues) {
|
|
30
|
+
super(`Invalid payload for job "${jobName}"`);
|
|
31
|
+
this.name = 'InvalidJobPayloadError';
|
|
32
|
+
this.jobName = jobName;
|
|
33
|
+
this.issues = issues;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Indicates a transient failure that should be retried.
|
|
38
|
+
* Optionally carries a retry-after duration.
|
|
39
|
+
*/
|
|
40
|
+
export class TransientJobError extends Error {
|
|
41
|
+
retryAfter;
|
|
42
|
+
constructor(message, retryAfter) {
|
|
43
|
+
super(message);
|
|
44
|
+
this.name = 'TransientJobError';
|
|
45
|
+
this.retryAfter = retryAfter;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Thrown internally when a job has exhausted all retry attempts.
|
|
50
|
+
* This triggers the onJobDeadLetter hook and indicates the job
|
|
51
|
+
* should be moved to the dead letter queue.
|
|
52
|
+
*/
|
|
53
|
+
export class RetryExhaustedError extends Error {
|
|
54
|
+
jobName;
|
|
55
|
+
attemptNumber;
|
|
56
|
+
maxAttempts;
|
|
57
|
+
cause;
|
|
58
|
+
constructor(jobName, attemptNumber, maxAttempts, cause) {
|
|
59
|
+
super(`Job "${jobName}" exhausted ${maxAttempts} retries after ${attemptNumber} attempts`);
|
|
60
|
+
this.name = 'RetryExhaustedError';
|
|
61
|
+
this.jobName = jobName;
|
|
62
|
+
this.attemptNumber = attemptNumber;
|
|
63
|
+
this.maxAttempts = maxAttempts;
|
|
64
|
+
this.cause = cause;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/jobs/errors.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,UAAU,CAAS;IACnB,OAAO,CAAS;IAEzB,YAAY,UAAkB,EAAE,OAAe;QAC7C,KAAK,CACH,qBAAqB,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,0BAA0B,IAAI,CAAC,KAAK,CACpF,OAAO,GAAG,IAAI,CACf,sEAAsE,CACxE,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IACtC,OAAO,CAAS;IAChB,MAAM,CAAuB;IAEtC,YAAY,OAAe,EAAE,MAA4B;QACvD,KAAK,CAAC,4BAA4B,OAAO,GAAG,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,UAAU,CAAiC;IAEpD,YAAY,OAAe,EAAE,UAA0C;QACrE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,OAAO,CAAS;IAChB,aAAa,CAAS;IACtB,WAAW,CAAS;IACpB,KAAK,CAAQ;IAEtB,YAAY,OAAe,EAAE,aAAqB,EAAE,WAAmB,EAAE,KAAY;QACnF,KAAK,CAAC,QAAQ,OAAO,eAAe,WAAW,kBAAkB,aAAa,WAAW,CAAC,CAAC;QAC3F,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { defineJob } from './define-job.js';
|
|
2
|
+
export { type EventBridgeSchedulerConfig, EventBridgeSchedulerDriver, type ScheduleResult, } from './drivers/eventbridge-scheduler-driver.js';
|
|
3
|
+
export { type MockEnqueuedJob, MockQueueDriver, type MockQueueDriverConfig, } from './drivers/mock-driver.js';
|
|
4
|
+
export { type SQSDriverConfig, SQSQueueDriver } from './drivers/sqs-driver.js';
|
|
5
|
+
export { InvalidJobPayloadError, PayloadTooLargeError, PermanentJobError, RetryExhaustedError, TransientJobError, } from './errors.js';
|
|
6
|
+
export { createJobRegistry, JobRegistry } from './job-registry.js';
|
|
7
|
+
export { JobService, type JobServiceConfig, type JobServiceHooks, } from './job-service.js';
|
|
8
|
+
export { definePeriodicJob } from './periodic-job.js';
|
|
9
|
+
export { createSchedulerHandler, type SchedulerConfig } from './scheduler.js';
|
|
10
|
+
export type { AnyJobDefinition, Duration, EnqueueResult, JobContext, JobDefinition, JobHandler, JobMessage, QueueDriver, RetryConfig, } from './types.js';
|
|
11
|
+
export { bootstrapWorker } from './worker.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EACL,KAAK,0BAA0B,EAC/B,0BAA0B,EAC1B,KAAK,cAAc,GACpB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,KAAK,eAAe,EACpB,eAAe,EACf,KAAK,qBAAqB,GAC3B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,KAAK,eAAe,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EACL,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC9E,YAAY,EACV,gBAAgB,EAChB,QAAQ,EACR,aAAa,EACb,UAAU,EACV,aAAa,EACb,UAAU,EACV,UAAU,EACV,WAAW,EACX,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { defineJob } from './define-job.js';
|
|
2
|
+
export { EventBridgeSchedulerDriver, } from './drivers/eventbridge-scheduler-driver.js';
|
|
3
|
+
export { MockQueueDriver, } from './drivers/mock-driver.js';
|
|
4
|
+
export { SQSQueueDriver } from './drivers/sqs-driver.js';
|
|
5
|
+
export { InvalidJobPayloadError, PayloadTooLargeError, PermanentJobError, RetryExhaustedError, TransientJobError, } from './errors.js';
|
|
6
|
+
export { createJobRegistry, JobRegistry } from './job-registry.js';
|
|
7
|
+
export { JobService, } from './job-service.js';
|
|
8
|
+
export { definePeriodicJob } from './periodic-job.js';
|
|
9
|
+
export { createSchedulerHandler } from './scheduler.js';
|
|
10
|
+
export { bootstrapWorker } from './worker.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAEL,0BAA0B,GAE3B,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAEL,eAAe,GAEhB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAwB,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EACL,UAAU,GAGX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAwB,MAAM,gBAAgB,CAAC;AAY9E,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { AnyJobDefinition, JobDefinition } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Registry for job definitions.
|
|
4
|
+
*/
|
|
5
|
+
export declare class JobRegistry {
|
|
6
|
+
private readonly jobs;
|
|
7
|
+
constructor(initialJobs?: AnyJobDefinition[]);
|
|
8
|
+
/**
|
|
9
|
+
* Register a job definition. Throws if a job with the same name already exists.
|
|
10
|
+
*/
|
|
11
|
+
register<TPayload>(job: JobDefinition<TPayload>): this;
|
|
12
|
+
/**
|
|
13
|
+
* Get a job by name.
|
|
14
|
+
*/
|
|
15
|
+
get<TPayload = unknown>(name: string): JobDefinition<TPayload> | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Get a job by name or throw if not found.
|
|
18
|
+
*/
|
|
19
|
+
getOrThrow<TPayload = unknown>(name: string): JobDefinition<TPayload>;
|
|
20
|
+
/**
|
|
21
|
+
* List all registered jobs.
|
|
22
|
+
*/
|
|
23
|
+
list(): AnyJobDefinition[];
|
|
24
|
+
/**
|
|
25
|
+
* Number of registered jobs.
|
|
26
|
+
*/
|
|
27
|
+
get size(): number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Convenience helper to build a registry from an array.
|
|
31
|
+
*/
|
|
32
|
+
export declare function createJobRegistry(jobs?: AnyJobDefinition[]): JobRegistry;
|
|
33
|
+
//# sourceMappingURL=job-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"job-registry.d.ts","sourceRoot":"","sources":["../../src/jobs/job-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAElE;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAuC;gBAEhD,WAAW,GAAE,gBAAgB,EAAO;IAMhD;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE,aAAa,CAAC,QAAQ,CAAC,GAAG,IAAI;IAQtD;;OAEG;IACH,GAAG,CAAC,QAAQ,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,GAAG,SAAS;IAI1E;;OAEG;IACH,UAAU,CAAC,QAAQ,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC;IAQrE;;OAEG;IACH,IAAI,IAAI,gBAAgB,EAAE;IAI1B;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,gBAAgB,EAAO,GAAG,WAAW,CAE5E"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry for job definitions.
|
|
3
|
+
*/
|
|
4
|
+
export class JobRegistry {
|
|
5
|
+
jobs = new Map();
|
|
6
|
+
constructor(initialJobs = []) {
|
|
7
|
+
for (const job of initialJobs) {
|
|
8
|
+
this.register(job);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Register a job definition. Throws if a job with the same name already exists.
|
|
13
|
+
*/
|
|
14
|
+
register(job) {
|
|
15
|
+
if (this.jobs.has(job.name)) {
|
|
16
|
+
throw new Error(`Job "${job.name}" is already registered`);
|
|
17
|
+
}
|
|
18
|
+
this.jobs.set(job.name, job);
|
|
19
|
+
return this;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get a job by name.
|
|
23
|
+
*/
|
|
24
|
+
get(name) {
|
|
25
|
+
return this.jobs.get(name);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get a job by name or throw if not found.
|
|
29
|
+
*/
|
|
30
|
+
getOrThrow(name) {
|
|
31
|
+
const job = this.get(name);
|
|
32
|
+
if (!job) {
|
|
33
|
+
throw new Error(`Job "${name}" not found in registry`);
|
|
34
|
+
}
|
|
35
|
+
return job;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* List all registered jobs.
|
|
39
|
+
*/
|
|
40
|
+
list() {
|
|
41
|
+
return [...this.jobs.values()];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Number of registered jobs.
|
|
45
|
+
*/
|
|
46
|
+
get size() {
|
|
47
|
+
return this.jobs.size;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Convenience helper to build a registry from an array.
|
|
52
|
+
*/
|
|
53
|
+
export function createJobRegistry(jobs = []) {
|
|
54
|
+
return new JobRegistry(jobs);
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=job-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"job-registry.js","sourceRoot":"","sources":["../../src/jobs/job-registry.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,OAAO,WAAW;IACL,IAAI,GAAG,IAAI,GAAG,EAA4B,CAAC;IAE5D,YAAY,cAAkC,EAAE;QAC9C,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;YAC9B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ,CAAW,GAA4B;QAC7C,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,IAAI,yBAAyB,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAuB,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,GAAG,CAAqB,IAAY;QAClC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAwC,CAAC;IACpE,CAAC;IAED;;OAEG;IACH,UAAU,CAAqB,IAAY;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAW,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,yBAAyB,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;OAEG;IACH,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA2B,EAAE;IAC7D,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Duration, EnqueueResult, JobDefinition, QueueDriver } from './types.js';
|
|
2
|
+
export interface JobServiceConfig {
|
|
3
|
+
/** Default queue name when a job does not specify one */
|
|
4
|
+
defaultQueue?: string;
|
|
5
|
+
/** Override the payload size limit (defaults to 256KB) */
|
|
6
|
+
maxPayloadBytes?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface JobServiceHooks {
|
|
9
|
+
/** Called after a job is successfully enqueued */
|
|
10
|
+
onEnqueued?: <TPayload>(job: JobDefinition<TPayload>, payload: TPayload, result: EnqueueResult) => Promise<void> | void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Service responsible for enqueuing jobs.
|
|
14
|
+
*/
|
|
15
|
+
export declare class JobService {
|
|
16
|
+
private readonly driver;
|
|
17
|
+
private readonly hooks?;
|
|
18
|
+
private readonly defaultQueue;
|
|
19
|
+
private readonly maxPayloadBytes;
|
|
20
|
+
constructor(driver: QueueDriver, config?: JobServiceConfig, hooks?: JobServiceHooks | undefined);
|
|
21
|
+
/**
|
|
22
|
+
* Enqueue a job for immediate processing.
|
|
23
|
+
*/
|
|
24
|
+
enqueue<TPayload>(job: JobDefinition<TPayload>, payload: TPayload): Promise<EnqueueResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Enqueue a job to run after a delay.
|
|
27
|
+
*/
|
|
28
|
+
enqueueIn<TPayload>(job: JobDefinition<TPayload>, payload: TPayload, delay: Duration): Promise<EnqueueResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Enqueue a job to run at a specific time.
|
|
31
|
+
*/
|
|
32
|
+
enqueueAt<TPayload>(job: JobDefinition<TPayload>, payload: TPayload, at: Date): Promise<EnqueueResult>;
|
|
33
|
+
/**
|
|
34
|
+
* Enqueue multiple jobs sequentially.
|
|
35
|
+
*/
|
|
36
|
+
enqueueBatch<TPayload>(jobs: Array<{
|
|
37
|
+
job: JobDefinition<TPayload>;
|
|
38
|
+
payload: TPayload;
|
|
39
|
+
}>): Promise<EnqueueResult[]>;
|
|
40
|
+
private validatePayload;
|
|
41
|
+
private validatePayloadSize;
|
|
42
|
+
private getJobId;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=job-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"job-service.d.ts","sourceRoot":"","sources":["../../src/jobs/job-service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAKtF,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,UAAU,CAAC,EAAE,CAAC,QAAQ,EACpB,GAAG,EAAE,aAAa,CAAC,QAAQ,CAAC,EAC5B,OAAO,EAAE,QAAQ,EACjB,MAAM,EAAE,aAAa,KAClB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC3B;AAED;;GAEG;AACH,qBAAa,UAAU;IAKnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;IANzB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAGtB,MAAM,EAAE,WAAW,EACpC,MAAM,GAAE,gBAAqB,EACZ,KAAK,CAAC,EAAE,eAAe,YAAA;IAM1C;;OAEG;IACG,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC;IAiBhG;;OAEG;IACG,SAAS,CAAC,QAAQ,EACtB,GAAG,EAAE,aAAa,CAAC,QAAQ,CAAC,EAC5B,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,QAAQ,GACd,OAAO,CAAC,aAAa,CAAC;IA0BzB;;OAEG;IACG,SAAS,CAAC,QAAQ,EACtB,GAAG,EAAE,aAAa,CAAC,QAAQ,CAAC,EAC5B,OAAO,EAAE,QAAQ,EACjB,EAAE,EAAE,IAAI,GACP,OAAO,CAAC,aAAa,CAAC;IA0BzB;;OAEG;IACG,YAAY,CAAC,QAAQ,EACzB,IAAI,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;QAAC,OAAO,EAAE,QAAQ,CAAA;KAAE,CAAC,GAC/D,OAAO,CAAC,aAAa,EAAE,CAAC;IAI3B,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,QAAQ;CAMjB"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { safeParse } from 'valibot';
|
|
2
|
+
import { InvalidJobPayloadError, PayloadTooLargeError } from './errors.js';
|
|
3
|
+
import { calculatePayloadSizeBytes, durationToSeconds } from './utils.js';
|
|
4
|
+
const DEFAULT_MAX_PAYLOAD_BYTES = 256 * 1024; // 256KB
|
|
5
|
+
/**
|
|
6
|
+
* Service responsible for enqueuing jobs.
|
|
7
|
+
*/
|
|
8
|
+
export class JobService {
|
|
9
|
+
driver;
|
|
10
|
+
hooks;
|
|
11
|
+
defaultQueue;
|
|
12
|
+
maxPayloadBytes;
|
|
13
|
+
constructor(driver, config = {}, hooks) {
|
|
14
|
+
this.driver = driver;
|
|
15
|
+
this.hooks = hooks;
|
|
16
|
+
this.defaultQueue = config.defaultQueue ?? driver.defaultQueue ?? 'default';
|
|
17
|
+
this.maxPayloadBytes = config.maxPayloadBytes ?? DEFAULT_MAX_PAYLOAD_BYTES;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Enqueue a job for immediate processing.
|
|
21
|
+
*/
|
|
22
|
+
async enqueue(job, payload) {
|
|
23
|
+
this.validatePayload(job, payload);
|
|
24
|
+
this.validatePayloadSize(payload);
|
|
25
|
+
const queue = job.queue ?? this.defaultQueue;
|
|
26
|
+
const jobId = this.getJobId(job, payload);
|
|
27
|
+
const result = await this.driver.enqueue({
|
|
28
|
+
jobName: job.name,
|
|
29
|
+
payload,
|
|
30
|
+
queue,
|
|
31
|
+
jobId,
|
|
32
|
+
});
|
|
33
|
+
await this.hooks?.onEnqueued?.(job, payload, result);
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Enqueue a job to run after a delay.
|
|
38
|
+
*/
|
|
39
|
+
async enqueueIn(job, payload, delay) {
|
|
40
|
+
this.validatePayload(job, payload);
|
|
41
|
+
this.validatePayloadSize(payload);
|
|
42
|
+
if (!this.driver.enqueueIn) {
|
|
43
|
+
const seconds = durationToSeconds(delay);
|
|
44
|
+
return this.enqueueAt(job, payload, new Date(Date.now() + seconds * 1000));
|
|
45
|
+
}
|
|
46
|
+
const queue = job.queue ?? this.defaultQueue;
|
|
47
|
+
const jobId = this.getJobId(job, payload);
|
|
48
|
+
const result = await this.driver.enqueueIn({
|
|
49
|
+
jobName: job.name,
|
|
50
|
+
payload,
|
|
51
|
+
queue,
|
|
52
|
+
jobId,
|
|
53
|
+
}, delay);
|
|
54
|
+
await this.hooks?.onEnqueued?.(job, payload, result);
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Enqueue a job to run at a specific time.
|
|
59
|
+
*/
|
|
60
|
+
async enqueueAt(job, payload, at) {
|
|
61
|
+
this.validatePayload(job, payload);
|
|
62
|
+
this.validatePayloadSize(payload);
|
|
63
|
+
if (!this.driver.enqueueAt) {
|
|
64
|
+
const delaySeconds = Math.max(0, Math.floor((at.getTime() - Date.now()) / 1000));
|
|
65
|
+
return this.enqueueIn(job, payload, delaySeconds);
|
|
66
|
+
}
|
|
67
|
+
const queue = job.queue ?? this.defaultQueue;
|
|
68
|
+
const jobId = this.getJobId(job, payload);
|
|
69
|
+
const result = await this.driver.enqueueAt({
|
|
70
|
+
jobName: job.name,
|
|
71
|
+
payload,
|
|
72
|
+
queue,
|
|
73
|
+
jobId,
|
|
74
|
+
}, at);
|
|
75
|
+
await this.hooks?.onEnqueued?.(job, payload, result);
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Enqueue multiple jobs sequentially.
|
|
80
|
+
*/
|
|
81
|
+
async enqueueBatch(jobs) {
|
|
82
|
+
return Promise.all(jobs.map(({ job, payload }) => this.enqueue(job, payload)));
|
|
83
|
+
}
|
|
84
|
+
validatePayload(job, payload) {
|
|
85
|
+
if (job.schema) {
|
|
86
|
+
const result = safeParse(job.schema, payload);
|
|
87
|
+
if (!result.success) {
|
|
88
|
+
throw new InvalidJobPayloadError(job.name, result.issues);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
validatePayloadSize(payload) {
|
|
93
|
+
const sizeBytes = calculatePayloadSizeBytes(payload);
|
|
94
|
+
if (sizeBytes > this.maxPayloadBytes) {
|
|
95
|
+
throw new PayloadTooLargeError(sizeBytes, this.maxPayloadBytes);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
getJobId(job, payload) {
|
|
99
|
+
if (job.unique) {
|
|
100
|
+
return job.unique.key(payload);
|
|
101
|
+
}
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=job-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"job-service.js","sourceRoot":"","sources":["../../src/jobs/job-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { JobDefinition } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Define a periodic job (typically triggered by EventBridge).
|
|
4
|
+
*/
|
|
5
|
+
export declare function definePeriodicJob(config: Pick<JobDefinition<undefined>, 'name' | 'queue' | 'handler'>): JobDefinition<undefined>;
|
|
6
|
+
//# sourceMappingURL=periodic-job.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"periodic-job.d.ts","sourceRoot":"","sources":["../../src/jobs/periodic-job.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,GACnE,aAAa,CAAC,SAAS,CAAC,CAM1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"periodic-job.js","sourceRoot":"","sources":["../../src/jobs/periodic-job.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAoE;IAEpE,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-constants.d.ts","sourceRoot":"","sources":["../../src/jobs/schedule-constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,qBAAqB,QAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-constants.js","sourceRoot":"","sources":["../../src/jobs/schedule-constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Logger } from '../utils/logger.js';
|
|
2
|
+
import type { QueueDriver } from './types.js';
|
|
3
|
+
export interface SchedulerConfig {
|
|
4
|
+
tableName: string;
|
|
5
|
+
driver: QueueDriver;
|
|
6
|
+
region: string;
|
|
7
|
+
endpoint?: string;
|
|
8
|
+
logger?: Logger;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Create a scheduler handler that reads due jobs from DynamoDB and enqueues them.
|
|
12
|
+
* Intended to be triggered periodically (e.g., every minute via EventBridge).
|
|
13
|
+
*/
|
|
14
|
+
export declare function createSchedulerHandler(config: SchedulerConfig): () => Promise<{
|
|
15
|
+
dispatched: number;
|
|
16
|
+
}>;
|
|
17
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/jobs/scheduler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAiDD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,eAAe;;GA4D7D"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
|
|
2
|
+
import { DeleteCommand, DynamoDBDocumentClient, QueryCommand } from '@aws-sdk/lib-dynamodb';
|
|
3
|
+
import { createLogger } from '../utils/logger.js';
|
|
4
|
+
/**
|
|
5
|
+
* Parse a scheduled item from DynamoDB into a job dispatch payload.
|
|
6
|
+
* Returns null if the item is invalid or malformed.
|
|
7
|
+
*/
|
|
8
|
+
function parseScheduledItem(item, logger) {
|
|
9
|
+
const jobName = item.jobName;
|
|
10
|
+
const jobId = item.sk;
|
|
11
|
+
if (!jobName || !jobId) {
|
|
12
|
+
logger.warn('Skipping scheduled item with missing required fields', {
|
|
13
|
+
hasJobName: !!jobName,
|
|
14
|
+
hasJobId: !!jobId,
|
|
15
|
+
});
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
let payload;
|
|
19
|
+
try {
|
|
20
|
+
payload = item.payload ? JSON.parse(item.payload) : undefined;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
logger.error('Failed to parse scheduled job payload', { jobName, jobId, error });
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
jobName,
|
|
28
|
+
jobId,
|
|
29
|
+
payload,
|
|
30
|
+
queue: item.queue ?? 'default',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create a scheduler handler that reads due jobs from DynamoDB and enqueues them.
|
|
35
|
+
* Intended to be triggered periodically (e.g., every minute via EventBridge).
|
|
36
|
+
*/
|
|
37
|
+
export function createSchedulerHandler(config) {
|
|
38
|
+
const logger = config.logger ?? createLogger('JobScheduler');
|
|
39
|
+
const ddbClient = new DynamoDBClient({
|
|
40
|
+
region: config.region,
|
|
41
|
+
...(config.endpoint && { endpoint: config.endpoint }),
|
|
42
|
+
});
|
|
43
|
+
const docClient = DynamoDBDocumentClient.from(ddbClient);
|
|
44
|
+
return async () => {
|
|
45
|
+
const partition = `SCHEDULED#${new Date().toISOString().slice(0, 16)}`;
|
|
46
|
+
const result = await docClient.send(new QueryCommand({
|
|
47
|
+
TableName: config.tableName,
|
|
48
|
+
KeyConditionExpression: 'pk = :pk',
|
|
49
|
+
ExpressionAttributeValues: { ':pk': partition },
|
|
50
|
+
}));
|
|
51
|
+
if (!result.Items || result.Items.length === 0) {
|
|
52
|
+
return { dispatched: 0 };
|
|
53
|
+
}
|
|
54
|
+
let dispatched = 0;
|
|
55
|
+
for (const item of result.Items) {
|
|
56
|
+
const parsed = parseScheduledItem(item, logger);
|
|
57
|
+
if (!parsed) {
|
|
58
|
+
// Delete malformed items to prevent infinite retries
|
|
59
|
+
if (item.sk) {
|
|
60
|
+
await docClient.send(new DeleteCommand({
|
|
61
|
+
TableName: config.tableName,
|
|
62
|
+
Key: { pk: partition, sk: item.sk },
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
await config.driver.enqueue({
|
|
68
|
+
jobName: parsed.jobName,
|
|
69
|
+
payload: parsed.payload,
|
|
70
|
+
queue: parsed.queue,
|
|
71
|
+
jobId: parsed.jobId,
|
|
72
|
+
});
|
|
73
|
+
await docClient.send(new DeleteCommand({
|
|
74
|
+
TableName: config.tableName,
|
|
75
|
+
Key: { pk: partition, sk: parsed.jobId },
|
|
76
|
+
}));
|
|
77
|
+
dispatched += 1;
|
|
78
|
+
}
|
|
79
|
+
logger.info('Dispatched scheduled jobs', { dispatched });
|
|
80
|
+
return { dispatched };
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/jobs/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE5F,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA0BlD;;;GAGG;AACH,SAAS,kBAAkB,CAAC,IAAmB,EAAE,MAAc;IAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC;IAEtB,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,sDAAsD,EAAE;YAClE,UAAU,EAAE,CAAC,CAAC,OAAO;YACrB,QAAQ,EAAE,CAAC,CAAC,KAAK;SAClB,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAChE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,uCAAuC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACjF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,OAAO;QACP,KAAK;QACL,OAAO;QACP,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,SAAS;KAC/B,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAuB;IAC5D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,YAAY,CAAC,cAAc,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,IAAI,cAAc,CAAC;QACnC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;KACtD,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,sBAAsB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEzD,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,SAAS,GAAG,aAAa,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QAEvE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,CACjC,IAAI,YAAY,CAAC;YACf,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,sBAAsB,EAAE,UAAU;YAClC,yBAAyB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE;SAChD,CAAC,CACH,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/C,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;QAC3B,CAAC;QAED,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAqB,EAAE,MAAM,CAAC,CAAC;YAEjE,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,qDAAqD;gBACrD,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;oBACZ,MAAM,SAAS,CAAC,IAAI,CAClB,IAAI,aAAa,CAAC;wBAChB,SAAS,EAAE,MAAM,CAAC,SAAS;wBAC3B,GAAG,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE;qBACpC,CAAC,CACH,CAAC;gBACJ,CAAC;gBACD,SAAS;YACX,CAAC;YAED,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;gBAC1B,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,KAAK,EAAE,MAAM,CAAC,KAAK;aACpB,CAAC,CAAC;YAEH,MAAM,SAAS,CAAC,IAAI,CAClB,IAAI,aAAa,CAAC;gBAChB,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,GAAG,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,EAAE;aACzC,CAAC,CACH,CAAC;YAEF,UAAU,IAAI,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QACzD,OAAO,EAAE,UAAU,EAAE,CAAC;IACxB,CAAC,CAAC;AACJ,CAAC"}
|