@cleverbrush/scheduler 1.0.0-beta.3 → 1.0.0-beta.5

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/types.js ADDED
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Schemas = exports.schemaRegistry = void 0;
4
+ const schema_1 = require("@cleverbrush/schema");
5
+ const registry = new schema_1.SchemaRegistry()
6
+ .addPreprocessor('StringToDate', (value) => {
7
+ if (typeof value === 'undefined')
8
+ return value;
9
+ if (typeof value === 'string') {
10
+ const time = Date.parse(value);
11
+ if (Number.isNaN(time))
12
+ return value;
13
+ return new Date(time);
14
+ }
15
+ return value;
16
+ })
17
+ .addSchema('Common.Date', ({ object }) => object()
18
+ .mapToType()
19
+ .addValidator((value) => value instanceof Date && !Number.isNaN(value)
20
+ ? {
21
+ valid: true
22
+ }
23
+ : {
24
+ valid: false,
25
+ errors: ['should be a valid Date object']
26
+ }))
27
+ .addSchema('Templates.Schedule', ({ object, number, alias }) => object({
28
+ /** Number of days between repeats */
29
+ interval: number().min(1).max(356),
30
+ /** Hour (0-23) */
31
+ hour: number().min(0).max(23).optional(),
32
+ /** Minute (0-59) */
33
+ minute: number().min(0).max(59).optional(),
34
+ /** Do not start earlier than this date */
35
+ startsOn: alias('Common.Date').optional(),
36
+ /** Do not repeat after this date */
37
+ endsOn: alias('Common.Date').optional(),
38
+ /** Max number of repeats (min 1) */
39
+ maxOccurences: number().min(1).optional(),
40
+ /** Skip this number of repeats. Min value is 1. */
41
+ skipFirst: number().min(1).optional()
42
+ })
43
+ .setPropPreprocessor('endsOn', 'StringToDate')
44
+ .addValidator((val) => {
45
+ if ('endsOn' in val &&
46
+ 'maxOccurences' in val &&
47
+ // TODO: remove this clause when object validator is fixed in a new version
48
+ typeof val.endsOf !== 'undefined') {
49
+ return {
50
+ valid: false,
51
+ errors: ['either endsOn or maxOccurences is required']
52
+ };
53
+ }
54
+ return { valid: true };
55
+ }))
56
+ .addSchemaFrom('Templates.Schedule', 'Models.TaskScheduleMinute', ({ string, base }) => base
57
+ .removeProp('hour')
58
+ .removeProp('minute')
59
+ .addProps({
60
+ /** Repeat every minute */
61
+ every: string('minute')
62
+ }))
63
+ .addSchemaFrom('Templates.Schedule', 'Models.TaskScheduleDay', ({ string, base }) => base.addProps({
64
+ /** Repeat every day */
65
+ every: string('day')
66
+ }))
67
+ .addSchemaFrom('Templates.Schedule', 'Models.TaskScheduleWeek', ({ base, number, string, array }) => base.addProps({
68
+ /** Repeat every week */
69
+ every: string('week'),
70
+ /** Day of week: array of no more than 7 numbers numbers (from 1 to 7 where 1 is Monday). */
71
+ dayOfWeek: array()
72
+ .ofType(number().min(1).max(7))
73
+ .minLength(1)
74
+ .maxLength(7)
75
+ .addValidator((val) => {
76
+ const map = {};
77
+ for (let i = 0; i < val.length; i++) {
78
+ if (map[val[i]]) {
79
+ return {
80
+ valid: false,
81
+ errors: ['no duplicates allowed']
82
+ };
83
+ }
84
+ map[val[i]] = true;
85
+ }
86
+ return {
87
+ valid: true
88
+ };
89
+ })
90
+ }))
91
+ .addSchemaFrom('Templates.Schedule', 'Models.TaskScheduleMonth', ({ base, string, number, union }) => base.addProps({
92
+ /** Repeat every month */
93
+ every: string('month'),
94
+ /** Day - 'last' or number from 1 to 28 */
95
+ day: union(string('last'), number().min(1).max(28))
96
+ }))
97
+ .addSchemaFrom('Templates.Schedule', 'Models.TaskScheduleYear', ({ base, string, number, union }) => base.addProps({
98
+ /** Repeat every year */
99
+ every: string('year'),
100
+ /** Day - 'last' or number from 1 to 28 */
101
+ day: union(string('last')).or(number().min(1).max(28)),
102
+ /** Month - number from 1 to 12 */
103
+ month: number().min(1).max(12)
104
+ }));
105
+ exports.schemaRegistry = registry
106
+ .addSchema('Models.Schedule', ({ alias, union }) => union(alias('Models.TaskScheduleMinute'), alias('Models.TaskScheduleDay'), alias('Models.TaskScheduleWeek'), alias('Models.TaskScheduleMonth'), alias('Models.TaskScheduleYear')))
107
+ .addSchema('Models.CreateJobRequest', ({ object, number, string, alias, union, func }) => object({
108
+ /** Id of job, must be uniq */
109
+ id: string(),
110
+ /** Path to js file (relative to root folder) */
111
+ path: string().minLength(1),
112
+ /** Job's schedule */
113
+ schedule: alias('Models.Schedule'),
114
+ /** Timeout for job (in milliseconds) */
115
+ timeout: number().min(0).optional(),
116
+ /** Arbitrary props for job (can be a callback returning props or Promise<props>) */
117
+ props: union(object().canHaveUnknownProps(), func()).optional(),
118
+ /** Job will be considered as disabled when more than that count of runs fails consequently
119
+ * unlimited if negative
120
+ */
121
+ maxConsequentFails: number().optional(),
122
+ /**
123
+ * Job will be retried right away this times. Job will be retried on next schedule run if this number is exceeded.
124
+ */
125
+ maxRetries: number().optional().min(1)
126
+ }));
127
+ exports.Schemas = exports.schemaRegistry;
128
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,11 +1,15 @@
1
1
  {
2
2
  "name": "@cleverbrush/scheduler",
3
- "version": "1.0.0-beta.3",
3
+ "version": "1.0.0-beta.5",
4
4
  "keywords": [
5
5
  "task scheduler"
6
6
  ],
7
7
  "author": "Andrew Zolotukhin <andrew_zol@cleverbrush.com>",
8
8
  "license": "BSD",
9
+ "files": [
10
+ "*",
11
+ "dist/*"
12
+ ],
9
13
  "main": "./dist/index.js",
10
14
  "readme": "https://github.com/cleverbrush/libs/tree/master/libs/scheduler#readme",
11
15
  "scripts": {
@@ -17,7 +21,7 @@
17
21
  "url": "github:cleverbrush/libs"
18
22
  },
19
23
  "dependencies": {
20
- "@cleverbrush/schema": "1.0.0-beta.3"
24
+ "@cleverbrush/schema": "1.0.0-beta.5"
21
25
  },
22
26
  "types": "./dist/index.d.ts"
23
27
  }
