@spinajs/tasks 2.0.552 → 2.0.554

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,18 +1,24 @@
1
1
  export declare const TASK_COMMAND = "task:command";
2
- interface TaskOptions {
2
+ export interface TaskOptions {
3
+ /**
4
+ * Allow several runs of the same task at once, e.g. a long run that overlaps the next start.
5
+ */
3
6
  taskStacking: boolean;
7
+ /**
8
+ * Lifetime of the task mutex in ms, renewed every lockTtl / 3 while the task runs, so a
9
+ * crashed process frees the task after at most lockTtl. 0 = never expires.
10
+ */
11
+ lockTtl: number;
4
12
  }
13
+ export declare const DEFAULT_TASK_OPTIONS: TaskOptions;
5
14
  /**
6
- * Cli command, wrapper for lib commander. For more docs on command options & args check
7
- * https://github.com/tj/commander.js
15
+ * Marks a method as a task: records runs in `__tasks` / `__task_history`, emits
16
+ * TaskSuccess / TaskFailed and, unless `taskStacking` is set, lets only one run
17
+ * happen at a time across all processes sharing the database.
8
18
  *
9
- * It allows to use all features that spinajs provides eg. DI, logging, intl support etc.
10
- * inside command functions without hassle.
11
- *
12
- * @param nameAndArgs - name of command with optional args defined
13
- * @param description - short description
14
- * @param opts - additional options, see https://github.com/tj/commander.js
19
+ * @param taskName - unique task name
20
+ * @param description - short description
21
+ * @param opts - see {@link TaskOptions}, defaults to {@link DEFAULT_TASK_OPTIONS}
15
22
  */
16
- export declare function Task(taskName: string, description: string, opts?: TaskOptions): (_target: any, _propertyKey: string | symbol, descriptor: PropertyDescriptor) => void;
17
- export {};
23
+ export declare function Task(taskName: string, description: string, opts?: Partial<TaskOptions>): (_target: any, _propertyKey: string | symbol, descriptor: PropertyDescriptor) => void;
18
24
  //# sourceMappingURL=decorators.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C,UAAU,WAAW;IAInB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,aAIlD,GAAG,gBAAgB,MAAM,GAAG,MAAM,cAAc,kBAAkB,UA4E7F"}
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,YAAY,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,oBAAoB,EAAE,WAGlC,CAAC;AAqDF;;;;;;;;GAQG;AACH,wBAAgB,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,aAK3D,GAAG,gBAAgB,MAAM,GAAG,MAAM,cAAc,kBAAkB,UAyE7F"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TASK_COMMAND = void 0;
3
+ exports.DEFAULT_TASK_OPTIONS = exports.TASK_COMMAND = void 0;
4
4
  exports.Task = Task;
5
5
  const threading_1 = require("@spinajs/threading");
6
6
  const util_1 = require("@spinajs/util");
@@ -11,20 +11,65 @@ const __task_history_js_1 = require("./models/__task_history.js");
11
11
  const TaskSuccess_js_1 = require("./events/TaskSuccess.js");
12
12
  const TaskFailed_js_1 = require("./events/TaskFailed.js");
13
13
  exports.TASK_COMMAND = 'task:command';
14
+ exports.DEFAULT_TASK_OPTIONS = {
15
+ taskStacking: false,
16
+ lockTtl: 60000,
17
+ };
18
+ // The mutex is re-entrant per tenant and the default tenant is per process,
19
+ // so overlapping runs inside one process are excluded here, not by the mutex.
20
+ const runningInProcess = new Set();
21
+ async function lockTask(name, opts, log) {
22
+ if (opts.taskStacking) {
23
+ return async () => { };
24
+ }
25
+ if (runningInProcess.has(name)) {
26
+ log.warn(`Task ${name} is already running in this process`);
27
+ return null;
28
+ }
29
+ runningInProcess.add(name);
30
+ const mutexName = `task-${name}`;
31
+ try {
32
+ const lock = await (0, threading_1.mutex_acquire)({ Name: mutexName, ttl: opts.lockTtl });
33
+ if (!lock.Locked) {
34
+ runningInProcess.delete(name);
35
+ log.warn(`Cannot acquire mutex for task ${name}, already locked !`);
36
+ return null;
37
+ }
38
+ }
39
+ catch (err) {
40
+ runningInProcess.delete(name);
41
+ throw err;
42
+ }
43
+ const heartbeat = opts.lockTtl > 0
44
+ ? setInterval(() => {
45
+ (0, threading_1.mutex_renew)({ Name: mutexName, ttl: opts.lockTtl })
46
+ .then((renewed) => {
47
+ if (!renewed) {
48
+ log.warn(`Task ${name} lost its mutex, another process may run it now`);
49
+ }
50
+ })
51
+ .catch((err) => log.error(err, `Cannot renew mutex for task ${name}`));
52
+ }, Math.max(1, Math.floor(opts.lockTtl / 3)))
53
+ : undefined;
54
+ return async () => {
55
+ clearInterval(heartbeat);
56
+ runningInProcess.delete(name);
57
+ await (0, threading_1.mutex_release)({ Name: mutexName });
58
+ };
59
+ }
14
60
  /**
15
- * Cli command, wrapper for lib commander. For more docs on command options & args check
16
- * https://github.com/tj/commander.js
61
+ * Marks a method as a task: records runs in `__tasks` / `__task_history`, emits
62
+ * TaskSuccess / TaskFailed and, unless `taskStacking` is set, lets only one run
63
+ * happen at a time across all processes sharing the database.
17
64
  *
18
- * It allows to use all features that spinajs provides eg. DI, logging, intl support etc.
19
- * inside command functions without hassle.
20
- *
21
- * @param nameAndArgs - name of command with optional args defined
22
- * @param description - short description
23
- * @param opts - additional options, see https://github.com/tj/commander.js
65
+ * @param taskName - unique task name
66
+ * @param description - short description
67
+ * @param opts - see {@link TaskOptions}, defaults to {@link DEFAULT_TASK_OPTIONS}
24
68
  */
25
69
  function Task(taskName, description, opts) {
26
70
  const _name = (0, util_1._check_arg)((0, util_1._trim)(), (0, util_1._non_empty)())(taskName, 'Task name is empty');
27
71
  const _description = (0, util_1._check_arg)((0, util_1._trim)(), (0, util_1._non_empty)())(description, 'Task description is empty');
72
+ const _opts = { ...exports.DEFAULT_TASK_OPTIONS, ...opts };
28
73
  return function (_target, _propertyKey, descriptor) {
29
74
  const oldFunction = descriptor.value;
30
75
  descriptor.value = async function (...args) {
@@ -36,18 +81,19 @@ function Task(taskName, description, opts) {
36
81
  Description: _description,
37
82
  State: 'stopped',
38
83
  });
39
- if (!opts.taskStacking) {
40
- const lock = await (0, threading_1.mutex_acquire)({
41
- Name: `task-${_name}`,
42
- });
43
- if (!lock.Locked) {
44
- log.warn(`Cannot acquire mutex for task ${_name}, already locked !`);
45
- return;
46
- }
84
+ const unlock = await lockTask(_name, _opts, log);
85
+ if (!unlock) {
86
+ return;
87
+ }
88
+ try {
89
+ task.State = 'running';
90
+ task.LastRunAt = luxon_1.DateTime.now();
91
+ await task.update();
92
+ }
93
+ catch (err) {
94
+ await unlock();
95
+ throw err;
47
96
  }
48
- task.State = 'running';
49
- task.LastRunAt = luxon_1.DateTime.now();
50
- await task.update();
51
97
  let taskResult = null;
52
98
  const start = luxon_1.DateTime.now();
53
99
  try {
@@ -70,9 +116,7 @@ function Task(taskName, description, opts) {
70
116
  }
71
117
  finally {
72
118
  try {
73
- await (0, threading_1.mutex_release)({
74
- Name: `task-${name}`,
75
- });
119
+ await unlock();
76
120
  await task.update({
77
121
  State: 'stopped',
78
122
  });
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":";;;;AAAA,kDAAkE;AAClE,wCAA8D;AAC9D,oCAAiC;AACjC,kDAA4C;AAC5C,iCAAiC;AACjC,kEAA4D;AAE5D,4DAAsD;AACtD,0DAAoD;AAEvC,QAAA,YAAY,GAAG,cAAc,CAAC;AAS3C;;;;;;;;;;GAUG;AACH,cAAqB,QAAgB,EAAE,WAAmB,EAAE,IAAkB;IAC5E,MAAM,KAAK,GAAG,IAAA,iBAAU,EAAC,IAAA,YAAK,GAAE,EAAE,IAAA,iBAAU,GAAE,CAAC,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;IAChF,MAAM,YAAY,GAAG,IAAA,iBAAU,EAAC,IAAA,YAAK,GAAE,EAAE,IAAA,iBAAU,GAAE,CAAC,CAAC,WAAW,EAAE,2BAA2B,CAAC,CAAC;IAEjG,OAAO,UAAU,OAAY,EAAE,YAA6B,EAAE,UAA8B;QAC1F,MAAM,WAAW,GAAa,UAAU,CAAC,KAAK,CAAC;QAC/C,UAAU,CAAC,KAAK,GAAG,KAAK,WAAW,GAAG,IAAW;YAC/C,MAAM,GAAG,GAAG,OAAE,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAQ,CAAC;YAEpD,GAAG,CAAC,IAAI,CAAC,kBAAkB,KAAK,MAAM,CAAC,CAAC;YAExC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,kBAAM,CAAC,WAAW,CAAC,IAAI,EAAE;oBAC1C,IAAI,EAAE,KAAK;oBACX,WAAW,EAAE,YAAY;oBACzB,KAAK,EAAE,SAAS;iBACjB,CAAC,CAAC;gBAEH,IAAI,CAAC,IAAK,CAAC,YAAY,EAAE,CAAC;oBACxB,MAAM,IAAI,GAAG,MAAM,IAAA,yBAAa,EAAC;wBAC/B,IAAI,EAAE,QAAQ,KAAK,EAAE;qBACtB,CAAC,CAAC;oBAEH,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;wBACjB,GAAG,CAAC,IAAI,CAAC,iCAAiC,KAAK,oBAAoB,CAAC,CAAC;wBACrE,OAAO;oBACT,CAAC;gBACH,CAAC;gBAED,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;gBACvB,IAAI,CAAC,SAAS,GAAG,gBAAQ,CAAC,GAAG,EAAE,CAAC;gBAChC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;gBAEpB,IAAI,UAAU,GAAG,IAAI,CAAC;gBACtB,MAAM,KAAK,GAAG,gBAAQ,CAAC,GAAG,EAAE,CAAC;gBAC7B,IAAI,CAAC;oBACH,UAAU,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;oBACjD,MAAM,4BAAW,CAAC,IAAI,CAAC;wBACrB,QAAQ,EAAE,QAAQ;qBACnB,CAAC,CAAC;oBAEH,GAAG,CAAC,OAAO,CAAC,QAAQ,QAAQ,aAAa,CAAC,CAAC;gBAC7C,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,uBAAuB,QAAQ,EAAE,CAAC,CAAC;oBAClD,UAAU,GAAG;wBACX,KAAK,EAAE,IAAI;wBACX,OAAO,EAAE,GAAG,CAAC,OAAO;qBACrB,CAAC;oBAEF,MAAM,0BAAU,CAAC,IAAI,CAAC;wBACpB,QAAQ,EAAE,QAAQ;wBAClB,MAAM,EAAE,GAAG,CAAC,OAAO;qBACpB,CAAC,CAAC;gBACL,CAAC;wBAAS,CAAC;oBACT,IAAI,CAAC;wBACH,MAAM,IAAA,yBAAa,EAAC;4BAClB,IAAI,EAAE,QAAQ,IAAI,EAAE;yBACrB,CAAC,CAAC;wBAEH,MAAM,IAAI,CAAC,MAAM,CAAC;4BAChB,KAAK,EAAE,SAAS;yBACjB,CAAC,CAAC;wBAEH,MAAM,kCAAc,CAAC,MAAM,CAAC;4BAC1B,MAAM,EAAE,IAAI,CAAC,EAAE;4BACf,MAAM,EAAE,UAAU;4BAClB,QAAQ,EAAE,gBAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY;yBAClD,CAAC,CAAC;oBACL,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;oBACzC,CAAC;oBAED,OAAO,UAAU,CAAC;gBACpB,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,qBAAqB,QAAQ,EAAE,CAAC,CAAC;gBAChD,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,24 @@
1
1
  export declare const TASK_COMMAND = "task:command";
2
- interface TaskOptions {
2
+ export interface TaskOptions {
3
+ /**
4
+ * Allow several runs of the same task at once, e.g. a long run that overlaps the next start.
5
+ */
3
6
  taskStacking: boolean;
7
+ /**
8
+ * Lifetime of the task mutex in ms, renewed every lockTtl / 3 while the task runs, so a
9
+ * crashed process frees the task after at most lockTtl. 0 = never expires.
10
+ */
11
+ lockTtl: number;
4
12
  }
13
+ export declare const DEFAULT_TASK_OPTIONS: TaskOptions;
5
14
  /**
6
- * Cli command, wrapper for lib commander. For more docs on command options & args check
7
- * https://github.com/tj/commander.js
15
+ * Marks a method as a task: records runs in `__tasks` / `__task_history`, emits
16
+ * TaskSuccess / TaskFailed and, unless `taskStacking` is set, lets only one run
17
+ * happen at a time across all processes sharing the database.
8
18
  *
9
- * It allows to use all features that spinajs provides eg. DI, logging, intl support etc.
10
- * inside command functions without hassle.
11
- *
12
- * @param nameAndArgs - name of command with optional args defined
13
- * @param description - short description
14
- * @param opts - additional options, see https://github.com/tj/commander.js
19
+ * @param taskName - unique task name
20
+ * @param description - short description
21
+ * @param opts - see {@link TaskOptions}, defaults to {@link DEFAULT_TASK_OPTIONS}
15
22
  */
16
- export declare function Task(taskName: string, description: string, opts?: TaskOptions): (_target: any, _propertyKey: string | symbol, descriptor: PropertyDescriptor) => void;
17
- export {};
23
+ export declare function Task(taskName: string, description: string, opts?: Partial<TaskOptions>): (_target: any, _propertyKey: string | symbol, descriptor: PropertyDescriptor) => void;
18
24
  //# sourceMappingURL=decorators.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C,UAAU,WAAW;IAInB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,aAIlD,GAAG,gBAAgB,MAAM,GAAG,MAAM,cAAc,kBAAkB,UA4E7F"}
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/decorators.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,YAAY,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,oBAAoB,EAAE,WAGlC,CAAC;AAqDF;;;;;;;;GAQG;AACH,wBAAgB,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,aAK3D,GAAG,gBAAgB,MAAM,GAAG,MAAM,cAAc,kBAAkB,UAyE7F"}
@@ -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,20 +7,65 @@ 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
+ }
10
56
  /**
11
- * Cli command, wrapper for lib commander. For more docs on command options & args check
12
- * https://github.com/tj/commander.js
57
+ * Marks a method as a task: records runs in `__tasks` / `__task_history`, emits
58
+ * TaskSuccess / TaskFailed and, unless `taskStacking` is set, lets only one run
59
+ * happen at a time across all processes sharing the database.
13
60
  *
14
- * It allows to use all features that spinajs provides eg. DI, logging, intl support etc.
15
- * inside command functions without hassle.
16
- *
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
61
+ * @param taskName - unique task name
62
+ * @param description - short description
63
+ * @param opts - see {@link TaskOptions}, defaults to {@link DEFAULT_TASK_OPTIONS}
20
64
  */
21
65
  export function Task(taskName, description, opts) {
22
66
  const _name = _check_arg(_trim(), _non_empty())(taskName, 'Task name is empty');
23
67
  const _description = _check_arg(_trim(), _non_empty())(description, 'Task description is empty');
68
+ const _opts = { ...DEFAULT_TASK_OPTIONS, ...opts };
24
69
  return function (_target, _propertyKey, descriptor) {
25
70
  const oldFunction = descriptor.value;
26
71
  descriptor.value = async function (...args) {
@@ -32,18 +77,19 @@ export function Task(taskName, description, opts) {
32
77
  Description: _description,
33
78
  State: 'stopped',
34
79
  });
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
- }
80
+ const unlock = await lockTask(_name, _opts, log);
81
+ if (!unlock) {
82
+ return;
83
+ }
84
+ try {
85
+ task.State = 'running';
86
+ task.LastRunAt = DateTime.now();
87
+ await task.update();
88
+ }
89
+ catch (err) {
90
+ await unlock();
91
+ throw err;
43
92
  }
44
- task.State = 'running';
45
- task.LastRunAt = DateTime.now();
46
- await task.update();
47
93
  let taskResult = null;
48
94
  const start = DateTime.now();
49
95
  try {
@@ -66,9 +112,7 @@ export function Task(taskName, description, opts) {
66
112
  }
67
113
  finally {
68
114
  try {
69
- await mutex_release({
70
- Name: `task-${name}`,
71
- });
115
+ await unlock();
72
116
  await task.update({
73
117
  State: 'stopped',
74
118
  });
@@ -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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"}