@morojs/moro 1.6.5 → 1.6.8

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 (200) hide show
  1. package/README.md +20 -4
  2. package/dist/core/auth/morojs-adapter.js +17 -14
  3. package/dist/core/auth/morojs-adapter.js.map +1 -1
  4. package/dist/core/config/config-sources.js +44 -0
  5. package/dist/core/config/config-sources.js.map +1 -1
  6. package/dist/core/database/adapters/drizzle.js +5 -5
  7. package/dist/core/database/adapters/drizzle.js.map +1 -1
  8. package/dist/core/database/adapters/mongodb.js +5 -1
  9. package/dist/core/database/adapters/mongodb.js.map +1 -1
  10. package/dist/core/database/adapters/mysql.js +5 -1
  11. package/dist/core/database/adapters/mysql.js.map +1 -1
  12. package/dist/core/database/adapters/postgresql.js +1 -1
  13. package/dist/core/database/adapters/postgresql.js.map +1 -1
  14. package/dist/core/database/adapters/redis.js +2 -2
  15. package/dist/core/database/adapters/redis.js.map +1 -1
  16. package/dist/core/database/adapters/sqlite.js +5 -1
  17. package/dist/core/database/adapters/sqlite.js.map +1 -1
  18. package/dist/core/docs/index.js.map +1 -1
  19. package/dist/core/docs/simple-docs.js +2 -1
  20. package/dist/core/docs/simple-docs.js.map +1 -1
  21. package/dist/core/docs/swagger-ui.js +1 -0
  22. package/dist/core/docs/swagger-ui.js.map +1 -1
  23. package/dist/core/docs/zod-to-openapi.js +4 -0
  24. package/dist/core/docs/zod-to-openapi.js.map +1 -1
  25. package/dist/core/events/event-bus.d.ts +1 -1
  26. package/dist/core/events/event-bus.js +8 -4
  27. package/dist/core/events/event-bus.js.map +1 -1
  28. package/dist/core/framework.d.ts +1 -1
  29. package/dist/core/framework.js +3 -1
  30. package/dist/core/framework.js.map +1 -1
  31. package/dist/core/graphql/adapter.d.ts +73 -0
  32. package/dist/core/graphql/adapter.js +2 -0
  33. package/dist/core/graphql/adapter.js.map +1 -0
  34. package/dist/core/graphql/adapters/graphql-js-adapter.d.ts +26 -0
  35. package/dist/core/graphql/adapters/graphql-js-adapter.js +229 -0
  36. package/dist/core/graphql/adapters/graphql-js-adapter.js.map +1 -0
  37. package/dist/core/graphql/core.d.ts +60 -0
  38. package/dist/core/graphql/core.js +165 -0
  39. package/dist/core/graphql/core.js.map +1 -0
  40. package/dist/core/graphql/index.d.ts +4 -0
  41. package/dist/core/graphql/index.js +4 -0
  42. package/dist/core/graphql/index.js.map +1 -0
  43. package/dist/core/graphql/loader.d.ts +9 -0
  44. package/dist/core/graphql/loader.js +32 -0
  45. package/dist/core/graphql/loader.js.map +1 -0
  46. package/dist/core/graphql/types.d.ts +211 -0
  47. package/dist/core/graphql/types.js +2 -0
  48. package/dist/core/graphql/types.js.map +1 -0
  49. package/dist/core/http/http-server.d.ts +7 -0
  50. package/dist/core/http/http-server.js +267 -123
  51. package/dist/core/http/http-server.js.map +1 -1
  52. package/dist/core/http/utils/uws-worker-clustering.d.ts +28 -0
  53. package/dist/core/http/utils/uws-worker-clustering.js +313 -0
  54. package/dist/core/http/utils/uws-worker-clustering.js.map +1 -0
  55. package/dist/core/http/uws-http-server.d.ts +7 -1
  56. package/dist/core/http/uws-http-server.js +272 -189
  57. package/dist/core/http/uws-http-server.js.map +1 -1
  58. package/dist/core/jobs/cron-parser.d.ts +62 -0
  59. package/dist/core/jobs/cron-parser.js +239 -0
  60. package/dist/core/jobs/cron-parser.js.map +1 -0
  61. package/dist/core/jobs/index.d.ts +12 -0
  62. package/dist/core/jobs/index.js +9 -0
  63. package/dist/core/jobs/index.js.map +1 -0
  64. package/dist/core/jobs/job-executor.d.ts +134 -0
  65. package/dist/core/jobs/job-executor.js +413 -0
  66. package/dist/core/jobs/job-executor.js.map +1 -0
  67. package/dist/core/jobs/job-scheduler.d.ts +214 -0
  68. package/dist/core/jobs/job-scheduler.js +551 -0
  69. package/dist/core/jobs/job-scheduler.js.map +1 -0
  70. package/dist/core/jobs/job-state-manager.d.ts +158 -0
  71. package/dist/core/jobs/job-state-manager.js +444 -0
  72. package/dist/core/jobs/job-state-manager.js.map +1 -0
  73. package/dist/core/jobs/leader-election.d.ts +124 -0
  74. package/dist/core/jobs/leader-election.js +481 -0
  75. package/dist/core/jobs/leader-election.js.map +1 -0
  76. package/dist/core/jobs/types.d.ts +151 -0
  77. package/dist/core/jobs/types.js +4 -0
  78. package/dist/core/jobs/types.js.map +1 -0
  79. package/dist/core/jobs/utils.d.ts +95 -0
  80. package/dist/core/jobs/utils.js +258 -0
  81. package/dist/core/jobs/utils.js.map +1 -0
  82. package/dist/core/logger/filters.js +2 -0
  83. package/dist/core/logger/filters.js.map +1 -1
  84. package/dist/core/logger/logger.d.ts +7 -5
  85. package/dist/core/logger/logger.js +68 -27
  86. package/dist/core/logger/logger.js.map +1 -1
  87. package/dist/core/logger/outputs.js +2 -0
  88. package/dist/core/logger/outputs.js.map +1 -1
  89. package/dist/core/middleware/built-in/auth/helpers.js +1 -1
  90. package/dist/core/middleware/built-in/auth/helpers.js.map +1 -1
  91. package/dist/core/middleware/built-in/auth/jwt-helpers.js +1 -1
  92. package/dist/core/middleware/built-in/auth/jwt-helpers.js.map +1 -1
  93. package/dist/core/middleware/built-in/auth/providers.js +1 -1
  94. package/dist/core/middleware/built-in/auth/providers.js.map +1 -1
  95. package/dist/core/middleware/built-in/cache/adapters/cache/file.js +3 -3
  96. package/dist/core/middleware/built-in/cache/adapters/cache/file.js.map +1 -1
  97. package/dist/core/middleware/built-in/cache/adapters/cache/memory.js +1 -0
  98. package/dist/core/middleware/built-in/cache/adapters/cache/memory.js.map +1 -1
  99. package/dist/core/middleware/built-in/cache/adapters/cache/redis.js +1 -1
  100. package/dist/core/middleware/built-in/cache/adapters/cache/redis.js.map +1 -1
  101. package/dist/core/middleware/built-in/cdn/adapters/cdn/azure.d.ts +8 -0
  102. package/dist/core/middleware/built-in/cdn/adapters/cdn/azure.js +100 -7
  103. package/dist/core/middleware/built-in/cdn/adapters/cdn/azure.js.map +1 -1
  104. package/dist/core/middleware/built-in/cdn/adapters/cdn/cloudflare.d.ts +6 -0
  105. package/dist/core/middleware/built-in/cdn/adapters/cdn/cloudflare.js +97 -13
  106. package/dist/core/middleware/built-in/cdn/adapters/cdn/cloudflare.js.map +1 -1
  107. package/dist/core/middleware/built-in/cdn/adapters/cdn/cloudfront.js +1 -1
  108. package/dist/core/middleware/built-in/cdn/adapters/cdn/cloudfront.js.map +1 -1
  109. package/dist/core/middleware/built-in/cookie/hook.d.ts +1 -1
  110. package/dist/core/middleware/built-in/cookie/hook.js +2 -2
  111. package/dist/core/middleware/built-in/cookie/hook.js.map +1 -1
  112. package/dist/core/middleware/built-in/csrf/core.js +1 -0
  113. package/dist/core/middleware/built-in/csrf/core.js.map +1 -1
  114. package/dist/core/middleware/built-in/graphql/core.d.ts +11 -0
  115. package/dist/core/middleware/built-in/graphql/core.js +24 -0
  116. package/dist/core/middleware/built-in/graphql/core.js.map +1 -0
  117. package/dist/core/middleware/built-in/graphql/helpers.d.ts +69 -0
  118. package/dist/core/middleware/built-in/graphql/helpers.js +187 -0
  119. package/dist/core/middleware/built-in/graphql/helpers.js.map +1 -0
  120. package/dist/core/middleware/built-in/graphql/hook.d.ts +7 -0
  121. package/dist/core/middleware/built-in/graphql/hook.js +78 -0
  122. package/dist/core/middleware/built-in/graphql/hook.js.map +1 -0
  123. package/dist/core/middleware/built-in/graphql/index.d.ts +5 -0
  124. package/dist/core/middleware/built-in/graphql/index.js +5 -0
  125. package/dist/core/middleware/built-in/graphql/index.js.map +1 -0
  126. package/dist/core/middleware/built-in/graphql/middleware.d.ts +7 -0
  127. package/dist/core/middleware/built-in/graphql/middleware.js +54 -0
  128. package/dist/core/middleware/built-in/graphql/middleware.js.map +1 -0
  129. package/dist/core/middleware/built-in/graphql/subscriptions.d.ts +20 -0
  130. package/dist/core/middleware/built-in/graphql/subscriptions.js +37 -0
  131. package/dist/core/middleware/built-in/graphql/subscriptions.js.map +1 -0
  132. package/dist/core/middleware/built-in/index.d.ts +2 -1
  133. package/dist/core/middleware/built-in/index.js +3 -0
  134. package/dist/core/middleware/built-in/index.js.map +1 -1
  135. package/dist/core/middleware/built-in/rate-limit/core.d.ts +5 -0
  136. package/dist/core/middleware/built-in/rate-limit/core.js +16 -8
  137. package/dist/core/middleware/built-in/rate-limit/core.js.map +1 -1
  138. package/dist/core/middleware/built-in/validation/core.js +42 -19
  139. package/dist/core/middleware/built-in/validation/core.js.map +1 -1
  140. package/dist/core/middleware/index.js +1 -0
  141. package/dist/core/middleware/index.js.map +1 -1
  142. package/dist/core/modules/auto-discovery.js +5 -4
  143. package/dist/core/modules/auto-discovery.js.map +1 -1
  144. package/dist/core/modules/modules.js.map +1 -1
  145. package/dist/core/networking/adapters/socketio-adapter.js +1 -1
  146. package/dist/core/networking/adapters/socketio-adapter.js.map +1 -1
  147. package/dist/core/networking/adapters/uws-adapter.js +7 -2
  148. package/dist/core/networking/adapters/uws-adapter.js.map +1 -1
  149. package/dist/core/networking/adapters/ws-adapter.js +5 -2
  150. package/dist/core/networking/adapters/ws-adapter.js.map +1 -1
  151. package/dist/core/networking/websocket-manager.js +2 -0
  152. package/dist/core/networking/websocket-manager.js.map +1 -1
  153. package/dist/core/pooling/object-pool-manager.d.ts +8 -2
  154. package/dist/core/pooling/object-pool-manager.js +38 -18
  155. package/dist/core/pooling/object-pool-manager.js.map +1 -1
  156. package/dist/core/routing/app-integration.d.ts +3 -3
  157. package/dist/core/routing/app-integration.js +1 -1
  158. package/dist/core/routing/app-integration.js.map +1 -1
  159. package/dist/core/routing/index.d.ts +1 -1
  160. package/dist/core/routing/index.js +1 -1
  161. package/dist/core/routing/index.js.map +1 -1
  162. package/dist/core/routing/path-matcher.d.ts +6 -0
  163. package/dist/core/routing/path-matcher.js +46 -7
  164. package/dist/core/routing/path-matcher.js.map +1 -1
  165. package/dist/core/routing/unified-router.d.ts +4 -0
  166. package/dist/core/routing/unified-router.js +104 -43
  167. package/dist/core/routing/unified-router.js.map +1 -1
  168. package/dist/core/runtime/base-adapter.js +3 -3
  169. package/dist/core/runtime/base-adapter.js.map +1 -1
  170. package/dist/core/runtime/cloudflare-workers-adapter.js +1 -1
  171. package/dist/core/runtime/cloudflare-workers-adapter.js.map +1 -1
  172. package/dist/core/runtime/node-adapter.d.ts +1 -1
  173. package/dist/core/runtime/node-adapter.js +7 -4
  174. package/dist/core/runtime/node-adapter.js.map +1 -1
  175. package/dist/core/runtime/vercel-edge-adapter.js +1 -0
  176. package/dist/core/runtime/vercel-edge-adapter.js.map +1 -1
  177. package/dist/core/utilities/circuit-breaker.d.ts +9 -2
  178. package/dist/core/utilities/circuit-breaker.js +32 -3
  179. package/dist/core/utilities/circuit-breaker.js.map +1 -1
  180. package/dist/core/utilities/container.js +6 -0
  181. package/dist/core/utilities/container.js.map +1 -1
  182. package/dist/core/utilities/hooks.d.ts +4 -0
  183. package/dist/core/utilities/hooks.js +134 -22
  184. package/dist/core/utilities/hooks.js.map +1 -1
  185. package/dist/core/validation/index.js +6 -1
  186. package/dist/core/validation/index.js.map +1 -1
  187. package/dist/index.d.ts +6 -0
  188. package/dist/index.js +5 -0
  189. package/dist/index.js.map +1 -1
  190. package/dist/moro.d.ts +154 -1
  191. package/dist/moro.js +592 -16
  192. package/dist/moro.js.map +1 -1
  193. package/dist/types/config.d.ts +28 -0
  194. package/dist/types/core.d.ts +1 -0
  195. package/dist/types/events.d.ts +1 -1
  196. package/dist/types/events.js +1 -0
  197. package/dist/types/events.js.map +1 -1
  198. package/dist/types/logger.d.ts +1 -0
  199. package/dist/types/module.d.ts +2 -2
  200. package/package.json +21 -1