@@ -86,7 +86,7 @@ test('day - 4', () => {
86
86
  interval: 2,
87
87
  startsOn: new Date(Date.UTC(2022, 9, 12, 21, 0, 0, 0)),
88
88
  endsOn: new Date(Date.UTC(2022, 11, 12, 0, 0, 0, 0)),
89
- startingFromIndex: 3,
89
+ skipFirst: 2,
90
90
  maxOccurences: 10
91
91
  });
92
92
 
@@ -102,8 +102,10 @@ test('day - 4', () => {
102
102
  ];
103
103
 
104
104
  for (let i = 0; i < results.length; i++) {
105
- expect(calculator.hasNext()).toEqual(true);
106
- expect(calculator.next().date.getTime()).toEqual(results[i].getTime());
105
+ const hasNext = calculator.hasNext();
106
+ expect(hasNext).toEqual(true);
107
+ const next = calculator.next();
108
+ expect(next.date.getTime()).toEqual(results[i].getTime());
107
109
  }
108
110
 
109
111
  expect(calculator.hasNext()).toEqual(false);
@@ -86,9 +86,12 @@ export class ScheduleCalculator {
86
86
  this.#hasNext = true;
87
87
  }
88
88
 
89
- let leftToSkip = this.#schedule.startingFromIndex || 1;
89
+ let leftToSkip =
90
+ typeof this.#schedule.skipFirst === 'number'
91
+ ? this.#schedule.skipFirst
92
+ : 0;
90
93
 
91
- while (leftToSkip-- > 1 && this.#hasNext) {
94
+ while (leftToSkip-- > 0 && this.#hasNext) {
92
95
  this.next();
93
96
  }
94
97
  }
package/src/index.ts CHANGED
@@ -35,6 +35,7 @@ const CHECK_INTERVAL = 1000 * 10; // every 10 seconds
35
35
  const SCHEDULE_JOB_SPAN = 1000 * 60; // 1 hour
36
36
  const DEFAULT_JOB_TIMEOUT = 1000 * 20; // 20 seconds
37
37
  const DEFAULT_MAX_CONSEQUENT_FAILS = 3;
38
+ const DEFAULT_MAX_RETRIES = 2;
38
39
 
39
40
  type JobStartItem = {
40
41
  jobId: string;
@@ -53,11 +54,16 @@ type JobErrorItem = JobStartItem & {
53
54
  error?: Error;
54
55
  };
55
56
 
57
+ type JobMessageItem = Omit<JobStartItem, 'stdout' | 'stderr'> & {
58
+ value: any;
59
+ };
60
+
56
61
  type Events = {
57
62
  'job:start': (job: JobStartItem) => any;
58
63
  'job:end': (job: JobEndItem) => any;
59
64
  'job:error': (job: JobErrorItem) => any;
60
65
  'job:timeout': (job: JobErrorItem) => any;
66
+ 'job:message': (msg: JobMessageItem) => any;
61
67
  };
62
68
 
63
69
  interface IJobScheduler {
@@ -102,7 +108,7 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
102
108
  }
103
109
 
104
110
  if (typeof job.successfullTimesRunned === 'number') {
105
- schedule.startingFromIndex = job.successfullTimesRunned + 1;
111
+ schedule.skipFirst = job.successfullTimesRunned - 1;
106
112
  }
107
113
 
108
114
  const res = new ScheduleCalculator(schedule);
@@ -152,8 +158,7 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
152
158
 
153
159
  return {
154
160
  promise,
155
- stderr: worker.stderr,
156
- stdout: worker.stdout
161
+ worker
157
162
  };
158
163
  }
159
164
 
@@ -193,45 +198,54 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
193
198
  status: 'running'
194
199
  });
