@cleverbrush/scheduler 1.0.0-beta.0 → 1.0.0-beta.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleverbrush/scheduler",
3
- "version": "1.0.0-beta.0",
3
+ "version": "1.0.0-beta.2",
4
4
  "keywords": [
5
5
  "task scheduler"
6
6
  ],
@@ -17,7 +17,7 @@
17
17
  "url": "github:cleverbrush/libs"
18
18
  },
19
19
  "dependencies": {
20
- "@cleverbrush/schema": "1.0.0-beta.0"
20
+ "@cleverbrush/schema": "1.0.0-beta.2"
21
21
  },
22
22
  "types": "./dist/index.d.ts"
23
23
  }
package/src/index.ts CHANGED
@@ -26,8 +26,10 @@ export { ScheduleCalculator, Schedule as TaskSchedule, Schemas };
26
26
  type WorkerResult = {
27
27
  status: JobInstanceStatus;
28
28
  exitCode: number;
29
+ error?: Error;
29
30
  };
30
31
 
32
+ const MAX_BUFFER_SIZE = 10 * 1024 * 1024; // 10MB
31
33
  const CHECK_INTERVAL = 1000 * 10; // every 10 seconds
32
34
  // const SCHEDULE_JOB_SPAN = 1000 * 60 * 60; // 1 hour
33
35
  const SCHEDULE_JOB_SPAN = 1000 * 60; // 1 hour
@@ -46,13 +48,22 @@ type JobEndItem = JobStartItem & {
46
48
  endDate: Date;
47
49
  };
48
50
 
51
+ type JobErrorItem = JobStartItem & {
52
+ endDate: Date;
53
+ error?: Error;
54
+ };
55
+
49
56
  type Events = {
50
57
  'job:start': (job: JobStartItem) => any;
51
58
  'job:end': (job: JobEndItem) => any;
59
+ 'job:error': (job: JobErrorItem) => any;
60
+ 'job:timeout': (job: JobErrorItem) => any;
52
61
  };
53
62
 
54
63
  interface IJobScheduler {
55
64
  on<T extends keyof Events>(name: T, callback: Events[T]): this;
65
+ addJob(job: CreateJobRequest): Promise<void>;
66
+ removeJob(id: string): Promise<void>;
56
67
  }
57
68
 
58
69
  export class JobScheduler extends EventEmitter implements IJobScheduler {
@@ -110,6 +121,7 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
110
121
  const promise = new Promise<WorkerResult>((resolve) => {
111
122
  let timedOut = false;
112
123
  let isFinished = false;
124
+ let error;
113
125
 
114
126
  const timeoutTimer = setTimeout(() => {
115
127
  if (isFinished) return;
@@ -121,7 +133,9 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
121
133
  });
122
134
  }, timeout);
123
135
 
124
- worker.on('error', (e) => e);
136
+ worker.on('error', (e) => {
137
+ error = e;
138
+ });
125
139
 
126
140
  worker.on('exit', (exitCode) => {
127
141
  if (isFinished) return;
@@ -130,7 +144,8 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
130
144
  isFinished = true;
131
145
  resolve({
132
146
  status: exitCode === 0 ? 'succeeded' : 'errored',
133
- exitCode
147
+ exitCode,
148
+ error
134
149
  });
135
150
  });
136
151
  });
@@ -184,16 +199,38 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
184
199
  job.timeout
185
200
  );
186
201
 
187
- const stdOutPass = new PassThrough();
188
- stdout.pipe(stdOutPass);
189
- const stdErrPass = new PassThrough();
190
- stderr.pipe(stdErrPass);
202
+ const stdOutPass = stdout.pipe(
203
+ new PassThrough({
204
+ highWaterMark: MAX_BUFFER_SIZE
205
+ })
206
+ );
207
+ const stdErrPass = stderr.pipe(
208
+ new PassThrough({
209
+ highWaterMark: MAX_BUFFER_SIZE
210
+ })
211
+ );
191
212
 
