@tstdl/base 0.93.140 → 0.93.141
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/application/application.d.ts +1 -1
- package/application/application.js +1 -1
- package/application/providers.d.ts +20 -2
- package/application/providers.js +34 -7
- package/audit/module.d.ts +5 -0
- package/audit/module.js +9 -1
- package/authentication/server/module.d.ts +5 -0
- package/authentication/server/module.js +9 -1
- package/authentication/tests/authentication.api-controller.test.js +1 -1
- package/authentication/tests/authentication.api-request-token.provider.test.js +1 -1
- package/authentication/tests/authentication.client-service.test.js +1 -1
- package/circuit-breaker/postgres/module.d.ts +1 -0
- package/circuit-breaker/postgres/module.js +5 -1
- package/document-management/server/configure.js +5 -1
- package/document-management/server/module.d.ts +1 -1
- package/document-management/server/module.js +1 -1
- package/document-management/server/services/document-management-ancillary.service.js +1 -1
- package/document-management/tests/ai-config-hierarchy.test.js +0 -5
- package/document-management/tests/document-management-ai-overrides.test.js +0 -1
- package/document-management/tests/document-validation-ai-overrides.test.js +0 -1
- package/examples/document-management/main.d.ts +1 -0
- package/examples/document-management/main.js +14 -11
- package/key-value-store/postgres/module.d.ts +1 -0
- package/key-value-store/postgres/module.js +5 -1
- package/lock/postgres/module.d.ts +1 -0
- package/lock/postgres/module.js +5 -1
- package/mail/module.d.ts +5 -1
- package/mail/module.js +11 -6
- package/module/modules/web-server.module.js +2 -3
- package/notification/server/module.d.ts +1 -0
- package/notification/server/module.js +5 -1
- package/notification/tests/notification-flow.test.js +2 -2
- package/orm/decorators.d.ts +5 -1
- package/orm/decorators.js +1 -1
- package/orm/server/drizzle/schema-converter.js +17 -30
- package/orm/server/encryption.d.ts +0 -1
- package/orm/server/encryption.js +1 -4
- package/orm/server/index.d.ts +1 -6
- package/orm/server/index.js +1 -6
- package/orm/server/migration.d.ts +19 -0
- package/orm/server/migration.js +72 -0
- package/orm/server/repository.d.ts +1 -1
- package/orm/server/transaction.d.ts +5 -10
- package/orm/server/transaction.js +22 -26
- package/orm/server/transactional.js +3 -3
- package/orm/tests/database-migration.test.d.ts +1 -0
- package/orm/tests/database-migration.test.js +82 -0
- package/orm/tests/encryption.test.js +3 -4
- package/orm/utils.d.ts +17 -2
- package/orm/utils.js +49 -1
- package/package.json +4 -3
- package/rate-limit/postgres/module.d.ts +1 -0
- package/rate-limit/postgres/module.js +5 -1
- package/reflection/decorator-data.js +11 -12
- package/task-queue/README.md +2 -9
- package/task-queue/postgres/drizzle/{0000_simple_invisible_woman.sql → 0000_wakeful_sunspot.sql} +22 -14
- package/task-queue/postgres/drizzle/meta/0000_snapshot.json +160 -82
- package/task-queue/postgres/drizzle/meta/_journal.json +2 -2
- package/task-queue/postgres/module.d.ts +1 -0
- package/task-queue/postgres/module.js +5 -1
- package/task-queue/postgres/schemas.d.ts +9 -6
- package/task-queue/postgres/schemas.js +4 -3
- package/task-queue/postgres/task-queue.d.ts +2 -12
- package/task-queue/postgres/task-queue.js +431 -354
- package/task-queue/postgres/task.model.d.ts +12 -5
- package/task-queue/postgres/task.model.js +51 -25
- package/task-queue/task-context.d.ts +2 -2
- package/task-queue/task-context.js +7 -7
- package/task-queue/task-queue.d.ts +36 -19
- package/task-queue/task-queue.js +18 -10
- package/task-queue/tests/cascading-cancellations.test.d.ts +1 -0
- package/task-queue/tests/cascading-cancellations.test.js +38 -0
- package/task-queue/tests/complex.test.js +44 -228
- package/task-queue/tests/coverage-branch.test.d.ts +1 -0
- package/task-queue/tests/coverage-branch.test.js +407 -0
- package/task-queue/tests/coverage-enhancement.test.d.ts +1 -0
- package/task-queue/tests/coverage-enhancement.test.js +144 -0
- package/task-queue/tests/dag-dependencies.test.d.ts +1 -0
- package/task-queue/tests/dag-dependencies.test.js +41 -0
- package/task-queue/tests/dependencies.test.js +26 -26
- package/task-queue/tests/extensive-dependencies.test.js +64 -139
- package/task-queue/tests/fan-out-spawning.test.d.ts +1 -0
- package/task-queue/tests/fan-out-spawning.test.js +53 -0
- package/task-queue/tests/idempotent-replacement.test.d.ts +1 -0
- package/task-queue/tests/idempotent-replacement.test.js +61 -0
- package/task-queue/tests/missing-idempotent-tasks.test.d.ts +1 -0
- package/task-queue/tests/missing-idempotent-tasks.test.js +38 -0
- package/task-queue/tests/queue.test.js +33 -24
- package/task-queue/tests/worker.test.js +20 -5
- package/task-queue/tests/zombie-parent.test.d.ts +1 -0
- package/task-queue/tests/zombie-parent.test.js +45 -0
- package/task-queue/tests/zombie-recovery.test.d.ts +1 -0
- package/task-queue/tests/zombie-recovery.test.js +51 -0
- package/test5.js +5 -5
- package/testing/integration-setup.d.ts +4 -4
- package/testing/integration-setup.js +54 -29
- package/text/localization.service.js +2 -2
- package/utils/file-reader.js +1 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
/** biome-ignore-all lint/nursery/noExcessiveClassesPerFile: <explanation> */
|
|
1
2
|
import { BaseEntity, type Json, type Timestamp } from '../../orm/index.js';
|
|
2
3
|
import type { ObjectLiteral, TypedOmit } from '../../types/types.js';
|
|
3
|
-
import {
|
|
4
|
+
import { type Task, TaskDependencyType, TaskStatus } from '../task-queue.js';
|
|
4
5
|
export declare abstract class PostgresTaskBase<Data extends ObjectLiteral = ObjectLiteral, State extends ObjectLiteral = ObjectLiteral, Result extends ObjectLiteral = ObjectLiteral> extends BaseEntity implements TypedOmit<Task, 'parentId'> {
|
|
5
6
|
namespace: string;
|
|
6
7
|
type: string;
|
|
@@ -8,12 +9,10 @@ export declare abstract class PostgresTaskBase<Data extends ObjectLiteral = Obje
|
|
|
8
9
|
idempotencyKey: string | null;
|
|
9
10
|
traceId: string | null;
|
|
10
11
|
tags: string[];
|
|
11
|
-
completeAfterTags: string[];
|
|
12
|
-
scheduleAfterTags: string[];
|
|
13
12
|
failFast: boolean;
|
|
14
|
-
dependencyJoinMode: DependencyJoinMode;
|
|
15
|
-
dependencyTriggerStatuses: TaskStatus[];
|
|
16
13
|
priority: number;
|
|
14
|
+
unresolvedScheduleDependencies: number;
|
|
15
|
+
unresolvedCompleteDependencies: number;
|
|
17
16
|
token: string | null;
|
|
18
17
|
creationTimestamp: Timestamp;
|
|
19
18
|
priorityAgeTimestamp: Timestamp;
|
|
@@ -37,3 +36,11 @@ export declare class PostgresTaskArchive<Data extends ObjectLiteral = ObjectLite
|
|
|
37
36
|
static readonly entityName = "TaskArchive";
|
|
38
37
|
parentId: string | null;
|
|
39
38
|
}
|
|
39
|
+
export declare class PostgresTaskDependency extends BaseEntity {
|
|
40
|
+
static readonly entityName = "TaskDependency";
|
|
41
|
+
namespace: string;
|
|
42
|
+
taskId: string;
|
|
43
|
+
dependencyTaskId: string;
|
|
44
|
+
type: TaskDependencyType;
|
|
45
|
+
requiredStatuses: TaskStatus[];
|
|
46
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** biome-ignore-all lint/nursery/noExcessiveClassesPerFile: <explanation> */
|
|
1
2
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
3
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
4
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -7,9 +8,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
8
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
10
|
};
|
|
10
|
-
import { BaseEntity, Index, JsonProperty,
|
|
11
|
+
import { BaseEntity, ForeignKey, Index, JsonProperty, Table, TimestampProperty, Unique, UuidProperty } from '../../orm/index.js';
|
|
11
12
|
import { Array as ArrayProperty, BooleanProperty, Enumeration, Integer, NumberProperty, StringProperty } from '../../schema/index.js';
|
|
12
|
-
import {
|
|
13
|
+
import { TaskDependencyType, TaskStatus } from '../task-queue.js';
|
|
13
14
|
export class PostgresTaskBase extends BaseEntity {
|
|
14
15
|
namespace;
|
|
15
16
|
type;
|
|
@@ -17,12 +18,10 @@ export class PostgresTaskBase extends BaseEntity {
|
|
|
17
18
|
idempotencyKey;
|
|
18
19
|
traceId;
|
|
19
20
|
tags;
|
|
20
|
-
completeAfterTags;
|
|
21
|
-
scheduleAfterTags;
|
|
22
21
|
failFast;
|
|
23
|
-
dependencyJoinMode;
|
|
24
|
-
dependencyTriggerStatuses;
|
|
25
22
|
priority;
|
|
23
|
+
unresolvedScheduleDependencies;
|
|
24
|
+
unresolvedCompleteDependencies;
|
|
26
25
|
token;
|
|
27
26
|
creationTimestamp;
|
|
28
27
|
priorityAgeTimestamp;
|
|
@@ -62,30 +61,22 @@ __decorate([
|
|
|
62
61
|
ArrayProperty(String),
|
|
63
62
|
__metadata("design:type", Array)
|
|
64
63
|
], PostgresTaskBase.prototype, "tags", void 0);
|
|
65
|
-
__decorate([
|
|
66
|
-
ArrayProperty(String),
|
|
67
|
-
__metadata("design:type", Array)
|
|
68
|
-
], PostgresTaskBase.prototype, "completeAfterTags", void 0);
|
|
69
|
-
__decorate([
|
|
70
|
-
ArrayProperty(String),
|
|
71
|
-
__metadata("design:type", Array)
|
|
72
|
-
], PostgresTaskBase.prototype, "scheduleAfterTags", void 0);
|
|
73
64
|
__decorate([
|
|
74
65
|
BooleanProperty(),
|
|
75
66
|
__metadata("design:type", Boolean)
|
|
76
67
|
], PostgresTaskBase.prototype, "failFast", void 0);
|
|
77
68
|
__decorate([
|
|
78
|
-
|
|
79
|
-
__metadata("design:type",
|
|
80
|
-
], PostgresTaskBase.prototype, "
|
|
69
|
+
Integer(),
|
|
70
|
+
__metadata("design:type", Number)
|
|
71
|
+
], PostgresTaskBase.prototype, "priority", void 0);
|
|
81
72
|
__decorate([
|
|
82
|
-
|
|
83
|
-
__metadata("design:type",
|
|
84
|
-
], PostgresTaskBase.prototype, "
|
|
73
|
+
Integer(),
|
|
74
|
+
__metadata("design:type", Number)
|
|
75
|
+
], PostgresTaskBase.prototype, "unresolvedScheduleDependencies", void 0);
|
|
85
76
|
__decorate([
|
|
86
77
|
Integer(),
|
|
87
78
|
__metadata("design:type", Number)
|
|
88
|
-
], PostgresTaskBase.prototype, "
|
|
79
|
+
], PostgresTaskBase.prototype, "unresolvedCompleteDependencies", void 0);
|
|
89
80
|
__decorate([
|
|
90
81
|
UuidProperty({ nullable: true }),
|
|
91
82
|
__metadata("design:type", Object)
|
|
@@ -147,20 +138,19 @@ let PostgresTask = class PostgresTask extends PostgresTaskBase {
|
|
|
147
138
|
parentId;
|
|
148
139
|
};
|
|
149
140
|
__decorate([
|
|
150
|
-
Reference(() => PostgresTask),
|
|
151
141
|
UuidProperty({ nullable: true }),
|
|
152
142
|
__metadata("design:type", Object)
|
|
153
143
|
], PostgresTask.prototype, "parentId", void 0);
|
|
154
144
|
PostgresTask = __decorate([
|
|
155
145
|
Table('task', { schema: 'task_queue' }),
|
|
156
146
|
Unique(['namespace', 'idempotencyKey']),
|
|
147
|
+
Unique(['namespace', 'id']),
|
|
157
148
|
Index(['namespace', 'status', 'scheduleTimestamp', 'priority']),
|
|
158
149
|
Index(['tags'], { using: 'gin' }),
|
|
159
|
-
Index(['completeAfterTags'], { using: 'gin' }),
|
|
160
|
-
Index(['scheduleAfterTags'], { using: 'gin' }),
|
|
161
150
|
Index(['status', 'completeTimestamp']),
|
|
162
151
|
Index(['status', 'visibilityDeadline']),
|
|
163
|
-
Index(['parentId'])
|
|
152
|
+
Index(['parentId']),
|
|
153
|
+
ForeignKey(() => PostgresTask, ['namespace', 'parentId'], ['namespace', 'id'])
|
|
164
154
|
], PostgresTask);
|
|
165
155
|
export { PostgresTask };
|
|
166
156
|
let PostgresTaskArchive = class PostgresTaskArchive extends PostgresTaskBase {
|
|
@@ -176,3 +166,39 @@ PostgresTaskArchive = __decorate([
|
|
|
176
166
|
Index(['namespace', 'completeTimestamp'])
|
|
177
167
|
], PostgresTaskArchive);
|
|
178
168
|
export { PostgresTaskArchive };
|
|
169
|
+
let PostgresTaskDependency = class PostgresTaskDependency extends BaseEntity {
|
|
170
|
+
static entityName = 'TaskDependency';
|
|
171
|
+
namespace;
|
|
172
|
+
taskId;
|
|
173
|
+
dependencyTaskId;
|
|
174
|
+
type;
|
|
175
|
+
requiredStatuses;
|
|
176
|
+
};
|
|
177
|
+
__decorate([
|
|
178
|
+
StringProperty(),
|
|
179
|
+
__metadata("design:type", String)
|
|
180
|
+
], PostgresTaskDependency.prototype, "namespace", void 0);
|
|
181
|
+
__decorate([
|
|
182
|
+
UuidProperty(),
|
|
183
|
+
__metadata("design:type", String)
|
|
184
|
+
], PostgresTaskDependency.prototype, "taskId", void 0);
|
|
185
|
+
__decorate([
|
|
186
|
+
UuidProperty(),
|
|
187
|
+
__metadata("design:type", String)
|
|
188
|
+
], PostgresTaskDependency.prototype, "dependencyTaskId", void 0);
|
|
189
|
+
__decorate([
|
|
190
|
+
Enumeration(TaskDependencyType),
|
|
191
|
+
__metadata("design:type", String)
|
|
192
|
+
], PostgresTaskDependency.prototype, "type", void 0);
|
|
193
|
+
__decorate([
|
|
194
|
+
Enumeration(TaskStatus, { array: true }),
|
|
195
|
+
__metadata("design:type", Array)
|
|
196
|
+
], PostgresTaskDependency.prototype, "requiredStatuses", void 0);
|
|
197
|
+
PostgresTaskDependency = __decorate([
|
|
198
|
+
Table('task_dependency', { schema: 'task_queue' }),
|
|
199
|
+
Unique(['namespace', 'taskId', 'dependencyTaskId', 'type']),
|
|
200
|
+
Index(['namespace', 'dependencyTaskId', 'type']),
|
|
201
|
+
ForeignKey(() => PostgresTask, ['namespace', 'taskId'], ['namespace', 'id'], { onDelete: 'cascade' }),
|
|
202
|
+
ForeignKey(() => PostgresTask, ['namespace', 'dependencyTaskId'], ['namespace', 'id'], { onDelete: 'cascade' })
|
|
203
|
+
], PostgresTaskDependency);
|
|
204
|
+
export { PostgresTaskDependency };
|
|
@@ -10,8 +10,8 @@ export declare class TaskContext<Definitions extends TaskDefinitionMap, Type ext
|
|
|
10
10
|
get type(): Type;
|
|
11
11
|
get parentId(): string | null;
|
|
12
12
|
get tags(): string[];
|
|
13
|
-
get
|
|
14
|
-
get
|
|
13
|
+
get unresolvedScheduleDependencies(): number;
|
|
14
|
+
get unresolvedCompleteDependencies(): number;
|
|
15
15
|
get data(): TaskData<Definitions, Type>;
|
|
16
16
|
get state(): TaskState<Definitions, Type> | null;
|
|
17
17
|
get attempt(): number;
|
|
@@ -24,11 +24,11 @@ export class TaskContext {
|
|
|
24
24
|
get tags() {
|
|
25
25
|
return this.#task.tags;
|
|
26
26
|
}
|
|
27
|
-
get
|
|
28
|
-
return this.#task.
|
|
27
|
+
get unresolvedScheduleDependencies() {
|
|
28
|
+
return this.#task.unresolvedScheduleDependencies;
|
|
29
29
|
}
|
|
30
|
-
get
|
|
31
|
-
return this.#task.
|
|
30
|
+
get unresolvedCompleteDependencies() {
|
|
31
|
+
return this.#task.unresolvedCompleteDependencies;
|
|
32
32
|
}
|
|
33
33
|
get data() {
|
|
34
34
|
return this.#task.data;
|
|
@@ -70,16 +70,16 @@ export class TaskContext {
|
|
|
70
70
|
const data = isForOtherQueue ? dataOrOptionsOrNothing : typeOrData;
|
|
71
71
|
const options = (isForOtherQueue ? optionsOrNothing : dataOrOptionsOrNothing);
|
|
72
72
|
if (isForOtherQueue) {
|
|
73
|
-
return await queueOrType.enqueue(type, data,
|
|
73
|
+
return await queueOrType.enqueue(type, data, options);
|
|
74
74
|
}
|
|
75
75
|
return await this.#queue.enqueue(type, data, { ...options, parentId: this.#task.id });
|
|
76
76
|
}
|
|
77
77
|
async spawnMany(queueOrItems, itemsOrNothing) {
|
|
78
78
|
const isForOtherQueue = isInstanceOf(queueOrItems, TaskQueue);
|
|
79
|
-
const items = (isForOtherQueue ? itemsOrNothing : queueOrItems).map((item) => ({ ...item, parentId: this.#task.id }));
|
|
80
79
|
if (isForOtherQueue) {
|
|
81
|
-
return await queueOrItems.enqueueMany(
|
|
80
|
+
return await queueOrItems.enqueueMany(itemsOrNothing, { returnTasks: true });
|
|
82
81
|
}
|
|
82
|
+
const items = queueOrItems.map((item) => ({ ...item, parentId: this.#task.id }));
|
|
83
83
|
return await this.#queue.enqueueMany(items, { returnTasks: true });
|
|
84
84
|
}
|
|
85
85
|
async reschedule(timestampOrDelay) {
|
|
@@ -18,36 +18,44 @@ export declare class TaskProcessResult<Result = unknown> {
|
|
|
18
18
|
}
|
|
19
19
|
export declare const TaskStatus: {
|
|
20
20
|
/**
|
|
21
|
-
* The task is
|
|
21
|
+
* The task is ready to be processed and is waiting for a worker.
|
|
22
22
|
*/
|
|
23
23
|
readonly Pending: "pending";
|
|
24
24
|
/**
|
|
25
|
-
* The task is currently being processed.
|
|
25
|
+
* The task is currently being processed by a worker.
|
|
26
26
|
*/
|
|
27
27
|
readonly Running: "running";
|
|
28
28
|
/**
|
|
29
|
-
* The task has been completed successfully.
|
|
29
|
+
* The task has been completed successfully and all its lifecycle requirements met.
|
|
30
30
|
*/
|
|
31
31
|
readonly Completed: "completed";
|
|
32
32
|
/**
|
|
33
|
-
* The task has been cancelled and will not be processed.
|
|
33
|
+
* The task has been cancelled and will not be processed further.
|
|
34
34
|
*/
|
|
35
35
|
readonly Cancelled: "cancelled";
|
|
36
36
|
/**
|
|
37
|
-
* The task
|
|
37
|
+
* The task has failed and will not be retried.
|
|
38
|
+
*/
|
|
39
|
+
readonly Dead: "dead";
|
|
40
|
+
/**
|
|
41
|
+
* The task is waiting for its pre-execution (schedule) dependencies to be met.
|
|
38
42
|
*/
|
|
39
43
|
readonly Waiting: "waiting";
|
|
40
44
|
/**
|
|
41
|
-
* The task has
|
|
45
|
+
* The task has finished execution but is waiting for its completion dependencies (children) to finish.
|
|
42
46
|
*/
|
|
43
|
-
readonly
|
|
47
|
+
readonly WaitingChildren: "waiting-children";
|
|
48
|
+
/**
|
|
49
|
+
* The task has been manually paused and will not be dequeued until resumed.
|
|
50
|
+
*/
|
|
51
|
+
readonly Paused: "paused";
|
|
44
52
|
};
|
|
45
53
|
export type TaskStatus = EnumType<typeof TaskStatus>;
|
|
46
|
-
export declare const
|
|
47
|
-
readonly
|
|
48
|
-
readonly
|
|
54
|
+
export declare const TaskDependencyType: {
|
|
55
|
+
readonly Schedule: "schedule";
|
|
56
|
+
readonly Complete: "complete";
|
|
49
57
|
};
|
|
50
|
-
export type
|
|
58
|
+
export type TaskDependencyType = EnumType<typeof TaskDependencyType>;
|
|
51
59
|
export type Task<Definitions extends TaskDefinitionMap = Record<string, {
|
|
52
60
|
data: unknown;
|
|
53
61
|
state: unknown;
|
|
@@ -67,11 +75,9 @@ export type Task<Definitions extends TaskDefinitionMap = Record<string, {
|
|
|
67
75
|
idempotencyKey: string | null;
|
|
68
76
|
traceId: string | null;
|
|
69
77
|
tags: string[];
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
unresolvedScheduleDependencies: number;
|
|
79
|
+
unresolvedCompleteDependencies: number;
|
|
72
80
|
failFast: boolean;
|
|
73
|
-
dependencyJoinMode: DependencyJoinMode;
|
|
74
|
-
dependencyTriggerStatuses: TaskStatus[];
|
|
75
81
|
data: TaskData<Definitions, Type>;
|
|
76
82
|
parentId: string | null;
|
|
77
83
|
tries: number;
|
|
@@ -108,11 +114,16 @@ export type EnqueueOptions = {
|
|
|
108
114
|
idempotencyKey?: string;
|
|
109
115
|
replace?: boolean;
|
|
110
116
|
tags?: string[];
|
|
111
|
-
|
|
112
|
-
|
|
117
|
+
scheduleAfter?: (string | {
|
|
118
|
+
id: string;
|
|
119
|
+
requiredStatuses?: TaskStatus[];
|
|
120
|
+
})[];
|
|
121
|
+
completeAfter?: (string | {
|
|
122
|
+
id: string;
|
|
123
|
+
requiredStatuses?: TaskStatus[];
|
|
124
|
+
})[];
|
|
113
125
|
failFast?: boolean;
|
|
114
|
-
|
|
115
|
-
dependencyTriggerStatuses?: TaskStatus[];
|
|
126
|
+
waitForCompletion?: boolean;
|
|
116
127
|
scheduleTimestamp?: number;
|
|
117
128
|
timeToLive?: number;
|
|
118
129
|
transaction?: Transaction;
|
|
@@ -197,6 +208,12 @@ export declare abstract class TaskQueue<Definitions extends TaskDefinitionMap =
|
|
|
197
208
|
abstract readonly maxTries: number;
|
|
198
209
|
batch(): TaskQueueEnqueueBatch<Definitions>;
|
|
199
210
|
abstract enqueue<Type extends TaskTypes<Definitions>>(type: Type, data: TaskData<Definitions, Type>, options?: EnqueueOneOptions): Promise<TaskOfType<Definitions, Type>>;
|
|
211
|
+
/**
|
|
212
|
+
* Enqueues multiple tasks.
|
|
213
|
+
* @param items The items to enqueue.
|
|
214
|
+
* @param options Enqueue options. If `returnTasks` is true, returns the enqueued tasks.
|
|
215
|
+
* **NOTE:** The order of returned tasks is NOT guaranteed to match the order of input items.
|
|
216
|
+
*/
|
|
200
217
|
abstract enqueueMany<Type extends TaskTypes<Definitions>>(items: EnqueueManyItem<Definitions, Type>[], options?: EnqueueManyOptions & {
|
|
201
218
|
returnTasks?: false;
|
|
202
219
|
}): Promise<void>;
|
package/task-queue/task-queue.js
CHANGED
|
@@ -81,33 +81,41 @@ export class TaskProcessResult {
|
|
|
81
81
|
}
|
|
82
82
|
export const TaskStatus = defineEnum('TaskStatus', {
|
|
83
83
|
/**
|
|
84
|
-
* The task is
|
|
84
|
+
* The task is ready to be processed and is waiting for a worker.
|
|
85
85
|
*/
|
|
86
86
|
Pending: 'pending',
|
|
87
87
|
/**
|
|
88
|
-
* The task is currently being processed.
|
|
88
|
+
* The task is currently being processed by a worker.
|
|
89
89
|
*/
|
|
90
90
|
Running: 'running',
|
|
91
91
|
/**
|
|
92
|
-
* The task has been completed successfully.
|
|
92
|
+
* The task has been completed successfully and all its lifecycle requirements met.
|
|
93
93
|
*/
|
|
94
94
|
Completed: 'completed',
|
|
95
95
|
/**
|
|
96
|
-
* The task has been cancelled and will not be processed.
|
|
96
|
+
* The task has been cancelled and will not be processed further.
|
|
97
97
|
*/
|
|
98
98
|
Cancelled: 'cancelled',
|
|
99
99
|
/**
|
|
100
|
-
* The task
|
|
100
|
+
* The task has failed and will not be retried.
|
|
101
|
+
*/
|
|
102
|
+
Dead: 'dead',
|
|
103
|
+
/**
|
|
104
|
+
* The task is waiting for its pre-execution (schedule) dependencies to be met.
|
|
101
105
|
*/
|
|
102
106
|
Waiting: 'waiting',
|
|
103
107
|
/**
|
|
104
|
-
* The task has
|
|
108
|
+
* The task has finished execution but is waiting for its completion dependencies (children) to finish.
|
|
105
109
|
*/
|
|
106
|
-
|
|
110
|
+
WaitingChildren: 'waiting-children',
|
|
111
|
+
/**
|
|
112
|
+
* The task has been manually paused and will not be dequeued until resumed.
|
|
113
|
+
*/
|
|
114
|
+
Paused: 'paused',
|
|
107
115
|
});
|
|
108
|
-
export const
|
|
109
|
-
|
|
110
|
-
|
|
116
|
+
export const TaskDependencyType = defineEnum('TaskDependencyType', {
|
|
117
|
+
Schedule: 'schedule',
|
|
118
|
+
Complete: 'complete',
|
|
111
119
|
});
|
|
112
120
|
export const defaultTaskPriority = 1000;
|
|
113
121
|
export const defaultQueueConfig = {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import { TaskQueueProvider, TaskStatus } from '../../task-queue/index.js';
|
|
3
|
+
import { setupIntegrationTest } from '../../testing/index.js';
|
|
4
|
+
describe('Cascading Cancellations', () => {
|
|
5
|
+
let injector;
|
|
6
|
+
let queue;
|
|
7
|
+
beforeAll(async () => {
|
|
8
|
+
({ injector } = await setupIntegrationTest({ modules: { taskQueue: true } }));
|
|
9
|
+
});
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
const queueProvider = injector.resolve(TaskQueueProvider);
|
|
12
|
+
const queueName = `cancellation-queue-${Date.now()}-${Math.random()}`;
|
|
13
|
+
queue = queueProvider.get(queueName, {
|
|
14
|
+
visibilityTimeout: 1000,
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
afterEach(async () => {
|
|
18
|
+
await queue.clear();
|
|
19
|
+
});
|
|
20
|
+
afterAll(async () => {
|
|
21
|
+
await injector?.dispose();
|
|
22
|
+
});
|
|
23
|
+
it('should recursively cancel children in ownership tree', async () => {
|
|
24
|
+
const root = await queue.enqueue('root', {});
|
|
25
|
+
const child1 = await queue.enqueue('child1', {}, { parentId: root.id });
|
|
26
|
+
const child2 = await queue.enqueue('child2', {}, { parentId: root.id });
|
|
27
|
+
const grandchild = await queue.enqueue('grandchild', {}, { parentId: child1.id });
|
|
28
|
+
await queue.cancel(root.id);
|
|
29
|
+
const uRoot = await queue.getTask(root.id);
|
|
30
|
+
const uChild1 = await queue.getTask(child1.id);
|
|
31
|
+
const uChild2 = await queue.getTask(child2.id);
|
|
32
|
+
const uGrandchild = await queue.getTask(grandchild.id);
|
|
33
|
+
expect(uRoot?.status).toBe(TaskStatus.Cancelled);
|
|
34
|
+
expect(uChild1?.status).toBe(TaskStatus.Cancelled);
|
|
35
|
+
expect(uChild2?.status).toBe(TaskStatus.Cancelled);
|
|
36
|
+
expect(uGrandchild?.status).toBe(TaskStatus.Cancelled);
|
|
37
|
+
});
|
|
38
|
+
});
|