195
200
 
196
- const { promise, stderr, stdout } = this.runWorkerWithTimeout(
201
+ const { promise, worker } = this.runWorkerWithTimeout(
197
202
  fileName,
198
203
  finalProps,
199
204
  job.timeout
200
205
  );
201
206
 
202
- const stdOutPass = stdout.pipe(
207
+ const stdOutPass = worker.stdout.pipe(
203
208
  new PassThrough({
204
209
  highWaterMark: MAX_BUFFER_SIZE
205
210
  })
206
211
  );
207
- const stdErrPass = stderr.pipe(
212
+ const stdErrPass = worker.stderr.pipe(
208
213
  new PassThrough({
209
214
  highWaterMark: MAX_BUFFER_SIZE
210
215
  })
211
216
  );
212
217
 
213
- const stdOutForJobStart = stdout.pipe(
218
+ const stdOutForJobStart = worker.stdout.pipe(
214
219
  new PassThrough({
215
220
  highWaterMark: MAX_BUFFER_SIZE
216
221
  })
217
222
  );
218
- const stdErrForJobStart = stderr.pipe(
223
+ const stdErrForJobStart = worker.stderr.pipe(
219
224
  new PassThrough({
220
225
  highWaterMark: MAX_BUFFER_SIZE
221
226
  })
222
227
  );
223
228
 
224
- const stdOutForJobEnd = stdout.pipe(
229
+ const stdOutForJobEnd = worker.stdout.pipe(
225
230
  new PassThrough({
226
231
  highWaterMark: MAX_BUFFER_SIZE
227
232
  })
228
233
  );
229
- const stdErrForJobEnd = stderr.pipe(
234
+ const stdErrForJobEnd = worker.stderr.pipe(
230
235
  new PassThrough({
231
236
  highWaterMark: MAX_BUFFER_SIZE
232
237
  })
233
238
  );
234
239
 
240
+ worker.on('message', (value) => {
241
+ this.emit('job:message', {
242
+ instanceId: instance.id,
243
+ jobId: job.id,
244
+ startDate,
245
+ value
246
+ });
247
+ });
248
+
235
249
  this.emit('job:start', {
236
250
  instanceId: instance.id,
237
251
  jobId: job.id,
@@ -323,8 +337,11 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
323
337
 
324
338
  await this._jobsRepository.saveJob(job);
325
339
 
326
- if (shouldRetry) {
327
- await this.startJobInstance(instance);
340
+ if (shouldRetry && instance.retryIndex < instance.maxRetries) {
341
+ await this.startJobInstance({
342
+ ...instance,
343
+ retryIndex: instance.retryIndex + 1
344
+ });
328
345
  }
329
346
  }
330
347
  }
@@ -347,7 +364,9 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
347
364
  scheduledTo: date,
348
365
  status: 'scheduled',
349
366
  timeout: job.timeout,
350
- index
367
+ index,
368
+ retryIndex: 0,
369
+ maxRetries: job.maxRetries
351
370
  });
352
371
 
353
372
  timer = setTimeout(async () => {
@@ -467,7 +486,11 @@ export class JobScheduler extends EventEmitter implements IJobScheduler {
467
486
  maxConsequentFails:
468
487
  typeof job.maxConsequentFails === 'number'
469
488
  ? job.maxConsequentFails
470
- : DEFAULT_MAX_CONSEQUENT_FAILS
489
+ : DEFAULT_MAX_CONSEQUENT_FAILS,
490
+ maxRetries:
491
+ typeof job.maxRetries === 'number'
492
+ ? job.maxRetries
493
+ : DEFAULT_MAX_RETRIES
471
494
  });
472
495
  }
473
496
 
package/src/types.ts CHANGED
@@ -40,8 +40,8 @@ const registry = new SchemaRegistry()
40
40
  endsOn: alias('Common.Date').optional(),
41
41
  /** Max number of repeats (min 1) */
42
42
  maxOccurences: number().min(1).optional(),
43
- /** Skip this number of repeats - 1. Min value is 1. */
44
- startingFromIndex: number().min(1).optional()
43
+ /** Skip this number of repeats. Min value is 1. */
44
+ skipFirst: number().min(1).optional()
45
45
  })
46
46
  .setPropPreprocessor('endsOn', 'StringToDate')
47
47
  .addValidator((val) => {
@@ -161,7 +161,11 @@ export const schemaRegistry = registry
161
161
  /** Job will be considered as disabled when more than that count of runs fails consequently
162
162
  * unlimited if negative
163
163
  */
164
- maxConsequentFails: number().optional()
164
+ maxConsequentFails: number().optional(),
165
+ /**
166
+ * Job will be retried right away this times. Job will be retried on next schedule run if this number is exceeded.
167
+ */
168
+ maxRetries: number().optional().min(1)
165
169
  })
166
170
  );
167
171
 
@@ -188,6 +192,7 @@ export type Job = {
188
192
  successfullTimesRunned?: number;
189
193
  consequentFailsCount: number;
190
194
  maxConsequentFails: number;
195
+ maxRetries: number;
191
196
  };
192
197
 
193
198
  export type JobInstance = {
@@ -202,6 +207,8 @@ export type JobInstance = {
202
207
  stdOut?: string;
203
208
  stdErr?: string;
204
209
  exitCode?: number;
210
+ retryIndex: number;
211
+ maxRetries: number;
205
212
  };
206
213
 
207
214
  export type JobSchedulerProps = {