@@ -0,0 +1,551 @@
1
+ // Production-grade Job Scheduler
2
+ // Main scheduler with graceful shutdown, concurrency control, and priority queue
3
+ import { EventEmitter } from 'events';
4
+ import { CronParser } from './cron-parser.js';
5
+ import { JobStateManager } from './job-state-manager.js';
6
+ import { LeaderElection } from './leader-election.js';
7
+ import { JobExecutor } from './job-executor.js';
8
+ import { randomBytes } from 'crypto';
9
+ /**
10
+ * JobScheduler - Production-grade job scheduling system
11
+ * Features:
12
+ * - Cron, interval, and one-time scheduling
13
+ * - Leader election for distributed systems
14
+ * - Graceful shutdown with running job completion
15
+ * - Global and per-job concurrency control
16
+ * - Priority queue for job execution
17
+ * - Automatic crash recovery
18
+ * - Full observability with events and metrics
19
+ */
20
+ export class JobScheduler extends EventEmitter {
21
+ jobs = new Map();
22
+ stateManager;
23
+ leaderElection;
24
+ executor;
25
+ logger;
26
+ loggerContext = 'JobScheduler';
27
+ started = false;
28
+ isShuttingDown = false;
29
+ maxConcurrentJobs;
30
+ currentConcurrentJobs = 0;
31
+ pendingQueue = [];
32
+ gracefulShutdownTimeout;
33
+ enableLeaderElection;
34
+ constructor(logger, options = {}) {
35
+ super();
36
+ this.logger = logger;
37
+ this.maxConcurrentJobs = options.maxConcurrentJobs ?? 10;
38
+ this.gracefulShutdownTimeout = options.gracefulShutdownTimeout ?? 30000;
39
+ this.enableLeaderElection = options.enableLeaderElection ?? true;
40
+ // Initialize state manager
41
+ this.stateManager = new JobStateManager(logger, options.stateManager);
42
+ // Initialize executor
43
+ this.executor = new JobExecutor(logger, options.executor);
44
+ // Initialize leader election if enabled
45
+ if (this.enableLeaderElection) {
46
+ this.leaderElection = new LeaderElection(logger, options.leaderElection);
47
+ // Handle leader election events
48
+ this.leaderElection.on('leader:elected', () => {
49
+ this.logger.info('Became leader, starting job scheduling', this.loggerContext);
50
+ this.scheduleAllJobs();
51
+ });
52
+ this.leaderElection.on('leader:stepdown', () => {
53
+ this.logger.info('Lost leadership, stopping job scheduling', this.loggerContext);
54
+ this.unscheduleAllJobs();
55
+ });
56
+ }
57
+ this.logger.debug('JobScheduler initialized', this.loggerContext, {
58
+ maxConcurrentJobs: this.maxConcurrentJobs,
59
+ enableLeaderElection: this.enableLeaderElection,
60
+ });
61
+ }
62
+ /**
63
+ * Start the job scheduler
64
+ */
65
+ async start() {
66
+ if (this.started) {
67
+ this.logger.warn('JobScheduler already started', this.loggerContext);
68
+ return;
69
+ }
70
+ this.logger.info('Starting JobScheduler...', this.loggerContext);
71
+ this.started = true;
72
+ // Start leader election if enabled
73
+ if (this.leaderElection) {
74
+ await this.leaderElection.start();
75
+ }
76
+ else {
77
+ // No leader election, start immediately
78
+ this.scheduleAllJobs();
79
+ }
80
+ this.logger.info('JobScheduler started', this.loggerContext, {
81
+ jobCount: this.jobs.size,
82
+ isLeader: this.isLeader(),
83
+ });
84
+ this.emit('scheduler:started', {
85
+ jobCount: this.jobs.size,
86
+ isLeader: this.isLeader(),
87
+ });
88
+ }
89
+ /**
90
+ * Register a new job
91
+ */
92
+ registerJob(name, schedule, fn, options = {}) {
93
+ const jobId = this.generateJobId();
94
+ // Validate schedule
95
+ this.validateSchedule(schedule);
96
+ const job = {
97
+ id: jobId,
98
+ name: options.name || name,
99
+ schedule,
100
+ fn,
101
+ options: { ...options, name: options.name || name, schedule },
102
+ enabled: options.enabled !== false,
103
+ priority: options.priority ?? 0,
104
+ concurrentExecutions: 0,
105
+ createdAt: new Date(),
106
+ };
107
+ // Calculate next run
108
+ job.nextRun = this.calculateNextRun(job);
109
+ this.jobs.set(jobId, job);
110
+ // Register in state manager
111
+ this.stateManager.registerJob(jobId, job.name, {
112
+ schedule: job.schedule,
113
+ priority: job.priority,
114
+ ...options.metadata,
115
+ });
116
+ this.logger.info(`Job registered: ${job.name} (${jobId})`, this.loggerContext, {
117
+ schedule: job.schedule,
118
+ nextRun: job.nextRun,
119
+ });
120
+ this.emit('job:registered', { jobId, name: job.name, schedule: job.schedule });
121
+ // Schedule if already started and is leader
122
+ if (this.started && this.isLeader() && job.enabled) {
123
+ this.scheduleJob(job);
124
+ }
125
+ return jobId;
126
+ }
127
+ /**
128
+ * Unregister a job
129
+ */
130
+ unregisterJob(jobId) {
131
+ const job = this.jobs.get(jobId);
132
+ if (!job) {
133
+ return false;
134
+ }
135
+ // Unschedule
136
+ this.unscheduleJob(job);
137
+ // Remove from jobs
138
+ this.jobs.delete(jobId);
139
+ // Unregister from state manager
140
+ this.stateManager.unregisterJob(jobId);
141
+ this.logger.info(`Job unregistered: ${job.name} (${jobId})`, this.loggerContext);
142
+ this.emit('job:unregistered', { jobId, name: job.name });
143
+ return true;
144
+ }
145
+ /**
146
+ * Get job by ID
147
+ */
148
+ getJob(jobId) {
149
+ return this.jobs.get(jobId);
150
+ }
151
+ /**
152
+ * Get all jobs
153
+ */
154
+ getAllJobs() {
155
+ return Array.from(this.jobs.values());
156
+ }
157
+ /**
158
+ * Enable/disable job
159
+ */
160
+ setJobEnabled(jobId, enabled) {
161
+ const job = this.jobs.get(jobId);
162
+ if (!job) {
163
+ return false;
164
+ }
165
+ job.enabled = enabled;
166
+ this.stateManager.setJobEnabled(jobId, enabled);
167
+ if (enabled && this.started && this.isLeader()) {
168
+ this.scheduleJob(job);
169
+ }
170
+ else if (!enabled) {
171
+ this.unscheduleJob(job);
172
+ }
173
+ this.logger.info(`Job ${enabled ? 'enabled' : 'disabled'}: ${job.name} (${jobId})`, this.loggerContext);
174
+ this.emit('job:enabled', { jobId, enabled });
175
+ return true;
176
+ }
177
+ /**
178
+ * Manually trigger job execution
179
+ */
180
+ async triggerJob(jobId, metadata) {
181
+ const job = this.jobs.get(jobId);
182
+ if (!job) {
183
+ throw new Error(`Job not found: ${jobId}`);
184
+ }
185
+ this.logger.info(`Manually triggering job: ${job.name} (${jobId})`, this.loggerContext);
186
+ return this.executeJob(job, metadata);
187
+ }
188
+ /**
189
+ * Validate schedule configuration
190
+ */
191
+ validateSchedule(schedule) {
192
+ if (schedule.type === 'cron') {
193
+ if (!schedule.cron) {
194
+ throw new Error('Cron schedule requires cron expression');
195
+ }
196
+ // Validate cron expression
197
+ const validation = CronParser.validate(schedule.cron);
198
+ if (!validation.valid) {
199
+ throw new Error(`Invalid cron expression: ${validation.error}`);
200
+ }
201
+ }
202
+ else if (schedule.type === 'interval') {
203
+ if (!schedule.interval || schedule.interval <= 0) {
204
+ throw new Error('Interval schedule requires positive interval value');
205
+ }
206
+ }
207
+ else if (schedule.type === 'oneTime') {
208
+ if (!schedule.at) {
209
+ throw new Error('One-time schedule requires date');
210
+ }
211
+ if (schedule.at < new Date()) {
212
+ throw new Error('One-time schedule date must be in the future');
213
+ }
214
+ }
215
+ }
216
+ /**
217
+ * Calculate next run time for job
218
+ */
219
+ calculateNextRun(job) {
220
+ const { schedule } = job;
221
+ if (schedule.type === 'cron') {
222
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
223
+ const parser = new CronParser(schedule.cron, job.options.timezone);
224
+ return parser.getNextRun().next;
225
+ }
226
+ else if (schedule.type === 'interval') {
227
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
228
+ return new Date(Date.now() + schedule.interval);
229
+ }
230
+ else if (schedule.type === 'oneTime') {
231
+ return schedule.at;
232
+ }
233
+ return undefined;
234
+ }
235
+ /**
236
+ * Schedule all jobs
237
+ */
238
+ scheduleAllJobs() {
239
+ for (const job of this.jobs.values()) {
240
+ if (job.enabled) {
241
+ this.scheduleJob(job);
242
+ }
243
+ }
244
+ }
245
+ /**
246
+ * Schedule a single job
247
+ */
248
+ scheduleJob(job) {
249
+ // Unschedule first if already scheduled
250
+ this.unscheduleJob(job);
251
+ if (!job.nextRun) {
252
+ this.logger.warn(`Job ${job.name} has no next run time, skipping schedule`, this.loggerContext);
253
+ return;
254
+ }
255
+ const delay = job.nextRun.getTime() - Date.now();
256
+ if (delay < 0) {
257
+ // Should have run already, execute immediately and calculate next
258
+ this.logger.debug(`Job ${job.name} overdue, executing immediately`, this.loggerContext);
259
+ this.queueJobExecution(job);
260
+ return;
261
+ }
262
+ job.timer = setTimeout(() => {
263
+ this.queueJobExecution(job);
264
+ }, delay);
265
+ // Don't keep process alive for job timers
266
+ job.timer.unref();
267
+ this.stateManager.setNextRun(job.id, job.nextRun);
268
+ this.logger.debug(`Job scheduled: ${job.name} (${job.id})`, this.loggerContext, {
269
+ nextRun: job.nextRun,
270
+ delay,
271
+ });
272
+ }
273
+ /**
274
+ * Unschedule a job
275
+ */
276
+ unscheduleJob(job) {
277
+ if (job.timer) {
278
+ clearTimeout(job.timer);
279
+ job.timer = undefined;
280
+ }
281
+ }
282
+ /**
283
+ * Unschedule all jobs
284
+ */
285
+ unscheduleAllJobs() {
286
+ for (const job of this.jobs.values()) {
287
+ this.unscheduleJob(job);
288
+ }
289
+ }
290
+ /**
291
+ * Queue job for execution (with concurrency control)
292
+ */
293
+ queueJobExecution(job) {
294
+ const executionId = this.generateExecutionId();
295
+ // Check global concurrency limit
296
+ if (this.currentConcurrentJobs >= this.maxConcurrentJobs) {
297
+ this.logger.debug(`Global concurrency limit reached, queueing job: ${job.name}`, this.loggerContext, {
298
+ current: this.currentConcurrentJobs,
299
+ max: this.maxConcurrentJobs,
300
+ });
301
+ this.pendingQueue.push({ job, executionId });
302
+ this.emit('job:queued', {
303
+ jobId: job.id,
304
+ executionId,
305
+ queueLength: this.pendingQueue.length,
306
+ });
307
+ return;
308
+ }
309
+ // Check per-job concurrency limit
310
+ const maxConcurrent = job.options.maxConcurrent ?? 1;
311
+ if (job.concurrentExecutions >= maxConcurrent) {
312
+ this.logger.debug(`Job concurrency limit reached, queueing: ${job.name}`, this.loggerContext, {
313
+ current: job.concurrentExecutions,
314
+ max: maxConcurrent,
315
+ });
316
+ this.pendingQueue.push({ job, executionId });
317
+ this.emit('job:queued', {
318
+ jobId: job.id,
319
+ executionId,
320
+ queueLength: this.pendingQueue.length,
321
+ });
322
+ return;
323
+ }
324
+ // Execute immediately
325
+ this.executeJobAsync(job, executionId);
326
+ }
327
+ /**
328
+ * Execute job asynchronously
329
+ */
330
+ executeJobAsync(job, executionId, metadata) {
331
+ // Execute in background
332
+ this.executeJob(job, metadata, executionId).catch(error => {
333
+ this.logger.error(`Unhandled error in job execution: ${job.name}`, this.loggerContext, {
334
+ error,
335
+ });
336
+ });
337
+ }
338
+ /**
339
+ * Execute job with full lifecycle management
340
+ */
341
+ async executeJob(job, metadata, executionId) {
342
+ const execId = executionId || this.generateExecutionId();
343
+ this.currentConcurrentJobs++;
344
+ job.concurrentExecutions++;
345
+ const context = {
346
+ jobId: job.id,
347
+ executionId: execId,
348
+ attempt: 1,
349
+ startTime: new Date(),
350
+ metadata: { ...job.options.metadata, ...metadata },
351
+ };
352
+ try {
353
+ // Start execution tracking
354
+ this.stateManager.startExecution(job.id, execId, context.metadata);
355
+ this.logger.info(`Executing job: ${job.name} (${execId})`, this.loggerContext);
356
+ this.emit('job:start', { jobId: job.id, executionId: execId, context });
357
+ // Call onStart hook
358
+ if (job.options.onStart) {
359
+ await Promise.resolve(job.options.onStart(context));
360
+ }
361
+ // Execute with executor (handles retry, timeout, circuit breaker)
362
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
363
+ const executorOptions = {
364
+ timeout: job.options.timeout,
365
+ maxRetries: job.options.maxRetries,
366
+ retryDelay: job.options.retryDelay,
367
+ retryBackoff: job.options.retryBackoff,
368
+ enableCircuitBreaker: job.options.enableCircuitBreaker,
369
+ };
370
+ const result = await this.executor.execute(job.id, execId, job.fn, context);
371
+ if (result.success) {
372
+ // End execution tracking
373
+ this.stateManager.endExecution(execId, 'completed');
374
+ this.logger.info(`Job completed: ${job.name} (${execId})`, this.loggerContext, {
375
+ duration: result.duration,
376
+ attempts: result.attempts,
377
+ });
378
+ this.emit('job:complete', {
379
+ jobId: job.id,
380
+ executionId: execId,
381
+ result: result.value,
382
+ duration: result.duration,
383
+ });
384
+ // Call onComplete hook
385
+ if (job.options.onComplete) {
386
+ await Promise.resolve(job.options.onComplete(context, result.value));
387
+ }
388
+ }
389
+ else {
390
+ // End execution tracking with error
391
+ const status = result.timedOut ? 'timeout' : 'failed';
392
+ this.stateManager.endExecution(execId, status, result.error);
393
+ this.logger.error(`Job failed: ${job.name} (${execId})`, this.loggerContext, {
394
+ error: result.error?.message,
395
+ duration: result.duration,
396
+ attempts: result.attempts,
397
+ timedOut: result.timedOut,
398
+ circuitBreakerTripped: result.circuitBreakerTripped,
399
+ });
400
+ this.emit('job:error', {
401
+ jobId: job.id,
402
+ executionId: execId,
403
+ error: result.error,
404
+ duration: result.duration,
405
+ timedOut: result.timedOut,
406
+ });
407
+ // Call onError hook
408
+ if (job.options.onError && result.error) {
409
+ await Promise.resolve(job.options.onError(context, result.error));
410
+ }
411
+ }
412
+ return result;
413
+ }
414
+ finally {
415
+ this.currentConcurrentJobs--;
416
+ job.concurrentExecutions--;
417
+ // Schedule next run (for recurring jobs)
418
+ if (job.schedule.type !== 'oneTime') {
419
+ job.nextRun = this.calculateNextRun(job);
420
+ if (job.enabled && this.isLeader()) {
421
+ this.scheduleJob(job);
422
+ }
423
+ }
424
+ else {
425
+ // One-time job, disable it
426
+ job.enabled = false;
427
+ this.stateManager.setJobEnabled(job.id, false);
428
+ }
429
+ // Process pending queue
430
+ this.processPendingQueue();
431
+ }
432
+ }
433
+ /**
434
+ * Process pending queue
435
+ */
436
+ processPendingQueue() {
437
+ if (this.pendingQueue.length === 0) {
438
+ return;
439
+ }
440
+ // Sort by priority (higher first)
441
+ this.pendingQueue.sort((a, b) => b.job.priority - a.job.priority);
442
+ while (this.pendingQueue.length > 0 && this.currentConcurrentJobs < this.maxConcurrentJobs) {
443
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
444
+ const item = this.pendingQueue.shift();
445
+ const { job, executionId } = item;
446
+ // Check per-job concurrency limit
447
+ const maxConcurrent = job.options.maxConcurrent ?? 1;
448
+ if (job.concurrentExecutions < maxConcurrent) {
449
+ this.executeJobAsync(job, executionId);
450
+ }
451
+ else {
452
+ // Put back in queue
453
+ this.pendingQueue.unshift(item);
454
+ break;
455
+ }
456
+ }
457
+ }
458
+ /**
459
+ * Check if this instance is the leader
460
+ */
461
+ isLeader() {
462
+ if (!this.leaderElection) {
463
+ return true; // No leader election, always leader
464
+ }
465
+ return this.leaderElection.isCurrentLeader();
466
+ }
467
+ /**
468
+ * Generate unique job ID
469
+ */
470
+ generateJobId() {
471
+ return `job_${Date.now()}_${randomBytes(8).toString('hex')}`;
472
+ }
473
+ /**
474
+ * Generate unique execution ID
475
+ */
476
+ generateExecutionId() {
477
+ return `exec_${Date.now()}_${randomBytes(8).toString('hex')}`;
478
+ }
479
+ /**
480
+ * Get scheduler stats
481
+ */
482
+ getStats() {
483
+ return {
484
+ totalJobs: this.jobs.size,
485
+ enabledJobs: Array.from(this.jobs.values()).filter(j => j.enabled).length,
486
+ runningJobs: this.currentConcurrentJobs,
487
+ queuedJobs: this.pendingQueue.length,
488
+ isLeader: this.isLeader(),
489
+ isStarted: this.started,
490
+ };
491
+ }
492
+ /**
493
+ * Get job state
494
+ */
495
+ getJobState(jobId) {
496
+ return this.stateManager.getState(jobId);
497
+ }
498
+ /**
499
+ * Get job history
500
+ */
501
+ getJobHistory(jobId, limit) {
502
+ return this.stateManager.getHistory(jobId, limit);
503
+ }
504
+ /**
505
+ * Get job metrics
506
+ */
507
+ getJobMetrics(jobId) {
508
+ return this.stateManager.getMetrics(jobId);
509
+ }
510
+ /**
511
+ * Graceful shutdown
512
+ */
513
+ async shutdown() {
514
+ if (this.isShuttingDown) {
515
+ return;
516
+ }
517
+ this.logger.info('JobScheduler shutting down...', this.loggerContext, {
518
+ runningJobs: this.currentConcurrentJobs,
519
+ queuedJobs: this.pendingQueue.length,
520
+ });
521
+ this.isShuttingDown = true;
522
+ // Unschedule all jobs
523
+ this.unscheduleAllJobs();
524
+ // Clear pending queue
525
+ this.pendingQueue = [];
526
+ // Wait for running jobs to complete
527
+ const startTime = Date.now();
528
+ while (this.currentConcurrentJobs > 0 &&
529
+ Date.now() - startTime < this.gracefulShutdownTimeout) {
530
+ this.logger.debug(`Waiting for ${this.currentConcurrentJobs} running jobs to complete`, this.loggerContext);
531
+ await this.sleep(1000);
532
+ }
533
+ if (this.currentConcurrentJobs > 0) {
534
+ this.logger.warn(`Forcing shutdown with ${this.currentConcurrentJobs} jobs still running`, this.loggerContext);
535
+ }
536
+ // Shutdown components
537
+ await Promise.all([
538
+ this.executor.shutdown(5000),
539
+ this.stateManager.shutdown(),
540
+ this.leaderElection?.shutdown(),
541
+ ]);
542
+ this.started = false;
543
+ this.removeAllListeners();
544
+ this.logger.info('JobScheduler shutdown complete', this.loggerContext);
545
+ this.emit('scheduler:shutdown');
546
+ }
547
+ sleep(ms) {
548
+ return new Promise(resolve => setTimeout(resolve, ms));
549
+ }
550
+ }
551
+ //# sourceMappingURL=job-scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-scheduler.js","sourceRoot":"","sources":["../../../src/core/jobs/job-scheduler.ts"],"names":[],"mappings":"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"}