@sidequest/engine 1.0.0-next.10

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 (81) hide show
  1. package/dist/engine.cjs +189 -0
  2. package/dist/engine.cjs.map +1 -0
  3. package/dist/engine.d.ts +122 -0
  4. package/dist/engine.js +187 -0
  5. package/dist/engine.js.map +1 -0
  6. package/dist/execution/dispatcher.cjs +90 -0
  7. package/dist/execution/dispatcher.cjs.map +1 -0
  8. package/dist/execution/dispatcher.d.ts +44 -0
  9. package/dist/execution/dispatcher.js +88 -0
  10. package/dist/execution/dispatcher.js.map +1 -0
  11. package/dist/execution/executor-manager.cjs +151 -0
  12. package/dist/execution/executor-manager.cjs.map +1 -0
  13. package/dist/execution/executor-manager.d.ts +51 -0
  14. package/dist/execution/executor-manager.js +149 -0
  15. package/dist/execution/executor-manager.js.map +1 -0
  16. package/dist/execution/queue-manager.cjs +43 -0
  17. package/dist/execution/queue-manager.cjs.map +1 -0
  18. package/dist/execution/queue-manager.d.ts +23 -0
  19. package/dist/execution/queue-manager.js +41 -0
  20. package/dist/execution/queue-manager.js.map +1 -0
  21. package/dist/index.cjs +38 -0
  22. package/dist/index.cjs.map +1 -0
  23. package/dist/index.d.ts +16 -0
  24. package/dist/index.js +17 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/job/constants.cjs +30 -0
  27. package/dist/job/constants.cjs.map +1 -0
  28. package/dist/job/constants.d.ts +20 -0
  29. package/dist/job/constants.js +28 -0
  30. package/dist/job/constants.js.map +1 -0
  31. package/dist/job/job-builder.cjs +153 -0
  32. package/dist/job/job-builder.cjs.map +1 -0
  33. package/dist/job/job-builder.d.ts +115 -0
  34. package/dist/job/job-builder.js +151 -0
  35. package/dist/job/job-builder.js.map +1 -0
  36. package/dist/job/job-transitioner.cjs +36 -0
  37. package/dist/job/job-transitioner.cjs.map +1 -0
  38. package/dist/job/job-transitioner.d.ts +21 -0
  39. package/dist/job/job-transitioner.js +34 -0
  40. package/dist/job/job-transitioner.js.map +1 -0
  41. package/dist/job/job.cjs +250 -0
  42. package/dist/job/job.cjs.map +1 -0
  43. package/dist/job/job.d.ts +178 -0
  44. package/dist/job/job.js +248 -0
  45. package/dist/job/job.js.map +1 -0
  46. package/dist/queue/grant-queue-config.cjs +49 -0
  47. package/dist/queue/grant-queue-config.cjs.map +1 -0
  48. package/dist/queue/grant-queue-config.d.ts +32 -0
  49. package/dist/queue/grant-queue-config.js +46 -0
  50. package/dist/queue/grant-queue-config.js.map +1 -0
  51. package/dist/routines/cleanup-finished-job.cjs +17 -0
  52. package/dist/routines/cleanup-finished-job.cjs.map +1 -0
  53. package/dist/routines/cleanup-finished-job.d.ts +10 -0
  54. package/dist/routines/cleanup-finished-job.js +15 -0
  55. package/dist/routines/cleanup-finished-job.js.map +1 -0
  56. package/dist/routines/release-stale-jobs.cjs +28 -0
  57. package/dist/routines/release-stale-jobs.cjs.map +1 -0
  58. package/dist/routines/release-stale-jobs.d.ts +12 -0
  59. package/dist/routines/release-stale-jobs.js +26 -0
  60. package/dist/routines/release-stale-jobs.js.map +1 -0
  61. package/dist/shared-runner/runner-pool.cjs +46 -0
  62. package/dist/shared-runner/runner-pool.cjs.map +1 -0
  63. package/dist/shared-runner/runner-pool.d.ts +28 -0
  64. package/dist/shared-runner/runner-pool.js +44 -0
  65. package/dist/shared-runner/runner-pool.js.map +1 -0
  66. package/dist/shared-runner/runner.cjs +39 -0
  67. package/dist/shared-runner/runner.cjs.map +1 -0
  68. package/dist/shared-runner/runner.d.ts +10 -0
  69. package/dist/shared-runner/runner.js +35 -0
  70. package/dist/shared-runner/runner.js.map +1 -0
  71. package/dist/utils/shutdown.cjs +53 -0
  72. package/dist/utils/shutdown.cjs.map +1 -0
  73. package/dist/utils/shutdown.d.ts +9 -0
  74. package/dist/utils/shutdown.js +50 -0
  75. package/dist/utils/shutdown.js.map +1 -0
  76. package/dist/workers/main.cjs +153 -0
  77. package/dist/workers/main.cjs.map +1 -0
  78. package/dist/workers/main.d.ts +39 -0
  79. package/dist/workers/main.js +151 -0
  80. package/dist/workers/main.js.map +1 -0
  81. package/package.json +30 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;"}
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ var backend = require('@sidequest/backend');
4
+
5
+ /**
6
+ * Default configuration values for job builders.
7
+ *
8
+ * Provides fallback settings when specific job configuration options are not explicitly set.
9
+ *
10
+ * @remarks
11
+ * - Uses "default" queue for job processing
12
+ * - No timeout limit by default
13
+ * - Uniqueness checking disabled
14
+ * - Maximum of 5 retry attempts on failure
15
+ * - Jobs are immediately available for processing
16
+ * - No constructor arguments passed by default
17
+ */
18
+ const JOB_BUILDER_FALLBACK = {
19
+ queue: "default",
20
+ timeout: undefined,
21
+ uniqueness: false,
22
+ maxAttempts: backend.JOB_FALLBACK.max_attempts,
23
+ get availableAt() {
24
+ return new Date();
25
+ },
26
+ constructorArgs: [],
27
+ };
28
+
29
+ exports.JOB_BUILDER_FALLBACK = JOB_BUILDER_FALLBACK;
30
+ //# sourceMappingURL=constants.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.cjs","sources":["../../src/job/constants.ts"],"sourcesContent":[null],"names":["JOB_FALLBACK"],"mappings":";;;;AAGA;;;;;;;;;;;;AAYG;AACI,MAAM,oBAAoB,GAAwD;AACvF,IAAA,KAAK,EAAE,SAAS;AAChB,IAAA,OAAO,EAAE,SAAS;AAClB,IAAA,UAAU,EAAE,KAAK;IACjB,WAAW,EAAEA,oBAAY,CAAC,YAAY;AACtC,IAAA,IAAI,WAAW,GAAA;QACb,OAAO,IAAI,IAAI,EAAE;IACnB,CAAC;AACD,IAAA,eAAe,EAAE,EAAE;;;;;"}
@@ -0,0 +1,20 @@
1
+ import { JobBuilderDefaults } from './job-builder.js';
2
+
3
+ /**
4
+ * Default configuration values for job builders.
5
+ *
6
+ * Provides fallback settings when specific job configuration options are not explicitly set.
7
+ *
8
+ * @remarks
9
+ * - Uses "default" queue for job processing
10
+ * - No timeout limit by default
11
+ * - Uniqueness checking disabled
12
+ * - Maximum of 5 retry attempts on failure
13
+ * - Jobs are immediately available for processing
14
+ * - No constructor arguments passed by default
15
+ */
16
+ declare const JOB_BUILDER_FALLBACK: JobBuilderDefaults & {
17
+ constructorArgs: unknown[];
18
+ };
19
+
20
+ export { JOB_BUILDER_FALLBACK };
@@ -0,0 +1,28 @@
1
+ import { JOB_FALLBACK } from '@sidequest/backend';
2
+
3
+ /**
4
+ * Default configuration values for job builders.
5
+ *
6
+ * Provides fallback settings when specific job configuration options are not explicitly set.
7
+ *
8
+ * @remarks
9
+ * - Uses "default" queue for job processing
10
+ * - No timeout limit by default
11
+ * - Uniqueness checking disabled
12
+ * - Maximum of 5 retry attempts on failure
13
+ * - Jobs are immediately available for processing
14
+ * - No constructor arguments passed by default
15
+ */
16
+ const JOB_BUILDER_FALLBACK = {
17
+ queue: "default",
18
+ timeout: undefined,
19
+ uniqueness: false,
20
+ maxAttempts: JOB_FALLBACK.max_attempts,
21
+ get availableAt() {
22
+ return new Date();
23
+ },
24
+ constructorArgs: [],
25
+ };
26
+
27
+ export { JOB_BUILDER_FALLBACK };
28
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sources":["../../src/job/constants.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAGA;;;;;;;;;;;;AAYG;AACI,MAAM,oBAAoB,GAAwD;AACvF,IAAA,KAAK,EAAE,SAAS;AAChB,IAAA,OAAO,EAAE,SAAS;AAClB,IAAA,UAAU,EAAE,KAAK;IACjB,WAAW,EAAE,YAAY,CAAC,YAAY;AACtC,IAAA,IAAI,WAAW,GAAA;QACb,OAAO,IAAI,IAAI,EAAE;IACnB,CAAC;AACD,IAAA,eAAe,EAAE,EAAE;;;;;"}
@@ -0,0 +1,153 @@
1
+ 'use strict';
2
+
3
+ var core = require('@sidequest/core');
4
+ var constants = require('./constants.cjs');
5
+
6
+ /**
7
+ * Builder for creating and enqueuing jobs with custom configuration.
8
+ * @template T The job class type.
9
+ */
10
+ class JobBuilder {
11
+ backend;
12
+ JobClass;
13
+ defaults;
14
+ constructorArgs;
15
+ queueName;
16
+ jobTimeout;
17
+ uniquenessConfig;
18
+ jobMaxAttempts;
19
+ jobAvailableAt;
20
+ /**
21
+ * Creates a new JobBuilder for the given job class.
22
+ * @param JobClass The job class constructor.
23
+ */
24
+ constructor(backend, JobClass, defaults) {
25
+ this.backend = backend;
26
+ this.JobClass = JobClass;
27
+ this.defaults = defaults;
28
+ this.queue(this.defaults?.queue ?? constants.JOB_BUILDER_FALLBACK.queue);
29
+ this.maxAttempts(this.defaults?.maxAttempts ?? constants.JOB_BUILDER_FALLBACK.maxAttempts);
30
+ this.availableAt(this.defaults?.availableAt ?? constants.JOB_BUILDER_FALLBACK.availableAt);
31
+ this.timeout(this.defaults?.timeout ?? constants.JOB_BUILDER_FALLBACK.timeout);
32
+ this.unique(this.defaults?.uniqueness ?? constants.JOB_BUILDER_FALLBACK.uniqueness);
33
+ this.with(...constants.JOB_BUILDER_FALLBACK.constructorArgs);
34
+ }
35
+ /**
36
+ * Sets the constructor arguments for the job.
37
+ * @param args The constructor arguments.
38
+ * @returns This builder instance.
39
+ */
40
+ with(...args) {
41
+ this.constructorArgs = args;
42
+ return this;
43
+ }
44
+ /**
45
+ * Sets the queue name for the job.
46
+ * @param queue The queue name.
47
+ * @returns This builder instance.
48
+ */
49
+ queue(queue) {
50
+ this.queueName = queue;
51
+ return this;
52
+ }
53
+ /**
54
+ * Sets the timeout for the job in milliseconds.
55
+ * @param ms Timeout in milliseconds.
56
+ * @returns This builder instance.
57
+ */
58
+ timeout(ms) {
59
+ this.jobTimeout = ms;
60
+ return this;
61
+ }
62
+ /**
63
+ * Sets the uniqueness configuration for the job.
64
+ * @param value Boolean or uniqueness config object. If true, uses an alive job uniqueness strategy (see {@link AliveJobUniqueness}).
65
+ * If false, disables uniqueness. If an object, uses the custom uniqueness strategy.
66
+ * @param value.withArgs If true, uniqueness is based on job class and job arguments.
67
+ * If false, uniqueness is based only on the job class.
68
+ * @param value.period If a period is provided, uses a fixed window uniqueness strategy (see {@link FixedWindowUniqueness}).
69
+ * @returns This builder instance.
70
+ * @see {@link UniquenessInput} for more details.
71
+ */
72
+ unique(value) {
73
+ if (typeof value === "boolean") {
74
+ if (value) {
75
+ const config = {
76
+ type: "alive-job",
77
+ withArgs: false,
78
+ };
79
+ this.uniquenessConfig = config;
80
+ }
81
+ else {
82
+ this.uniquenessConfig = undefined; // no uniqueness
83
+ }
84
+ }
85
+ else {
86
+ if (value.period) {
87
+ this.uniquenessConfig = {
88
+ type: "fixed-window",
89
+ period: value.period,
90
+ withArgs: value.withArgs,
91
+ };
92
+ }
93
+ else {
94
+ this.uniquenessConfig = { type: "alive-job", withArgs: value.withArgs };
95
+ }
96
+ }
97
+ return this;
98
+ }
99
+ /**
100
+ * Sets the maximum number of attempts for the job.
101
+ * @param value The max attempts.
102
+ * @returns This builder instance.
103
+ */
104
+ maxAttempts(value) {
105
+ this.jobMaxAttempts = value;
106
+ return this;
107
+ }
108
+ /**
109
+ * Sets the time when the job becomes available.
110
+ * @param value The available date.
111
+ * @returns This builder instance.
112
+ */
113
+ availableAt(value) {
114
+ this.jobAvailableAt = value;
115
+ return this;
116
+ }
117
+ /**
118
+ * Enqueues the job with the specified arguments.
119
+ * @param args Arguments to pass to the job's run method.
120
+ * @returns A promise resolving to the created job data.
121
+ */
122
+ async enqueue(...args) {
123
+ const job = new this.JobClass(...this.constructorArgs);
124
+ await job.ready();
125
+ if (!job.script) {
126
+ throw new Error(`Error on starting job ${job.className} could not detect source file.`);
127
+ }
128
+ const jobData = {
129
+ queue: this.queueName,
130
+ script: job.script,
131
+ class: job.className,
132
+ state: "waiting",
133
+ args,
134
+ constructor_args: this.constructorArgs,
135
+ attempt: 0,
136
+ max_attempts: this.jobMaxAttempts,
137
+ available_at: this.jobAvailableAt,
138
+ timeout: this.jobTimeout,
139
+ uniqueness_config: this.uniquenessConfig,
140
+ };
141
+ core.logger("JobBuilder").debug(`Enqueuing job ${job.className} with args: ${JSON.stringify(args)}
142
+ and constructor args: ${JSON.stringify(this.constructorArgs)}`);
143
+ if (this.uniquenessConfig) {
144
+ const uniqueness = core.UniquenessFactory.create(this.uniquenessConfig);
145
+ jobData.unique_digest = uniqueness.digest(jobData);
146
+ core.logger("JobBuilder").debug(`Job ${job.className} uniqueness digest: ${jobData.unique_digest}`);
147
+ }
148
+ return this.backend.createNewJob(jobData);
149
+ }
150
+ }
151
+
152
+ exports.JobBuilder = JobBuilder;
153
+ //# sourceMappingURL=job-builder.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-builder.cjs","sources":["../../src/job/job-builder.ts"],"sourcesContent":[null],"names":["JOB_BUILDER_FALLBACK","logger","UniquenessFactory"],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ import { Backend } from '@sidequest/backend';
2
+ import { TimePeriod, JobData } from '@sidequest/core';
3
+ import { JobClassType } from './job.js';
4
+
5
+ /**
6
+ * Configuration for job uniqueness constraints.
7
+ *
8
+ * @remarks
9
+ * Controls how jobs are deduplicated to prevent multiple instances of the same job from running.
10
+ *
11
+ * - When `true`: Jobs are made unique based on their type/name only
12
+ * - When `false`: No uniqueness constraint is applied
13
+ * - When an object: Provides fine-grained control over uniqueness behavior
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // Simple uniqueness
18
+ * const unique: UniquenessInput = true;
19
+ *
20
+ * // No uniqueness
21
+ * const notUnique: UniquenessInput = false;
22
+ *
23
+ * // Advanced uniqueness with arguments consideration
24
+ * const advancedUnique: UniquenessInput = {
25
+ * withArgs: true,
26
+ * period: { hours: 1 }
27
+ * };
28
+ * ```
29
+ */
30
+ type UniquenessInput = boolean | {
31
+ withArgs?: boolean;
32
+ period?: TimePeriod;
33
+ };
34
+ interface JobBuilderDefaults {
35
+ /** Default queue name for jobs built with the JobBuilder */
36
+ queue?: string;
37
+ /** Default timeout in milliseconds for jobs built with the JobBuilder */
38
+ timeout?: number;
39
+ /** Default uniqueness configuration for jobs built with the JobBuilder */
40
+ uniqueness?: UniquenessInput;
41
+ /** Default maximum attempts for jobs built with the JobBuilder */
42
+ maxAttempts?: number;
43
+ /** Default available at date for jobs built with the JobBuilder */
44
+ availableAt?: Date;
45
+ }
46
+ /**
47
+ * Builder for creating and enqueuing jobs with custom configuration.
48
+ * @template T The job class type.
49
+ */
50
+ declare class JobBuilder<T extends JobClassType> {
51
+ private backend;
52
+ private JobClass;
53
+ private defaults?;
54
+ private constructorArgs?;
55
+ private queueName?;
56
+ private jobTimeout?;
57
+ private uniquenessConfig?;
58
+ private jobMaxAttempts?;
59
+ private jobAvailableAt?;
60
+ /**
61
+ * Creates a new JobBuilder for the given job class.
62
+ * @param JobClass The job class constructor.
63
+ */
64
+ constructor(backend: Backend, JobClass: T, defaults?: JobBuilderDefaults | undefined);
65
+ /**
66
+ * Sets the constructor arguments for the job.
67
+ * @param args The constructor arguments.
68
+ * @returns This builder instance.
69
+ */
70
+ with(...args: ConstructorParameters<T>): this;
71
+ /**
72
+ * Sets the queue name for the job.
73
+ * @param queue The queue name.
74
+ * @returns This builder instance.
75
+ */
76
+ queue(queue: string): this;
77
+ /**
78
+ * Sets the timeout for the job in milliseconds.
79
+ * @param ms Timeout in milliseconds.
80
+ * @returns This builder instance.
81
+ */
82
+ timeout(ms: number): this;
83
+ /**
84
+ * Sets the uniqueness configuration for the job.
85
+ * @param value Boolean or uniqueness config object. If true, uses an alive job uniqueness strategy (see {@link AliveJobUniqueness}).
86
+ * If false, disables uniqueness. If an object, uses the custom uniqueness strategy.
87
+ * @param value.withArgs If true, uniqueness is based on job class and job arguments.
88
+ * If false, uniqueness is based only on the job class.
89
+ * @param value.period If a period is provided, uses a fixed window uniqueness strategy (see {@link FixedWindowUniqueness}).
90
+ * @returns This builder instance.
91
+ * @see {@link UniquenessInput} for more details.
92
+ */
93
+ unique(value: UniquenessInput): this;
94
+ /**
95
+ * Sets the maximum number of attempts for the job.
96
+ * @param value The max attempts.
97
+ * @returns This builder instance.
98
+ */
99
+ maxAttempts(value: number): this;
100
+ /**
101
+ * Sets the time when the job becomes available.
102
+ * @param value The available date.
103
+ * @returns This builder instance.
104
+ */
105
+ availableAt(value: Date): this;
106
+ /**
107
+ * Enqueues the job with the specified arguments.
108
+ * @param args Arguments to pass to the job's run method.
109
+ * @returns A promise resolving to the created job data.
110
+ */
111
+ enqueue(...args: Parameters<InstanceType<T>["run"]>): Promise<JobData>;
112
+ }
113
+
114
+ export { JobBuilder };
115
+ export type { JobBuilderDefaults, UniquenessInput };
@@ -0,0 +1,151 @@
1
+ import { logger, UniquenessFactory } from '@sidequest/core';
2
+ import { JOB_BUILDER_FALLBACK } from './constants.js';
3
+
4
+ /**
5
+ * Builder for creating and enqueuing jobs with custom configuration.
6
+ * @template T The job class type.
7
+ */
8
+ class JobBuilder {
9
+ backend;
10
+ JobClass;
11
+ defaults;
12
+ constructorArgs;
13
+ queueName;
14
+ jobTimeout;
15
+ uniquenessConfig;
16
+ jobMaxAttempts;
17
+ jobAvailableAt;
18
+ /**
19
+ * Creates a new JobBuilder for the given job class.
20
+ * @param JobClass The job class constructor.
21
+ */
22
+ constructor(backend, JobClass, defaults) {
23
+ this.backend = backend;
24
+ this.JobClass = JobClass;
25
+ this.defaults = defaults;
26
+ this.queue(this.defaults?.queue ?? JOB_BUILDER_FALLBACK.queue);
27
+ this.maxAttempts(this.defaults?.maxAttempts ?? JOB_BUILDER_FALLBACK.maxAttempts);
28
+ this.availableAt(this.defaults?.availableAt ?? JOB_BUILDER_FALLBACK.availableAt);
29
+ this.timeout(this.defaults?.timeout ?? JOB_BUILDER_FALLBACK.timeout);
30
+ this.unique(this.defaults?.uniqueness ?? JOB_BUILDER_FALLBACK.uniqueness);
31
+ this.with(...JOB_BUILDER_FALLBACK.constructorArgs);
32
+ }
33
+ /**
34
+ * Sets the constructor arguments for the job.
35
+ * @param args The constructor arguments.
36
+ * @returns This builder instance.
37
+ */
38
+ with(...args) {
39
+ this.constructorArgs = args;
40
+ return this;
41
+ }
42
+ /**
43
+ * Sets the queue name for the job.
44
+ * @param queue The queue name.
45
+ * @returns This builder instance.
46
+ */
47
+ queue(queue) {
48
+ this.queueName = queue;
49
+ return this;
50
+ }
51
+ /**
52
+ * Sets the timeout for the job in milliseconds.
53
+ * @param ms Timeout in milliseconds.
54
+ * @returns This builder instance.
55
+ */
56
+ timeout(ms) {
57
+ this.jobTimeout = ms;
58
+ return this;
59
+ }
60
+ /**
61
+ * Sets the uniqueness configuration for the job.
62
+ * @param value Boolean or uniqueness config object. If true, uses an alive job uniqueness strategy (see {@link AliveJobUniqueness}).
63
+ * If false, disables uniqueness. If an object, uses the custom uniqueness strategy.
64
+ * @param value.withArgs If true, uniqueness is based on job class and job arguments.
65
+ * If false, uniqueness is based only on the job class.
66
+ * @param value.period If a period is provided, uses a fixed window uniqueness strategy (see {@link FixedWindowUniqueness}).
67
+ * @returns This builder instance.
68
+ * @see {@link UniquenessInput} for more details.
69
+ */
70
+ unique(value) {
71
+ if (typeof value === "boolean") {
72
+ if (value) {
73
+ const config = {
74
+ type: "alive-job",
75
+ withArgs: false,
76
+ };
77
+ this.uniquenessConfig = config;
78
+ }
79
+ else {
80
+ this.uniquenessConfig = undefined; // no uniqueness
81
+ }
82
+ }
83
+ else {
84
+ if (value.period) {
85
+ this.uniquenessConfig = {
86
+ type: "fixed-window",
87
+ period: value.period,
88
+ withArgs: value.withArgs,
89
+ };
90
+ }
91
+ else {
92
+ this.uniquenessConfig = { type: "alive-job", withArgs: value.withArgs };
93
+ }
94
+ }
95
+ return this;
96
+ }
97
+ /**
98
+ * Sets the maximum number of attempts for the job.
99
+ * @param value The max attempts.
100
+ * @returns This builder instance.
101
+ */
102
+ maxAttempts(value) {
103
+ this.jobMaxAttempts = value;
104
+ return this;
105
+ }
106
+ /**
107
+ * Sets the time when the job becomes available.
108
+ * @param value The available date.
109
+ * @returns This builder instance.
110
+ */
111
+ availableAt(value) {
112
+ this.jobAvailableAt = value;
113
+ return this;
114
+ }
115
+ /**
116
+ * Enqueues the job with the specified arguments.
117
+ * @param args Arguments to pass to the job's run method.
118
+ * @returns A promise resolving to the created job data.
119
+ */
120
+ async enqueue(...args) {
121
+ const job = new this.JobClass(...this.constructorArgs);
122
+ await job.ready();
123
+ if (!job.script) {
124
+ throw new Error(`Error on starting job ${job.className} could not detect source file.`);
125
+ }
126
+ const jobData = {
127
+ queue: this.queueName,
128
+ script: job.script,
129
+ class: job.className,
130
+ state: "waiting",
131
+ args,
132
+ constructor_args: this.constructorArgs,
133
+ attempt: 0,
134
+ max_attempts: this.jobMaxAttempts,
135
+ available_at: this.jobAvailableAt,
136
+ timeout: this.jobTimeout,
137
+ uniqueness_config: this.uniquenessConfig,
138
+ };
139
+ logger("JobBuilder").debug(`Enqueuing job ${job.className} with args: ${JSON.stringify(args)}
140
+ and constructor args: ${JSON.stringify(this.constructorArgs)}`);
141
+ if (this.uniquenessConfig) {
142
+ const uniqueness = UniquenessFactory.create(this.uniquenessConfig);
143
+ jobData.unique_digest = uniqueness.digest(jobData);
144
+ logger("JobBuilder").debug(`Job ${job.className} uniqueness digest: ${jobData.unique_digest}`);
145
+ }
146
+ return this.backend.createNewJob(jobData);
147
+ }
148
+ }
149
+
150
+ export { JobBuilder };
151
+ //# sourceMappingURL=job-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-builder.js","sources":["../../src/job/job-builder.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+
3
+ var core = require('@sidequest/core');
4
+
5
+ /**
6
+ * Handles applying job transitions and updating jobs in the backend.
7
+ */
8
+ class JobTransitioner {
9
+ /**
10
+ * Applies a transition to a job and updates it in the backend.
11
+ *
12
+ * This method checks if the transition should run based on the job's current state.
13
+ * If applicable, it applies the transition and updates the job in the backend.
14
+ *
15
+ * @param jobData The job data to update.
16
+ * @param transition The job transition to apply.
17
+ * @returns A promise resolving to the updated job data.
18
+ */
19
+ static apply(backend, jobData, transition) {
20
+ if (!transition.shouldRun(jobData)) {
21
+ core.logger("JobTransitioner").debug(`Transition ${transition.constructor.name} not applicable for job ${jobData.id}. Returning original job data.`);
22
+ return jobData;
23
+ }
24
+ core.logger("JobTransitioner").info(`Applying transition ${transition.constructor.name} to job ${jobData.id}`);
25
+ const newData = transition.apply(jobData);
26
+ if (newData.uniqueness_config) {
27
+ const uniqueness = core.UniquenessFactory.create(newData.uniqueness_config);
28
+ newData.unique_digest = uniqueness.digest(jobData);
29
+ }
30
+ core.logger("JobTransitioner").debug(`Updating with new job data: ${JSON.stringify(newData)}`);
31
+ return backend.updateJob(newData);
32
+ }
33
+ }
34
+
35
+ exports.JobTransitioner = JobTransitioner;
36
+ //# sourceMappingURL=job-transitioner.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-transitioner.cjs","sources":["../../src/job/job-transitioner.ts"],"sourcesContent":[null],"names":["logger","UniquenessFactory"],"mappings":";;;;AAGA;;AAEG;MACU,eAAe,CAAA;AAC1B;;;;;;;;;AASG;AACH,IAAA,OAAO,KAAK,CAAC,OAAgB,EAAE,OAAgB,EAAE,UAAyB,EAAA;QACxE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;AAClC,YAAAA,WAAM,CAAC,iBAAiB,CAAC,CAAC,KAAK,CAC7B,cAAc,UAAU,CAAC,WAAW,CAAC,IAAI,CAAA,wBAAA,EAA2B,OAAO,CAAC,EAAE,CAAA,8BAAA,CAAgC,CAC/G;AACD,YAAA,OAAO,OAAO;QAChB;AAEA,QAAAA,WAAM,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,uBAAuB,UAAU,CAAC,WAAW,CAAC,IAAI,CAAA,QAAA,EAAW,OAAO,CAAC,EAAE,CAAA,CAAE,CAAC;QACzG,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC;AACzC,QAAA,IAAI,OAAO,CAAC,iBAAiB,EAAE;YAC7B,MAAM,UAAU,GAAGC,sBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC;YACtE,OAAO,CAAC,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC;QACpD;AACA,QAAAD,WAAM,CAAC,iBAAiB,CAAC,CAAC,KAAK,CAAC,CAAA,4BAAA,EAA+B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA,CAAE,CAAC;AACzF,QAAA,OAAO,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC;IACnC;AACD;;;;"}
@@ -0,0 +1,21 @@
1
+ import { Backend } from '@sidequest/backend';
2
+ import { JobData, JobTransition } from '@sidequest/core';
3
+
4
+ /**
5
+ * Handles applying job transitions and updating jobs in the backend.
6
+ */
7
+ declare class JobTransitioner {
8
+ /**
9
+ * Applies a transition to a job and updates it in the backend.
10
+ *
11
+ * This method checks if the transition should run based on the job's current state.
12
+ * If applicable, it applies the transition and updates the job in the backend.
13
+ *
14
+ * @param jobData The job data to update.
15
+ * @param transition The job transition to apply.
16
+ * @returns A promise resolving to the updated job data.
17
+ */
18
+ static apply(backend: Backend, jobData: JobData, transition: JobTransition): JobData | Promise<JobData>;
19
+ }
20
+
21
+ export { JobTransitioner };
@@ -0,0 +1,34 @@
1
+ import { logger, UniquenessFactory } from '@sidequest/core';
2
+
3
+ /**
4
+ * Handles applying job transitions and updating jobs in the backend.
5
+ */
6
+ class JobTransitioner {
7
+ /**
8
+ * Applies a transition to a job and updates it in the backend.
9
+ *
10
+ * This method checks if the transition should run based on the job's current state.
11
+ * If applicable, it applies the transition and updates the job in the backend.
12
+ *
13
+ * @param jobData The job data to update.
14
+ * @param transition The job transition to apply.
15
+ * @returns A promise resolving to the updated job data.
16
+ */
17
+ static apply(backend, jobData, transition) {
18
+ if (!transition.shouldRun(jobData)) {
19
+ logger("JobTransitioner").debug(`Transition ${transition.constructor.name} not applicable for job ${jobData.id}. Returning original job data.`);
20
+ return jobData;
21
+ }
22
+ logger("JobTransitioner").info(`Applying transition ${transition.constructor.name} to job ${jobData.id}`);
23
+ const newData = transition.apply(jobData);
24
+ if (newData.uniqueness_config) {
25
+ const uniqueness = UniquenessFactory.create(newData.uniqueness_config);
26
+ newData.unique_digest = uniqueness.digest(jobData);
27
+ }
28
+ logger("JobTransitioner").debug(`Updating with new job data: ${JSON.stringify(newData)}`);
29
+ return backend.updateJob(newData);
30
+ }
31
+ }
32
+
33
+ export { JobTransitioner };
34
+ //# sourceMappingURL=job-transitioner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-transitioner.js","sources":["../../src/job/job-transitioner.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAGA;;AAEG;MACU,eAAe,CAAA;AAC1B;;;;;;;;;AASG;AACH,IAAA,OAAO,KAAK,CAAC,OAAgB,EAAE,OAAgB,EAAE,UAAyB,EAAA;QACxE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;AAClC,YAAA,MAAM,CAAC,iBAAiB,CAAC,CAAC,KAAK,CAC7B,cAAc,UAAU,CAAC,WAAW,CAAC,IAAI,CAAA,wBAAA,EAA2B,OAAO,CAAC,EAAE,CAAA,8BAAA,CAAgC,CAC/G;AACD,YAAA,OAAO,OAAO;QAChB;AAEA,QAAA,MAAM,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,uBAAuB,UAAU,CAAC,WAAW,CAAC,IAAI,CAAA,QAAA,EAAW,OAAO,CAAC,EAAE,CAAA,CAAE,CAAC;QACzG,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC;AACzC,QAAA,IAAI,OAAO,CAAC,iBAAiB,EAAE;YAC7B,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC;YACtE,OAAO,CAAC,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC;QACpD;AACA,QAAA,MAAM,CAAC,iBAAiB,CAAC,CAAC,KAAK,CAAC,CAAA,4BAAA,EAA+B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA,CAAE,CAAC;AACzF,QAAA,OAAO,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC;IACnC;AACD;;;;"}