192
- const stdOutForJobStart = stdout.pipe(new PassThrough());
193
- const stdErrForJobStart = stderr.pipe(new PassThrough());
213
+ const stdOutForJobStart = stdout.pipe(
214
+ new PassThrough({
215
+ highWaterMark: MAX_BUFFER_SIZE
216
+ })
217
+ );
218
+ const stdErrForJobStart = stderr.pipe(
219
+ new PassThrough({
220
+ highWaterMark: MAX_BUFFER_SIZE
221
+ })
222
+ );
194
223
 
195
- const stdOutForJobEnd = stdout.pipe(new PassThrough());
196
- const stdErrForJobEnd = stderr.pipe(new PassThrough());
224
+ const stdOutForJobEnd = stdout.pipe(
225
+ new PassThrough({
226
+ highWaterMark: MAX_BUFFER_SIZE
227
+ })
228
+ );
229
+ const stdErrForJobEnd = stderr.pipe(
230
+ new PassThrough({
231
+ highWaterMark: MAX_BUFFER_SIZE
232
+ })
233
+ );
197
234
 
198
235
  this.emit('job:start', {
199
236
  instanceId: instance.id,
@@ -209,17 +246,43 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
209
246
  const result = await promise;
210
247
  status = result.status;
211
248
  exitCode = result.exitCode;
249
+ const { error } = result;
212
250
 
213
251
  const endDate = new Date();
214
252
 
215
- this.emit('job:end', {
216
- instanceId: instance.id,
217
- jobId: job.id,
218
- stderr: stdErrForJobEnd,
219
- stdout: stdOutForJobEnd,
220
- startDate,
221
- endDate
222
- } as JobStartItem);
253
+ switch (status) {
254
+ case 'errored':
255
+ this.emit('job:error', {
256
+ instanceId: instance.id,
257
+ jobId: job.id,
258
+ stderr: stdErrForJobEnd,
259
+ stdout: stdOutForJobEnd,
260
+ startDate,
261
+ endDate,
262
+ error
263
+ } as JobErrorItem);
264
+ break;
265
+ case 'timedout':
266
+ this.emit('job:timeout', {
267
+ instanceId: instance.id,
268
+ jobId: job.id,
269
+ stderr: stdErrForJobEnd,
270
+ stdout: stdOutForJobEnd,
271
+ startDate,
272
+ endDate,
273
+ error
274
+ } as JobErrorItem);
275
+ break;
276
+ default:
277
+ this.emit('job:end', {
278
+ instanceId: instance.id,
279
+ jobId: job.id,
280
+ stderr: stdErrForJobEnd,
281
+ stdout: stdOutForJobEnd,
282
+ startDate,
283
+ endDate
284
+ } as JobStartItem);
285
+ }
223
286
 
224
287
  instance = await this._jobsRepository.saveInstance({
225
288
  ...instance,
@@ -241,7 +304,10 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
241
304
  const schedule = await this.getJobSchedule(job);
242
305
 
243
306
  if (status !== 'succeeded') {
244
- if (job.consequentFailsCount + 1 >= job.maxConsequentFails) {
307
+ if (
308
+ job.consequentFailsCount + 1 >= job.maxConsequentFails &&
309
+ job.maxConsequentFails > 0
310
+ ) {
245
311
  job.status = 'disabled';
246
312
  } else {
247
313
  job.consequentFailsCount += 1;
@@ -286,7 +352,7 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
286
352
 
287
353
  timer = setTimeout(async () => {
288
354
  const actualJob = await this._jobsRepository.getJobById(job.id);
289
- if (actualJob.status !== 'active') {
355
+ if (!actualJob || actualJob.status !== 'active') {
290
356
  instance.status = 'canceled';
291
357
  await this._jobsRepository.saveInstance(instance);
292
358
  return;
@@ -319,6 +385,8 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
319
385
 
320
386
  while (schedule.hasNext(SCHEDULE_JOB_SPAN)) {
321
387
  const { date: nextRun, index } = schedule.next();
388
+ if (nextRun < new Date()) continue;
389
+
322
390
  const alreadyScheduled = scheduledInstances.find(
323
391
  (i) => i.index === index
324
392
  );
@@ -359,6 +427,18 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
359
427
  // TODO: add logic
360
428
  }
361
429
 
430
+ public async jobExists(jobId: string): Promise<boolean> {
431
+ return (await this._jobsRepository.getJobById(jobId)) !== null;
432
+ }
433
+
434
+ public async removeJob(jobId: string): Promise<void> {
435
+ if (typeof jobId !== 'string' || !jobId) {
436
+ throw new Error('id is required');
437
+ }
438
+
439
+ await this._jobsRepository.removeJob(jobId);
440
+ }
441
+
362
442
  public async addJob(job: CreateJobRequest) {
363
443
  const validationResult =
364
444
  await schemaRegistry.schemas.Models.CreateJobRequest.validate(job);
@@ -7,6 +7,7 @@ export interface IJobRepository {
7
7
  getJobs(): Promise<Job[]>;
8
8
  getJobById(jobId: string): Promise<Job>;
9
9
  createJob(item: AddJobRequest): Promise<Job>;
10
+ removeJob(jobId: string): Promise<void>;
10
11
 
11
12
  saveJob(job: Job): Promise<Job>;
12
13
 
@@ -36,6 +37,12 @@ export class InMemoryJobRepository implements IJobRepository {
36
37
  return this._jobs;
37
38
  }
38
39
 
40
+ async removeJob(jobId: string) {
41
+ const job = this.getJobById(jobId);
42
+ if (!job) throw new Error(`job with id ${jobId} doesn't exist`);
43
+ this._jobs = this._jobs.filter((j) => j.id !== jobId);
44
+ }
45
+
39
46
  async createJob(item: AddJobRequest): Promise<Job> {
40
47
  const job: Job = {
41
48
  ...item,
package/src/types.ts CHANGED
@@ -62,8 +62,8 @@ const registry = new SchemaRegistry()
62
62
  .addSchemaFrom(
63
63
  'Templates.Schedule',
64
64
  'Models.TaskScheduleMinute',
65
- ({ string, schema }) =>
66
- schema
65
+ ({ string, base }) =>
66
+ base
67
67
  .removeProp('hour')
68
68
  .removeProp('minute')
69
69
  .addProps({
@@ -74,8 +74,8 @@ const registry = new SchemaRegistry()
74
74
  .addSchemaFrom(
75
75
  'Templates.Schedule',
76
76
  'Models.TaskScheduleDay',
77
- ({ string, schema }) =>
78
- schema.addProps({
77
+ ({ string, base }) =>
78
+ base.addProps({
79
79
  /** Repeat every day */
80
80
  every: string('day')
81
81
  })
@@ -83,8 +83,8 @@ const registry = new SchemaRegistry()
83
83
  .addSchemaFrom(
84
84
  'Templates.Schedule',
85
85
  'Models.TaskScheduleWeek',
86
- ({ schema, number, string, array }) =>
87
- schema.addProps({
86
+ ({ base, number, string, array }) =>
87
+ base.addProps({
88
88
  /** Repeat every week */
89
89
  every: string('week'),
90
90
  /** Day of week: array of no more than 7 numbers numbers (from 1 to 7 where 1 is Monday). */
@@ -112,8 +112,8 @@ const registry = new SchemaRegistry()
112
112
  .addSchemaFrom(
113
113
  'Templates.Schedule',
114
114
  'Models.TaskScheduleMonth',
115
- ({ schema, string, number, union }) =>
116
- schema.addProps({
115
+ ({ base, string, number, union }) =>
116
+ base.addProps({
117
117
  /** Repeat every month */
118
118
  every: string('month'),
119
119
  /** Day - 'last' or number from 1 to 28 */
@@ -123,8 +123,8 @@ const registry = new SchemaRegistry()
123
123
  .addSchemaFrom(
124
124
  'Templates.Schedule',
125
125
  'Models.TaskScheduleYear',
126
- ({ schema, string, number, union }) =>
127
- schema.addProps({
126
+ ({ base, string, number, union }) =>
127
+ base.addProps({
128
128
  /** Repeat every year */
129
129
  every: string('year'),
130
130
  /** Day - 'last' or number from 1 to 28 */
@@ -158,8 +158,10 @@ export const schemaRegistry = registry
158
158
  timeout: number().min(0).optional(),
159
159
  /** Arbitrary props for job (can be a callback returning props or Promise<props>) */
160
160
  props: union(object().canHaveUnknownProps(), func()).optional(),
161
- /** Job will be considered as disabled when more than that count of runs fails consequently */
162
- maxConsequentFails: number().min(0).optional()
161
+ /** Job will be considered as disabled when more than that count of runs fails consequently
162
+ * unlimited if negative
163
+ */
164
+ maxConsequentFails: number().optional()
163
165
  })
164
166
  );
165
167
 
@@ -1,9 +0,0 @@
1
- /// <reference types="node" />
2
- /// <reference types="node" />
3
- import { Readable } from 'stream';
4
- export declare class CloneReadableStream extends Readable {
5
- private _chunks;
6
- constructor(source: Readable);
7
- toBuffer(): Buffer;
8
- _read(): void;
9
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"CloneReadableStream.d.ts","sourceRoot":"","sources":["../src/CloneReadableStream.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,qBAAa,mBAAoB,SAAQ,QAAQ;IAC7C,OAAO,CAAC,OAAO,CAAM;gBAET,MAAM,EAAE,QAAQ;IAarB,QAAQ,IAAI,MAAM;IAKzB,KAAK;CACR"}
@@ -1,25 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CloneReadableStream = void 0;
4
- const stream_1 = require("stream");
5
- class CloneReadableStream extends stream_1.Readable {
6
- _chunks = [];
7
- constructor(source) {
8
- super();
9
- if (!source)
10
- throw new Error('source is required');
11
- source.on('data', (chunk) => {
12
- this.push(chunk);
13
- this._chunks.push(chunk);
14
- });
15
- source.on('end', () => this.push(null));
16
- source.on('error', (err) => this.emit('error', err));
17
- }
18
- toBuffer() {
19
- return Buffer.concat(this._chunks);
20
- }
21
- // eslint-disable-next-line
22
- _read() { }
23
- }
24
- exports.CloneReadableStream = CloneReadableStream;
25
- //# sourceMappingURL=CloneReadableStream.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CloneReadableStream.js","sourceRoot":"","sources":["../src/CloneReadableStream.ts"],"names":[],"mappings":";;;AAAA,mCAAkC;AAElC,MAAa,mBAAoB,SAAQ,iBAAQ;IACrC,OAAO,GAAG,EAAE,CAAC;IAErB,YAAY,MAAgB;QACxB,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QAEnD,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACxB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;IAEM,QAAQ;QACX,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IAED,2BAA2B;IAC3B,KAAK,KAAI,CAAC;CACb;AAtBD,kDAsBC"}
@@ -1,10 +0,0 @@
1
- import { Schedule } from './types.js';
2
- export declare class ScheduleCalculator {
3
- #private;
4
- constructor(schedule: Schedule);
5
- hasNext(span?: number): boolean;
6
- next(): {
7
- date: Date;
8
- index: number;
9
- };
10
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"ScheduleCalculator.d.ts","sourceRoot":"","sources":["../src/ScheduleCalculator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAiBtC,qBAAa,kBAAkB;;gBAWf,QAAQ,EAAE,QAAQ;IA+PvB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO;IAY/B,IAAI,IAAI;QACX,IAAI,EAAE,IAAI,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;KACjB;CA0BJ"}
@@ -1,208 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ScheduleCalculator = void 0;
4
- const MS_IN_DAY = 1000 * 60 * 60 * 24;
5
- const MS_IN_WEEK = MS_IN_DAY * 7;
6
- const getDayOfWeek = (date) => {
7
- const res = date.getUTCDay();
8
- if (res === 0)
9
- return 7;
10
- return res;
11
- };
12
- const getNumberOfDaysInMonth = (date) => {
13
- return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 0, 0, 0, 0, 0)).getDate();
14
- };
15
- class ScheduleCalculator {
16
- #schedule;
17
- #currentDate = new Date();
18
- #hour = 9;
19
- #minute = 0;
20
- #maxRepeat = -1;
21
- #repeatCount = 0;
22
- #hasNext = false;
23
- #next;
24
- constructor(schedule) {
25
- if (!schedule)
26
- throw new Error('schedule is required');
27
- this.#schedule = { ...schedule };
28
- if (typeof schedule.startsOn !== 'undefined') {
29
- this.#currentDate = schedule.startsOn;
30
- }
31
- else {
32
- this.#schedule.startsOn = new Date();
33
- this.#currentDate = this.#schedule.startsOn;
34
- }
35
- if (schedule.every !== 'minute') {
36
- if (typeof schedule.hour === 'number') {
37
- this.#hour = schedule.hour;
38
- }
39
- if (typeof schedule.minute === 'number') {
40
- this.#minute = schedule.minute;
41
- }
42
- if (schedule.every === 'day' &&
43
- new Date(Date.UTC(this.#currentDate.getUTCFullYear(), this.#currentDate.getUTCMonth(), this.#currentDate.getUTCDate(), this.#hour, this.#minute, 0, 0)).getTime() < this.#currentDate.getTime()) {
44
- const date = new Date(Date.UTC(this.#currentDate.getUTCFullYear(), this.#currentDate.getUTCMonth(), this.#currentDate.getUTCDate() + 1, this.#hour, this.#minute, 0, 0));
45
- this.#currentDate = date;
46
- }
47
- }
48
- if (typeof schedule.maxOccurences === 'number') {
49
- this.#maxRepeat = schedule.maxOccurences;
50
- }
51
- const next = this.#getNext();
52
- if (typeof next !== 'undefined') {
53
- this.#next = next;
54
- this.#hasNext = true;
55
- }
56
- let leftToSkip = this.#schedule.startingFromIndex || 1;
57
- while (leftToSkip-- > 1 && this.#hasNext) {
58
- this.next();
59
- }
60
- }
61
- #getNext() {
62
- let candidate = null;
63
- let dayOfWeek;
64
- switch (this.#schedule.every) {
65
- case 'minute':
66
- candidate =
67
- this.#repeatCount === 0
68
- ? this.#schedule.startsOn
69
- : new Date(Date.UTC(this.#currentDate.getUTCFullYear(), this.#currentDate.getUTCMonth(), this.#currentDate.getUTCDate(), this.#currentDate.getUTCHours(), this.#currentDate.getUTCMinutes() +
70
- this.#schedule.interval, this.#currentDate.getUTCSeconds(), this.#currentDate.getUTCMilliseconds()));
71
- break;
72
- case 'day':
73
- {
74
- const date = new Date(this.#currentDate.getTime() +
75
- MS_IN_DAY *
76
- (this.#repeatCount === 0
77
- ? 0
78
- : this.#schedule.interval - 1));
79
- candidate = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), this.#hour, this.#minute, 0, 0));
80
- }
81
- break;
82
- case 'week':
83
- {
84
- let date = this.#currentDate;
85
- do {
86
- let found = false;
87
- dayOfWeek = getDayOfWeek(date);
88
- if (Number.isNaN(dayOfWeek))
89
- return;
90
- for (let i = 0; i < 7 - dayOfWeek + 1; i++) {
91
- date = new Date(date.getTime() + (i == 0 ? 0 : MS_IN_DAY));
92
- if (this.#schedule.endsOn &&
93
- date > this.#schedule.endsOn) {
94
- return;
95
- }
96
- if (this.#schedule.dayOfWeek.includes(getDayOfWeek(date))) {
97
- const dateWithTime = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), this.#hour, this.#minute, 0, 0));
98
- if (dateWithTime > this.#schedule.startsOn) {
99
- candidate = dateWithTime;
100
- found = true;
101
- break;
102
- }
103
- }
104
- }
105
- if (found)
106
- break;
107
- date = new Date(date.getTime() +
108
- MS_IN_DAY +
109
- (this.#repeatCount == 0
110
- ? 0
111
- : (this.#schedule.interval - 1) *
112
- MS_IN_WEEK));
113
- } while ((this.#schedule.endsOn &&
114
- date <= this.#schedule.endsOn) ||
115
- !this.#schedule.endsOn);
116
- }
117
- break;
118
- case 'month':
119
- {
120
- let dateTime;
121
- const cDate = this.#currentDate;
122
- let iteration = 0;
123
- do {
124
- const date = this.#schedule.day === 'last'
125
- ? getNumberOfDaysInMonth(new Date(Date.UTC(cDate.getUTCFullYear(), cDate.getUTCMonth() +
126
- iteration *
127
- (this.#repeatCount === 0
128
- ? 1
129
- : this.#schedule
130
- .interval), 1, 0, 0, 0, 0)))
131
- : this.#schedule.day;
132
- dateTime = new Date(Date.UTC(cDate.getUTCFullYear(), cDate.getUTCMonth() +
133
- iteration *
134
- (this.#repeatCount === 0
135
- ? 1
136
- : this.#schedule.interval), date, this.#hour, this.#minute, 0, 0));
137
- iteration++;
138
- } while (dateTime < this.#schedule.startsOn ||
139
- dateTime <= this.#currentDate);
140
- candidate = dateTime;
141
- }
142
- break;
143
- case 'year':
144
- {
145
- let dateTime;
146
- const cDate = this.#currentDate;
147
- let iteration = 0;
148
- do {
149
- const date = this.#schedule.day === 'last'
150
- ? getNumberOfDaysInMonth(new Date(Date.UTC(cDate.getUTCFullYear() +
151
- iteration *
152
- (this.#repeatCount === 0
153
- ? 1
154
- : this.#schedule
155
- .interval), this.#schedule.month - 1, 1, 0, 0, 0, 0)))
156
- : this.#schedule.day;
157
- dateTime = new Date(Date.UTC(cDate.getUTCFullYear() +
158
- iteration *
159
- (this.#repeatCount === 0
160
- ? 1
161
- : this.#schedule.interval), this.#schedule.month - 1, date, this.#hour, this.#minute, 0, 0));
162
- iteration++;
163
- } while (dateTime < this.#schedule.startsOn ||
164
- dateTime <= this.#currentDate);
165
- candidate = dateTime;
166
- }
167
- break;
168
- default:
169
- throw new Error('unknown schedule type');
170
- }
171
- if (!candidate)
172
- return;
173
- if (typeof this.#schedule.endsOn !== 'undefined' &&
174
- candidate > this.#schedule.endsOn) {
175
- return;
176
- }
177
- return candidate;
178
- }
179
- hasNext(span) {
180
- if (!this.#hasNext) {
181
- return false;
182
- }
183
- if (typeof span !== 'number')
184
- return this.#hasNext;
185
- return this.#next.getTime() - new Date().getTime() <= span;
186
- }
187
- next() {
188
- if (!this.#hasNext)
189
- throw new Error('schedule is over');
190
- const result = this.#next;
191
- this.#currentDate = new Date(result.getTime() +
192
- (['day', 'week'].includes(this.#schedule.every) ? MS_IN_DAY : 0));
193
- this.#repeatCount++;
194
- const next = this.#getNext();
195
- this.#next = next;
196
- this.#hasNext = typeof next !== 'undefined';
197
- if (this.#maxRepeat > 0 && this.#repeatCount >= this.#maxRepeat) {
198
- this.#next = undefined;
199
- this.#hasNext = false;
200
- }
201
- return {
202
- date: result,
203
- index: this.#repeatCount
204
- };
205
- }
206
- }
207
- exports.ScheduleCalculator = ScheduleCalculator;
208
- //# sourceMappingURL=ScheduleCalculator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ScheduleCalculator.js","sourceRoot":"","sources":["../src/ScheduleCalculator.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts DELETED
@@ -1,55 +0,0 @@
1
- /// <reference types="node" />
2
- /// <reference types="node" />
3
- import { EventEmitter } from 'events';
4
- import { Readable } from 'stream';
5
- import { JobSchedulerProps, CreateJobRequest, SchedulerStatus, Schedule, Job, JobInstance, JobInstanceStatus, Schemas } from './types.js';
6
- import { ScheduleCalculator } from './ScheduleCalculator.js';
7
- import { IJobRepository } from './jobRepository.js';
8
- export { ScheduleCalculator, Schedule as TaskSchedule, Schemas };
9
- declare type WorkerResult = {
10
- status: JobInstanceStatus;
11
- exitCode: number;
12
- };
13
- declare type JobStartItem = {
14
- jobId: string;
15
- instanceId: number;
16
- stdout: Readable;
17
- stderr: Readable;
18
- startDate: Date;
19
- };
20
- declare type JobEndItem = JobStartItem & {
21
- endDate: Date;
22
- };
23
- declare type Events = {
24
- 'job:start': (job: JobStartItem) => any;
25
- 'job:end': (job: JobEndItem) => any;
26
- };
27
- interface IJobScheduler {
28
- on<T extends keyof Events>(name: T, callback: Events[T]): this;
29
- }
30
- export declare class JobScheduler extends EventEmitter implements IJobScheduler {
31
- protected _rootFolder: string;
32
- protected _status: SchedulerStatus;
33
- protected _defaultTimezone: string;
34
- protected _checkTimer: any;
35
- protected _jobsRepository: IJobRepository;
36
- protected _jobProps: Map<string, any>;
37
- get status(): SchedulerStatus;
38
- protected set status(val: SchedulerStatus);
39
- private scheduleCalculatorCache;
40
- protected getJobSchedule(job: Job): Promise<ScheduleCalculator>;
41
- protected runWorkerWithTimeout(file: string, props: any, timeout: number): {
42
- promise: Promise<WorkerResult>;
43
- stderr: Readable;
44
- stdout: Readable;
45
- };
46
- private readToEnd;
47
- protected startJobInstance(instance: JobInstance): Promise<void>;
48
- protected scheduleJobTo(job: Job, date: Date, index: number): Promise<JobInstance | null>;
49
- protected checkForUpcomingJobs(): Promise<void>;
50
- start(): Promise<void>;
51
- stop(): void;
52
- addJob(job: CreateJobRequest): Promise<void>;
53
- constructor(props: JobSchedulerProps);
54
- on<T extends keyof Events>(name: T, callback: Events[T]): this;
55
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAe,MAAM,QAAQ,CAAC;AAO/C,OAAO,EAEH,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,GAAG,EACH,WAAW,EACX,iBAAiB,EACpB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAyB,MAAM,oBAAoB,CAAC;AAE3E,aAAK,YAAY,GAAG;IAChB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CACpB,CAAC;AAQF,aAAK,YAAY,GAAG;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,QAAQ,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;CACnB,CAAC;AAEF,aAAK,UAAU,GAAG,YAAY,GAAG;IAC7B,OAAO,EAAE,IAAI,CAAC;CACjB,CAAC;AAEF,aAAK,MAAM,GAAG;IACV,WAAW,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,GAAG,CAAC;IACxC,SAAS,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,GAAG,CAAC;CACvC,CAAC;AAEF,UAAU,aAAa;IACnB,EAAE,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;CAClE;AAED,qBAAa,YAAa,SAAQ,YAAa,YAAW,aAAa;IACnE,SAAS,CAAC,WAAW,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,OAAO,EAAE,eAAe,CAAa;IAC/C,SAAS,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAEnC,SAAS,CAAC,WAAW,MAAC;IAEtB,SAAS,CAAC,eAAe,EAAE,cAAc,CAA+B;IAExE,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAA0B;IAE/D,IAAW,MAAM,IAIS,eAAe,CAFxC;IAED,SAAS,KAAK,MAAM,CAAC,GAAG,EAAE,eAAe,EAGxC;cAEe,cAAc,CAAC,GAAG,EAAE,GAAG;IAgBvC,SAAS,CAAC,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM;;;;;IA0CxE,OAAO,CAAC,SAAS;cASD,gBAAgB,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;cAgHtD,aAAa,CACzB,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;cAoCd,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BxC,KAAK;IAeX,IAAI;IAWE,MAAM,CAAC,GAAG,EAAE,gBAAgB;gBAgC7B,KAAK,EAAE,iBAAiB;IAqB7B,EAAE,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI;CAIxE"}