@spinajs/tasks 2.0.553 → 2.0.555

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.
@@ -1,4 +1,4 @@
1
- import { mutex_acquire, mutex_release } from '@spinajs/threading';
1
+ import { mutex_acquire, mutex_release, mutex_renew } from '@spinajs/threading';
2
2
  import { _check_arg, _non_empty, _trim } from '@spinajs/util';
3
3
  import { DI } from '@spinajs/di';
4
4
  import { __task } from './models/__task.js';
@@ -7,87 +7,181 @@ import { __task_history } from './models/__task_history.js';
7
7
  import { TaskSuccess } from './events/TaskSuccess.js';
8
8
  import { TaskFailed } from './events/TaskFailed.js';
9
9
  export const TASK_COMMAND = 'task:command';
10
+ export const DEFAULT_TASK_OPTIONS = {
11
+ taskStacking: false,
12
+ lockTtl: 60000,
13
+ };
14
+ // The mutex is re-entrant per tenant and the default tenant is per process,
15
+ // so overlapping runs inside one process are excluded here, not by the mutex.
16
+ const runningInProcess = new Set();
17
+ async function lockTask(name, opts, log) {
18
+ if (opts.taskStacking) {
19
+ return async () => { };
20
+ }
21
+ if (runningInProcess.has(name)) {
22
+ log.warn(`Task ${name} is already running in this process`);
23
+ return null;
24
+ }
25
+ runningInProcess.add(name);
26
+ const mutexName = `task-${name}`;
27
+ try {
28
+ const lock = await mutex_acquire({ Name: mutexName, ttl: opts.lockTtl });
29
+ if (!lock.Locked) {
30
+ runningInProcess.delete(name);
31
+ log.warn(`Cannot acquire mutex for task ${name}, already locked !`);
32
+ return null;
33
+ }
34
+ }
35
+ catch (err) {
36
+ runningInProcess.delete(name);
37
+ throw err;
38
+ }
39
+ const heartbeat = opts.lockTtl > 0
40
+ ? setInterval(() => {
41
+ mutex_renew({ Name: mutexName, ttl: opts.lockTtl })
42
+ .then((renewed) => {
43
+ if (!renewed) {
44
+ log.warn(`Task ${name} lost its mutex, another process may run it now`);
45
+ }
46
+ })
47
+ .catch((err) => log.error(err, `Cannot renew mutex for task ${name}`));
48
+ }, Math.max(1, Math.floor(opts.lockTtl / 3)))
49
+ : undefined;
50
+ return async () => {
51
+ clearInterval(heartbeat);
52
+ runningInProcess.delete(name);
53
+ await mutex_release({ Name: mutexName });
54
+ };
55
+ }
56
+ const declarations = new Map();
57
+ export function getTaskDeclarations(name) {
58
+ if (name !== undefined) {
59
+ return [...(declarations.get(name) ?? [])];
60
+ }
61
+ return [...declarations.values()].flat();
62
+ }
63
+ function errorMessage(err) {
64
+ return err?.message ?? String(err);
65
+ }
66
+ const NO_LOCK = () => Promise.resolve();
10
67
  /**
11
- * Cli command, wrapper for lib commander. For more docs on command options & args check
12
- * https://github.com/tj/commander.js
13
- *
14
- * It allows to use all features that spinajs provides eg. DI, logging, intl support etc.
15
- * inside command functions without hassle.
68
+ * Runs a task method with the `@Task` bookkeeping: `__tasks` state, a `__task_history` row and
69
+ * TaskSuccess / TaskFailed. The decorator calls it with `{ lock: true, rethrow: false }`.
70
+ */
71
+ export async function runTask(decl, thisArg, args, opts) {
72
+ const log = DI.resolve('__log__', ['TASKS']);
73
+ log.info(`Executing task ${decl.name} ...`);
74
+ let task;
75
+ let unlock;
76
+ try {
77
+ task = await __task.getOrCreate(null, {
78
+ Name: decl.name,
79
+ Description: decl.description,
80
+ State: 'stopped',
81
+ });
82
+ const lock = opts.lock ? await lockTask(decl.name, decl.options, log) : NO_LOCK;
83
+ if (!lock) {
84
+ return undefined;
85
+ }
86
+ unlock = lock;
87
+ try {
88
+ task.State = 'running';
89
+ task.LastRunAt = DateTime.now();
90
+ await task.update();
91
+ }
92
+ catch (err) {
93
+ await unlock();
94
+ throw err;
95
+ }
96
+ }
97
+ catch (err) {
98
+ log.error(err, `Cannot start task ${decl.name}`);
99
+ throw err;
100
+ }
101
+ let taskResult = null;
102
+ let failure = null;
103
+ const start = DateTime.now();
104
+ try {
105
+ try {
106
+ taskResult = await decl.method.apply(thisArg, args);
107
+ }
108
+ catch (err) {
109
+ failure = { error: err };
110
+ log.error(err, `Cannot execute task ${decl.name}`);
111
+ taskResult = {
112
+ error: true,
113
+ message: errorMessage(err),
114
+ };
115
+ }
116
+ // An emit failure (queue outage) is logged only: it must not turn a run whose side effects
117
+ // already happened into a failure that a caller would retry.
118
+ try {
119
+ if (failure) {
120
+ await TaskFailed.emit({
121
+ TaskName: decl.name,
122
+ Reason: errorMessage(failure.error),
123
+ });
124
+ }
125
+ else {
126
+ await TaskSuccess.emit({
127
+ TaskName: decl.name,
128
+ });
129
+ log.success(`Task ${decl.name} executed !`);
130
+ }
131
+ }
132
+ catch (emitErr) {
133
+ log.error(emitErr, `Cannot emit ${failure ? 'TaskFailed' : 'TaskSuccess'} for ${decl.name}`);
134
+ }
135
+ }
136
+ finally {
137
+ try {
138
+ await unlock();
139
+ await task.update({
140
+ State: 'stopped',
141
+ });
142
+ await __task_history.insert({
143
+ TaskId: task.Id,
144
+ Result: taskResult,
145
+ Duration: DateTime.now().diff(start).milliseconds,
146
+ });
147
+ }
148
+ catch (err) {
149
+ log.error(err, `Cannot finalize task`);
150
+ }
151
+ }
152
+ if (failure && opts.rethrow) {
153
+ throw failure.error;
154
+ }
155
+ return taskResult;
156
+ }
157
+ /**
158
+ * Marks a method as a task: records runs in `__tasks` / `__task_history`, emits
159
+ * TaskSuccess / TaskFailed and, unless `taskStacking` is set, lets only one run
160
+ * happen at a time across all processes sharing the database. The declaration is
161
+ * also recorded, so `@spinajs/scheduler` can schedule the method by task name.
16
162
  *
17
- * @param nameAndArgs - name of command with optional args defined
18
- * @param description - short description
19
- * @param opts - additional options, see https://github.com/tj/commander.js
163
+ * @param taskName - unique task name
164
+ * @param description - short description
165
+ * @param opts - see {@link TaskOptions}, defaults to {@link DEFAULT_TASK_OPTIONS}
20
166
  */
