@webtypen/webframez-core 0.3.51 → 0.3.53

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.
@@ -10,11 +10,15 @@ export declare class QueueWorkerCommand extends ConsoleCommand {
10
10
  autorestart: boolean;
11
11
  workerOperationId: string | null;
12
12
  workerHadError: boolean;
13
+ lastAutomationCheckAt: any;
13
14
  jobsExecuted: number;
14
15
  jobsSucceeded: number;
15
16
  jobsFailed: number;
16
17
  lastJob: any;
17
18
  log(message: string): void;
19
+ private formatAutomationCommand;
20
+ private formatAutomationExecution;
21
+ private logRegisteredAutomation;
18
22
  handle(): Promise<void>;
19
23
  init(): boolean;
20
24
  canStart(): boolean;
@@ -27,7 +31,11 @@ export declare class QueueWorkerCommand extends ConsoleCommand {
27
31
  }): void;
28
32
  getWorkerAutomation(): any[];
29
33
  getWorkerJobclasses(): any[] | null;
30
- checkWorkerAutomation(): any;
34
+ private getWorkerTimezone;
35
+ private getAutomationExecutionPayload;
36
+ private createAutomationEntry;
37
+ private pushIfDue;
38
+ checkWorkerAutomation(since?: any, until?: any): any;
31
39
  runAutomation(): Promise<void>;
32
40
  getNextJobNumber(connection: any): Promise<number>;
33
41
  checkStop(): boolean;
