@cleverbrush/scheduler 1.0.0-beta.0 → 1.0.0-beta.1
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 +2 -2
- package/src/index.ts +100 -20
- package/src/jobRepository.ts +7 -0
- package/src/types.ts +14 -12
- package/dist/CloneReadableStream.d.ts +0 -9
- package/dist/CloneReadableStream.d.ts.map +0 -1
- package/dist/CloneReadableStream.js +0 -25
- package/dist/CloneReadableStream.js.map +0 -1
- package/dist/ScheduleCalculator.d.ts +0 -10
- package/dist/ScheduleCalculator.d.ts.map +0 -1
- package/dist/ScheduleCalculator.js +0 -208
- package/dist/ScheduleCalculator.js.map +0 -1
- package/dist/index.d.ts +0 -55
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -307
- package/dist/index.js.map +0 -1
- package/dist/jobRepository.d.ts +0 -32
- package/dist/jobRepository.d.ts.map +0 -1
- package/dist/jobRepository.js +0 -84
- package/dist/jobRepository.js.map +0 -1
- package/dist/reports.d.ts +0 -0
- package/dist/reports.js +0 -231
- package/dist/types.d.ts +0 -577
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -122
- package/dist/types.js.map +0 -1
package/dist/reports.js
DELETED
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
// import fs from 'fs';
|
|
2
|
-
// import { access as fsAccess } from 'fs/promises';
|
|
3
|
-
// import { join as pathJoin } from 'path';
|
|
4
|
-
// import { Worker } from 'worker_threads';
|
|
5
|
-
// import cronParser from 'cron-parser';
|
|
6
|
-
// import {
|
|
7
|
-
// schemaRegistry,
|
|
8
|
-
// JobSchedulerProps,
|
|
9
|
-
// CreateJobRequest,
|
|
10
|
-
// SchedulerStatus,
|
|
11
|
-
// Job,
|
|
12
|
-
// JobInstance
|
|
13
|
-
// } from './types.js';
|
|
14
|
-
// import { IJobRepository, InMemoryJobRepository } from './jobRepository.js';
|
|
15
|
-
// type WorkerResult = {
|
|
16
|
-
// status: 'success' | 'error' | 'timeout';
|
|
17
|
-
// stdout: unknown;
|
|
18
|
-
// stderr: unknown;
|
|
19
|
-
// };
|
|
20
|
-
// const CHECK_INTERVAL = 1000; // every second
|
|
21
|
-
// const SCHEDULE_JOB_SPAN = 1000 * 60 * 60; // 1 hour
|
|
22
|
-
// const DEFAULT_JOB_TIMEOUT = 1000 * 20; // 20 seconds
|
|
23
|
-
// export class JobScheduler {
|
|
24
|
-
// protected _rootFolder: string;
|
|
25
|
-
// protected _status: SchedulerStatus = 'stopped';
|
|
26
|
-
// protected _defaultTimezone: string;
|
|
27
|
-
// protected _checkTimer;
|
|
28
|
-
// protected _jobsRepository: IJobRepository = new InMemoryJobRepository();
|
|
29
|
-
// public get status() {
|
|
30
|
-
// return this._status;
|
|
31
|
-
// }
|
|
32
|
-
// protected set status(val: SchedulerStatus) {
|
|
33
|
-
// if (val === this._status) return;
|
|
34
|
-
// this._status = val;
|
|
35
|
-
// }
|
|
36
|
-
// protected async getJobSchedule(job: Job) {
|
|
37
|
-
// let timeZoneMix: { utc?: boolean; tz?: string } = {
|
|
38
|
-
// utc: true
|
|
39
|
-
// };
|
|
40
|
-
// if (typeof job.timeZone === 'string') {
|
|
41
|
-
// timeZoneMix = {
|
|
42
|
-
// tz: job.timeZone
|
|
43
|
-
// };
|
|
44
|
-
// } else if (typeof this._defaultTimezone === 'string') {
|
|
45
|
-
// timeZoneMix = {
|
|
46
|
-
// tz: this._defaultTimezone
|
|
47
|
-
// };
|
|
48
|
-
// }
|
|
49
|
-
// return cronParser.parseExpression(
|
|
50
|
-
// job.cron,
|
|
51
|
-
// Object.assign(
|
|
52
|
-
// {},
|
|
53
|
-
// timeZoneMix,
|
|
54
|
-
// typeof job.endDate !== 'undefined'
|
|
55
|
-
// ? {
|
|
56
|
-
// endDate: job.endDate
|
|
57
|
-
// }
|
|
58
|
-
// : {}
|
|
59
|
-
// )
|
|
60
|
-
// );
|
|
61
|
-
// }
|
|
62
|
-
// protected runFileWithTimeout(file: string): Promise<WorkerResult> {
|
|
63
|
-
// return new Promise((resolve) => {
|
|
64
|
-
// const worker = new Worker(file, {
|
|
65
|
-
// stderr: true,
|
|
66
|
-
// stdout: true
|
|
67
|
-
// });
|
|
68
|
-
// worker.on('error', () =>
|
|
69
|
-
// resolve({
|
|
70
|
-
// status: 'error',
|
|
71
|
-
// stderr: worker.stderr as any as ReadableStream,
|
|
72
|
-
// stdout: worker.stdout as any as ReadableStream
|
|
73
|
-
// })
|
|
74
|
-
// );
|
|
75
|
-
// worker.on('exit', () =>
|
|
76
|
-
// resolve({
|
|
77
|
-
// status: 'success',
|
|
78
|
-
// stderr: worker.stderr,
|
|
79
|
-
// stdout: worker.stdout
|
|
80
|
-
// })
|
|
81
|
-
// );
|
|
82
|
-
// });
|
|
83
|
-
// }
|
|
84
|
-
// protected async startJobInstance(instance: JobInstance): Promise<void> {
|
|
85
|
-
// await this._jobsRepository.setJobStatus(instance.id, 'active');
|
|
86
|
-
// const job = await this._jobsRepository.getJobById(instance.jobId);
|
|
87
|
-
// const fileName = pathJoin(this._rootFolder, job.path);
|
|
88
|
-
// const workerResult = await this.runFileWithTimeout(fileName);
|
|
89
|
-
// for await (const chunk of workerResult.stdout as any) {
|
|
90
|
-
// console.log(chunk.toString());
|
|
91
|
-
// }
|
|
92
|
-
// // console.log(workerResult.stdout);
|
|
93
|
-
// // workerResult.stdout
|
|
94
|
-
// // return new Promise((res) => {
|
|
95
|
-
// // const timer = setTimeout(() => {
|
|
96
|
-
// // console.log('task finished', instance);
|
|
97
|
-
// // res();
|
|
98
|
-
// // }, 20000);
|
|
99
|
-
// // console.log('task started', instance);
|
|
100
|
-
// // });
|
|
101
|
-
// }
|
|
102
|
-
// protected async scheduleJobTo(job: Job, date: Date): Promise<JobInstance> {
|
|
103
|
-
// let timer;
|
|
104
|
-
// try {
|
|
105
|
-
// const now = new Date();
|
|
106
|
-
// const interval = date.getTime() - now.getTime();
|
|
107
|
-
// console.log(now, date);
|
|
108
|
-
// if (interval < 0) throw new Error('interval is in the past');
|
|
109
|
-
// const instance = await this._jobsRepository.addInstance(job.id, {
|
|
110
|
-
// scheduledTo: date,
|
|
111
|
-
// status: 'scheduled',
|
|
112
|
-
// timeout: job.timeout
|
|
113
|
-
// });
|
|
114
|
-
// console.log(interval);
|
|
115
|
-
// timer = setTimeout(async () => {
|
|
116
|
-
// await this.startJobInstance(instance);
|
|
117
|
-
// console.log('finished');
|
|
118
|
-
// }, interval);
|
|
119
|
-
// return instance;
|
|
120
|
-
// } catch (e) {
|
|
121
|
-
// clearTimeout(timer);
|
|
122
|
-
// console.log(e);
|
|
123
|
-
// console.log('task failed!');
|
|
124
|
-
// }
|
|
125
|
-
// }
|
|
126
|
-
// protected async checkForUpcomingJobs(): Promise<void> {
|
|
127
|
-
// const jobs = await this._jobsRepository.getJobs();
|
|
128
|
-
// for (let i = 0; i < jobs.length; i++) {
|
|
129
|
-
// const schedule = await this.getJobSchedule(jobs[i]);
|
|
130
|
-
// if (schedule.hasNext()) {
|
|
131
|
-
// const scheduledInstances =
|
|
132
|
-
// await this._jobsRepository.getInstancesWithStatus(
|
|
133
|
-
// jobs[i].id,
|
|
134
|
-
// 'scheduled'
|
|
135
|
-
// );
|
|
136
|
-
// const now = new Date().getTime();
|
|
137
|
-
// while (schedule.hasNext()) {
|
|
138
|
-
// const nextRun = schedule.next().toDate();
|
|
139
|
-
// if (nextRun.getTime() - now > SCHEDULE_JOB_SPAN) break;
|
|
140
|
-
// const alreadyScheduled = scheduledInstances.find(
|
|
141
|
-
// (i) => i.scheduledTo.getTime() === nextRun.getTime()
|
|
142
|
-
// );
|
|
143
|
-
// if (alreadyScheduled) continue;
|
|
144
|
-
// await this.scheduleJobTo(jobs[i], nextRun);
|
|
145
|
-
// }
|
|
146
|
-
// } else {
|
|
147
|
-
// await this._jobsRepository.setJobStatus(jobs[i].id, 'finished');
|
|
148
|
-
// }
|
|
149
|
-
// }
|
|
150
|
-
// }
|
|
151
|
-
// public async start() {
|
|
152
|
-
// if (this._status === 'started') {
|
|
153
|
-
// throw new Error('Scheduler is already started');
|
|
154
|
-
// }
|
|
155
|
-
// this.status = 'started';
|
|
156
|
-
// this._checkTimer = setInterval(
|
|
157
|
-
// this.checkForUpcomingJobs.bind(this),
|
|
158
|
-
// CHECK_INTERVAL
|
|
159
|
-
// );
|
|
160
|
-
// // TODO: add logic
|
|
161
|
-
// }
|
|
162
|
-
// public stop() {
|
|
163
|
-
// if (this._status === 'stopped') {
|
|
164
|
-
// throw new Error('Scheduler is already stopped');
|
|
165
|
-
// }
|
|
166
|
-
// clearInterval(this._checkTimer);
|
|
167
|
-
// this.status = 'stopped';
|
|
168
|
-
// // TODO: add logic
|
|
169
|
-
// }
|
|
170
|
-
// public async addJob(job: CreateJobRequest) {
|
|
171
|
-
// const validationResult =
|
|
172
|
-
// await schemaRegistry.schemas.Models.CreateJobRequest.validate(job);
|
|
173
|
-
// if (!validationResult.valid) {
|
|
174
|
-
// throw new Error(
|
|
175
|
-
// `Invalid CreateJobRequest: ${validationResult.errors?.join(
|
|
176
|
-
// '; '
|
|
177
|
-
// )}`
|
|
178
|
-
// );
|
|
179
|
-
// }
|
|
180
|
-
// const path = pathJoin(this._rootFolder, job.path);
|
|
181
|
-
// await fsAccess(path, fs.constants.R_OK);
|
|
182
|
-
// await this._jobsRepository.addJob({
|
|
183
|
-
// createdAt: new Date(),
|
|
184
|
-
// cron: job.cron,
|
|
185
|
-
// endDate: job.endDate,
|
|
186
|
-
// maxRuns: job.maxRuns,
|
|
187
|
-
// timeZone: job.timeZone,
|
|
188
|
-
// timeout: job.timeout || DEFAULT_JOB_TIMEOUT,
|
|
189
|
-
// path: job.path
|
|
190
|
-
// });
|
|
191
|
-
// }
|
|
192
|
-
// constructor(props: JobSchedulerProps) {
|
|
193
|
-
// if (typeof props.rootFolder !== 'string') {
|
|
194
|
-
// throw new Error('rootFolder must be a string');
|
|
195
|
-
// }
|
|
196
|
-
// if (typeof props.defaultTimeZone === 'string') {
|
|
197
|
-
// this._defaultTimezone = props.defaultTimeZone;
|
|
198
|
-
// }
|
|
199
|
-
// if (typeof props.persistRepository === 'object') {
|
|
200
|
-
// this._jobsRepository = props.persistRepository;
|
|
201
|
-
// }
|
|
202
|
-
// this._rootFolder = props.rootFolder;
|
|
203
|
-
// }
|
|
204
|
-
// }
|
|
205
|
-
// // testing area
|
|
206
|
-
// const doWork = async () => {
|
|
207
|
-
// const scheduler = new JobScheduler({
|
|
208
|
-
// rootFolder: '/home/andrew_zol/projects/cleverbrush-libs/libs/scheduler'
|
|
209
|
-
// });
|
|
210
|
-
// await scheduler.addJob({
|
|
211
|
-
// path: 'task1.js',
|
|
212
|
-
// schedule: {
|
|
213
|
-
// every: 'day',
|
|
214
|
-
// span: 1
|
|
215
|
-
// },
|
|
216
|
-
// endDate: new Date(Date.UTC(2022, 7, 17, 18, 0, 0, 0))
|
|
217
|
-
// });
|
|
218
|
-
// scheduler.start();
|
|
219
|
-
// // setTimeout(() => {
|
|
220
|
-
// // console.log('stopping scheduler');
|
|
221
|
-
// // scheduler.stop();
|
|
222
|
-
// // }, 10000);
|
|
223
|
-
// };
|
|
224
|
-
// // doWork();
|
|
225
|
-
// const cron = cronParser.parseExpression('0 8 */14 * *', {
|
|
226
|
-
// startDate: new Date(),
|
|
227
|
-
// endDate: new Date(Date.UTC(2022, 11, 31))
|
|
228
|
-
// });
|
|
229
|
-
// while (cron.hasNext()) {
|
|
230
|
-
// console.log(cron.next().toDate());
|
|
231
|
-
// }
|