21
167
  export function Task(taskName, description, opts) {
22
168
  const _name = _check_arg(_trim(), _non_empty())(taskName, 'Task name is empty');
23
169
  const _description = _check_arg(_trim(), _non_empty())(description, 'Task description is empty');
24
- return function (_target, _propertyKey, descriptor) {
25
- const oldFunction = descriptor.value;
26
- descriptor.value = async function (...args) {
27
- const log = DI.resolve('__log__', ['TASKS']);
28
- log.info(`Executing task ${_name} ...`);
29
- try {
30
- const task = await __task.getOrCreate(null, {
31
- Name: _name,
32
- Description: _description,
33
- State: 'stopped',
34
- });
35
- if (!opts.taskStacking) {
36
- const lock = await mutex_acquire({
37
- Name: `task-${_name}`,
38
- });
39
- if (!lock.Locked) {
40
- log.warn(`Cannot acquire mutex for task ${_name}, already locked !`);
41
- return;
42
- }
43
- }
44
- task.State = 'running';
45
- task.LastRunAt = DateTime.now();
46
- await task.update();
47
- let taskResult = null;
48
- const start = DateTime.now();
49
- try {
50
- taskResult = await oldFunction.apply(this, args);
51
- await TaskSuccess.emit({
52
- TaskName: taskName,
53
- });
54
- log.success(`Task ${taskName} executed !`);
55
- }
56
- catch (err) {
57
- log.error(err, `Cannot execute task ${taskName}`);
58
- taskResult = {
59
- error: true,
60
- message: err.Message,
61
- };
62
- await TaskFailed.emit({
63
- TaskName: taskName,
64
- Reason: err.Message,
65
- });
66
- }
67
- finally {
68
- try {
69
- await mutex_release({
70
- Name: `task-${name}`,
71
- });
72
- await task.update({
73
- State: 'stopped',
74
- });
75
- await __task_history.insert({
76
- TaskId: task.Id,
77
- Result: taskResult,
78
- Duration: DateTime.now().diff(start).milliseconds,
79
- });
80
- }
81
- catch (err) {
82
- log.error(err, `Cannot finalize task`);
83
- }
84
- return taskResult;
85
- }
86
- }
87
- catch (err) {
88
- log.error(err, `Cannot start task ${taskName}`);
89
- throw err;
90
- }
170
+ const _opts = { ...DEFAULT_TASK_OPTIONS, ...opts };
171
+ return function (target, propertyKey, descriptor) {
172
+ const isStatic = typeof target === 'function';
173
+ const decl = {
174
+ name: _name,
175
+ description: _description,
176
+ options: _opts,
177
+ target: isStatic ? target : target.constructor,
178
+ isStatic,
179
+ propertyKey,
180
+ method: descriptor.value,
181
+ };
182
+ declarations.set(_name, [...(declarations.get(_name) ?? []), decl]);
183
+ descriptor.value = function (...args) {
184
+ return runTask(decl, this, args, { lock: true, rethrow: false });
91
185
  };
92
186
  };
93
187
  }
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"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"}