@@ -38,6 +38,7 @@ class QueueWorkerCommand extends ConsoleCommand_1.ConsoleCommand {
38
38
  this.autorestart = false;
39
39
  this.workerOperationId = null;
40
40
  this.workerHadError = false;
41
+ this.lastAutomationCheckAt = null;
41
42
  // Statistics
42
43
  this.jobsExecuted = 0;
43
44
  this.jobsSucceeded = 0;
@@ -49,6 +50,47 @@ class QueueWorkerCommand extends ConsoleCommand_1.ConsoleCommand {
49
50
  .tz(this.workerConfig.timezone ? this.workerConfig.timezone : "Europe/Berlin")
50
51
  .format("YY-MM-DD HH:mm:ss")}] ${message}`);
51
52
  }
53
+ formatAutomationCommand(automation) {
54
+ if (automation.jobclass === "BackupRunJob" && automation.payload && automation.payload.backupKey) {
55
+ return `backup:run ${automation.payload.backupKey}`;
56
+ }
57
+ return automation.jobclass || "unknown";
58
+ }
59
+ formatAutomationExecution(execution) {
60
+ if (!Array.isArray(execution)) {
61
+ return "invalid execution";
62
+ }
63
+ const [type, value, options] = execution;
64
+ const suffix = options && options.identifier ? ` (${options.identifier})` : "";
65
+ if (type === "daily") {
66
+ return `daily at ${value}${suffix}`;
67
+ }
68
+ if (type === "every_hour") {
69
+ return `every hour at minute ${value !== undefined && value !== null ? value : 0}${suffix}`;
70
+ }
71
+ if (type === "every_x_mins") {
72
+ return `every ${value} minute(s)${suffix}`;
73
+ }
74
+ if (value !== undefined && value !== null) {
75
+ return `${type} at ${value}${suffix}`;
76
+ }
77
+ return `${type}${suffix}`;
78
+ }
79
+ logRegisteredAutomation() {
80
+ const automations = this.getWorkerAutomation();
81
+ if (!automations || automations.length < 1) {
82
+ this.log("Registered automations: none");
83
+ return;
84
+ }
85
+ this.log("Registered automations:");
86
+ for (const automation of automations) {
87
+ const command = this.formatAutomationCommand(automation);
88
+ const executions = automation.executions && Array.isArray(automation.executions) && automation.executions.length > 0
89
+ ? automation.executions.map((execution) => this.formatAutomationExecution(execution)).join(", ")
90
+ : "no executions";
91
+ this.log(`- ${command}: ${executions}`);
92
+ }
93
+ }
52
94
  handle() {
53
95
  return __awaiter(this, void 0, void 0, function* () {
54
96
  const workerKey = this.getOption("worker");
@@ -80,6 +122,7 @@ class QueueWorkerCommand extends ConsoleCommand_1.ConsoleCommand {
80
122
  });
81
123
  try {
82
124
  this.log("Queue started");
125
+ this.logRegisteredAutomation();
83
126
  yield this.run();
84
127
  }
85
128
  catch (e) {
@@ -264,14 +307,38 @@ class QueueWorkerCommand extends ConsoleCommand_1.ConsoleCommand {
264
307
  }
265
308
  return jobclasses;
266
309
  }
267
- checkWorkerAutomation() {
310
+ getWorkerTimezone() {
311
+ return this.workerConfig.timezone ? this.workerConfig.timezone : "Europe/Berlin";
312
+ }
313
+ getAutomationExecutionPayload(automation, options) {
314
+ return automation.payload || (options && options.payload)
315
+ ? Object.assign(Object.assign({}, (automation.payload ? automation.payload : {})), (options && options.payload ? options.payload : {})) : null;
316
+ }
317
+ createAutomationEntry(automation, type, value, options, executionIdentifier, executionKey, dueAt) {
318
+ return Object.assign(Object.assign({}, automation), { _execution: {
319
+ key: `${automation.jobclass}_${executionKey}${executionIdentifier ? "_" + executionIdentifier : ""}_${dueAt.format("YYYY-MM-DD_HH:mm")}`,
320
+ type: type,
321
+ value: value,
322
+ identifier: executionIdentifier,
323
+ scheduled_at: dueAt.toDate(),
324
+ payload: this.getAutomationExecutionPayload(automation, options),
325
+ } });
326
+ }
327
+ pushIfDue(out, entryFactory, dueAt, since, until) {
328
+ if (dueAt.isAfter(since) && !dueAt.isAfter(until)) {
329
+ out.push(entryFactory(dueAt));
330
+ }
331
+ }
332
+ checkWorkerAutomation(since, until) {
268
333
  const workerAutomation = this.getWorkerAutomation();
269
334
  if (!workerAutomation || workerAutomation.length < 1) {
270
335
  return null;
271
336
  }
272
337
  const out = [];
273
338
  const days = DateFunctions_1.DateFunctions.getDays();
274
- const now = (0, moment_timezone_1.default)().tz(this.workerConfig.timezone ? this.workerConfig.timezone : "Europe/Berlin");
339
+ const timezone = this.getWorkerTimezone();
340
+ const now = until ? until.clone().tz(timezone) : (0, moment_timezone_1.default)().tz(timezone);
341
+ const checkedSince = since ? since.clone().tz(timezone) : now.clone().startOf("minute").subtract(1, "millisecond");
275
342
  let automationIndex = -1;
276
343
  for (let automation of workerAutomation) {
277
344
  automationIndex++;
@@ -315,61 +382,58 @@ class QueueWorkerCommand extends ConsoleCommand_1.ConsoleCommand {
315
382
  const useType = days.includes(type) ? "day_in_week" : type;
316
383
  const executionKey = type + "-" + (value !== undefined && value !== null ? value : "0");
317
384
  const executionIdentifier = options && options.identifier ? options.identifier : automation.identifier ? automation.identifier : null;
318
- const intervalKey = `${automation.jobclass}_${executionKey}${executionIdentifier ? "_" + executionIdentifier : ""}_${now.format("YYYY-MM-DD_HH:mm")}`;
385
+ const entryFactory = (dueAt, executionValue = value) => this.createAutomationEntry(automation, type, executionValue, options, executionIdentifier, executionKey, dueAt);
319
386
  switch (useType) {
320
- case "every_hour":
321
- if (parseInt(now.format("mm")) === parseInt(value && !isNaN(parseInt(value)) ? value : "0")) {
322
- out.push(Object.assign(Object.assign({}, automation), { _execution: {
323
- key: intervalKey,
324
- type: type,
325
- value: parseInt(value),
326
- identifier: executionIdentifier,
327
- payload: automation.payload || (options && options.payload)
328
- ? Object.assign(Object.assign({}, (automation.payload ? automation.payload : {})), (options.payload ? options.payload : {})) : null,
329
- } }));
387
+ case "every_hour": {
388
+ const minute = parseInt(value && !isNaN(parseInt(value)) ? value : "0");
389
+ let dueAt = checkedSince.clone().startOf("hour").minute(minute).second(0).millisecond(0);
390
+ if (!dueAt.isAfter(checkedSince)) {
391
+ dueAt.add(1, "hour");
392
+ }
393
+ while (!dueAt.isAfter(now)) {
394
+ this.pushIfDue(out, (entryDueAt) => entryFactory(entryDueAt, minute), dueAt, checkedSince, now);
395
+ dueAt = dueAt.clone().add(1, "hour");
330
396
  }
331
397
  break;
332
- case "every_x_mins":
398
+ }
399
+ case "every_x_mins": {
333
400
  const intervalMinutes = parseInt(value);
334
- const diffMins = now.diff((0, moment_timezone_1.default)()
335
- .tz(this.workerConfig.timezone ? this.workerConfig.timezone : "Europe/Berlin")
336
- .startOf("day"), "minutes");
337
- if (diffMins % intervalMinutes === 0) {
338
- out.push(Object.assign(Object.assign({}, automation), { _execution: {
339
- key: intervalKey,
340
- type: type,
341
- value: value,
342
- identifier: executionIdentifier,
343
- payload: automation.payload || (options && options.payload)
344
- ? Object.assign(Object.assign({}, (automation.payload ? automation.payload : {})), (options.payload ? options.payload : {})) : null,
345
- } }));
401
+ let dueAt = checkedSince.clone().startOf("minute").second(0).millisecond(0);
402
+ if (!dueAt.isAfter(checkedSince)) {
403
+ dueAt.add(1, "minute");
404
+ }
405
+ while (!dueAt.isAfter(now)) {
406
+ const diffMins = dueAt.diff(dueAt.clone().startOf("day"), "minutes");
407
+ if (diffMins % intervalMinutes === 0) {
408
+ this.pushIfDue(out, entryFactory, dueAt, checkedSince, now);
409
+ }
410
+ dueAt = dueAt.clone().add(1, "minute");
346
411
  }
347
412
  break;
348
- case "daily":
349
- if (now.format("HH:mm") === value) {
350
- out.push(Object.assign(Object.assign({}, automation), { _execution: {
351
- key: intervalKey,
352
- type: type,
353
- value: value,
354
- identifier: executionIdentifier,
355
- payload: automation.payload || (options && options.payload)
356
- ? Object.assign(Object.assign({}, (automation.payload ? automation.payload : {})), (options.payload ? options.payload : {})) : null,
357
- } }));
413
+ }
414
+ case "daily": {
415
+ let day = checkedSince.clone().startOf("day");
416
+ const endDay = now.clone().startOf("day");
417
+ while (!day.isAfter(endDay)) {
418
+ const dueAt = moment_timezone_1.default.tz(`${day.format("YYYY-MM-DD")} ${value}`, "YYYY-MM-DD HH:mm", timezone);
419
+ this.pushIfDue(out, entryFactory, dueAt, checkedSince, now);
420
+ day = day.clone().add(1, "day");
358
421
  }
359
422
  break;
360
- case "day_in_week":
361
- if ((now.format("dddd").toLowerCase() === type || now.format("dddd").toLowerCase() + "s" === type) &&
362
- now.format("HH:mm") === value) {
363
- out.push(Object.assign(Object.assign({}, automation), { _execution: {
364
- key: intervalKey,
365
- type: type,
366
- value: value,
367
- identifier: executionIdentifier,
368
- payload: automation.payload || (options && options.payload)
369
- ? Object.assign(Object.assign({}, (automation.payload ? automation.payload : {})), (options.payload ? options.payload : {})) : null,
370
- } }));
423
+ }
424
+ case "day_in_week": {
425
+ const isoWeekday = days.indexOf(type) + 1;
426
+ let day = checkedSince.clone().startOf("day");
427
+ const endDay = now.clone().startOf("day");
428
+ while (!day.isAfter(endDay)) {
429
+ if (day.isoWeekday() === isoWeekday) {
430
+ const dueAt = moment_timezone_1.default.tz(`${day.format("YYYY-MM-DD")} ${value}`, "YYYY-MM-DD HH:mm", timezone);
431
+ this.pushIfDue(out, entryFactory, dueAt, checkedSince, now);
432
+ }
433
+ day = day.clone().add(1, "day");
371
434
  }
372
435
  break;
436
+ }
373
437
  }
374
438
  }
375
439
  }
@@ -388,7 +452,12 @@ class QueueWorkerCommand extends ConsoleCommand_1.ConsoleCommand {
388
452
  automationChecking = false;
389
453
  break;
390
454
  }
391
- const checkAutomation = this.checkWorkerAutomation();
455
+ const now = (0, moment_timezone_1.default)().tz(this.getWorkerTimezone());
456
+ const checkedSince = this.lastAutomationCheckAt
457
+ ? this.lastAutomationCheckAt.clone()
458
+ : now.clone().startOf("minute").subtract(1, "millisecond");
459
+ this.lastAutomationCheckAt = now.clone();
460
+ const checkAutomation = this.checkWorkerAutomation(checkedSince, now);
392
461
  if (!checkAutomation || checkAutomation.length < 1) {
393
462
  yield this.wait(5000);
394
463
  continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webtypen/webframez-core",
3
- "version": "0.3.51",
3
+ "version": "0.3.53",
4
4
  "description": "The core package of the typescript based webframez (web-framework) by webtypen.de",
5
5
  "homepage": "https://webtypen.de/",
6
6
  "license": "MIT",