@tstdl/base 0.93.139 → 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/README.md +166 -0
- package/ai/genkit/multi-region.plugin.js +5 -3
- package/ai/genkit/tests/multi-region.test.d.ts +1 -0
- package/ai/genkit/tests/multi-region.test.js +5 -2
- package/ai/parser/parser.js +2 -2
- package/ai/prompts/build.js +1 -0
- package/ai/prompts/instructions-formatter.d.ts +15 -2
- package/ai/prompts/instructions-formatter.js +36 -31
- package/ai/prompts/prompt-builder.js +5 -5
- package/ai/prompts/steering.d.ts +3 -2
- package/ai/prompts/steering.js +3 -1
- package/ai/tests/instructions-formatter.test.js +1 -0
- package/api/README.md +403 -0
- package/api/client/client.js +7 -13
- package/api/client/tests/api-client.test.js +10 -10
- package/api/default-error-handlers.js +1 -1
- package/api/response.d.ts +2 -2
- package/api/response.js +22 -33
- package/api/server/api-controller.d.ts +1 -1
- package/api/server/api-controller.js +3 -3
- package/api/server/api-request-token.provider.d.ts +1 -0
- package/api/server/api-request-token.provider.js +1 -0
- package/api/server/middlewares/allowed-methods.middleware.js +2 -1
- package/api/server/middlewares/content-type.middleware.js +2 -1
- package/api/types.d.ts +3 -2
- package/application/README.md +240 -0
- package/application/application.d.ts +1 -1
- package/application/application.js +3 -3
- package/application/providers.d.ts +20 -2
- package/application/providers.js +34 -7
- package/audit/README.md +267 -0
- package/audit/module.d.ts +5 -0
- package/audit/module.js +9 -1
- package/authentication/README.md +288 -0
- package/authentication/client/authentication.service.d.ts +12 -11
- package/authentication/client/authentication.service.js +21 -21
- package/authentication/client/http-client.middleware.js +2 -2
- 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-error-handling.test.js +2 -1
- package/authentication/tests/authentication.client-service-refresh.test.js +5 -3
- package/authentication/tests/authentication.client-service.test.js +1 -1
- package/browser/README.md +401 -0
- package/cancellation/README.md +156 -0
- package/cancellation/tests/coverage.test.d.ts +1 -0
- package/cancellation/tests/coverage.test.js +49 -0
- package/cancellation/tests/leak.test.js +24 -29
- package/cancellation/tests/token.test.d.ts +1 -0
- package/cancellation/tests/token.test.js +136 -0
- package/cancellation/token.d.ts +53 -177
- package/cancellation/token.js +132 -208
- package/circuit-breaker/postgres/module.d.ts +1 -0
- package/circuit-breaker/postgres/module.js +5 -1
- package/context/README.md +174 -0
- package/cookie/README.md +161 -0
- package/css/README.md +157 -0
- package/data-structures/README.md +320 -0
- package/decorators/README.md +140 -0
- package/distributed-loop/README.md +231 -0
- package/distributed-loop/distributed-loop.js +1 -1
- package/document-management/README.md +403 -0
- 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/server/services/document-management.service.js +9 -7
- 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-management-core.test.js +2 -7
- package/document-management/tests/document-management.api.test.js +6 -7
- package/document-management/tests/document-statistics.service.test.js +11 -12
- package/document-management/tests/document-validation-ai-overrides.test.js +0 -1
- package/document-management/tests/document.service.test.js +3 -3
- package/document-management/tests/enum-helpers.test.js +2 -3
- package/dom/README.md +213 -0
- package/enumerable/README.md +259 -0
- package/enumeration/README.md +121 -0
- package/errors/README.md +267 -0
- package/examples/document-management/main.d.ts +1 -0
- package/examples/document-management/main.js +14 -11
- package/file/README.md +191 -0
- package/formats/README.md +210 -0
- package/function/README.md +144 -0
- package/http/README.md +318 -0
- package/http/client/adapters/undici.adapter.js +1 -1
- package/http/client/http-client-request.d.ts +6 -5
- package/http/client/http-client-request.js +8 -9
- package/http/server/node/node-http-server.js +1 -2
- package/image-service/README.md +137 -0
- package/injector/README.md +491 -0
- package/intl/README.md +113 -0
- package/json-path/README.md +182 -0
- package/jsx/README.md +154 -0
- package/key-value-store/README.md +191 -0
- package/key-value-store/postgres/module.d.ts +1 -0
- package/key-value-store/postgres/module.js +5 -1
- package/lock/README.md +249 -0
- package/lock/postgres/module.d.ts +1 -0
- package/lock/postgres/module.js +5 -1
- package/lock/web/web-lock.js +119 -47
- package/logger/README.md +287 -0
- package/mail/README.md +256 -0
- package/mail/module.d.ts +5 -1
- package/mail/module.js +11 -6
- package/memory/README.md +144 -0
- package/message-bus/README.md +244 -0
- package/message-bus/message-bus-base.js +1 -1
- package/module/README.md +182 -0
- package/module/module.d.ts +1 -1
- package/module/module.js +77 -17
- package/module/modules/web-server.module.js +3 -4
- 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/notification/tests/notification-type.service.test.js +24 -15
- package/object-storage/README.md +300 -0
- package/openid-connect/README.md +274 -0
- package/orm/README.md +423 -0
- 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 +9 -6
- package/password/README.md +164 -0
- package/pdf/README.md +246 -0
- package/polyfills.js +1 -0
- package/pool/README.md +198 -0
- package/process/README.md +237 -0
- package/promise/README.md +252 -0
- package/promise/cancelable-promise.js +1 -1
- package/random/README.md +193 -0
- package/rate-limit/postgres/module.d.ts +1 -0
- package/rate-limit/postgres/module.js +5 -1
- package/reflection/README.md +305 -0
- package/reflection/decorator-data.js +11 -12
- package/rpc/README.md +386 -0
- package/rxjs-utils/README.md +262 -0
- package/schema/README.md +342 -0
- package/serializer/README.md +342 -0
- package/signals/implementation/README.md +134 -0
- package/sse/README.md +278 -0
- package/task-queue/README.md +293 -0
- 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 +4 -13
- package/task-queue/postgres/task-queue.js +462 -355
- 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 +8 -8
- package/task-queue/task-queue.d.ts +53 -19
- package/task-queue/task-queue.js +121 -55
- 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 +45 -229
- 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 +28 -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 +128 -8
- package/task-queue/tests/worker.test.js +39 -16
- 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/templates/README.md +287 -0
- package/test5.js +5 -5
- package/testing/README.md +157 -0
- package/testing/integration-setup.d.ts +4 -4
- package/testing/integration-setup.js +54 -29
- package/text/README.md +346 -0
- package/text/localization.service.js +2 -2
- package/threading/README.md +238 -0
- package/types/README.md +311 -0
- package/utils/README.md +322 -0
- package/utils/async-iterable-helpers/observable-iterable.d.ts +1 -1
- package/utils/async-iterable-helpers/observable-iterable.js +4 -8
- package/utils/async-iterable-helpers/take-until.js +4 -4
- package/utils/backoff.js +89 -30
- package/utils/file-reader.js +1 -2
- package/utils/retry-with-backoff.js +1 -1
- package/utils/timer.d.ts +1 -1
- package/utils/timer.js +5 -7
- package/utils/timing.d.ts +1 -1
- package/utils/timing.js +2 -4
- package/utils/z-base32.d.ts +1 -0
- package/utils/z-base32.js +1 -0
|
@@ -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;
|
|
@@ -46,7 +46,7 @@ export class TaskContext {
|
|
|
46
46
|
return this.triesLeft <= 0;
|
|
47
47
|
}
|
|
48
48
|
get signal() {
|
|
49
|
-
return this.#signal
|
|
49
|
+
return this.#signal;
|
|
50
50
|
}
|
|
51
51
|
get logger() {
|
|
52
52
|
return this.#logger;
|
|
@@ -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;
|
|
@@ -175,6 +186,14 @@ export type QueueConfig = {
|
|
|
175
186
|
export type TaskQueueArgument = string | (QueueConfig & {
|
|
176
187
|
namespace: string;
|
|
177
188
|
});
|
|
189
|
+
export type TaskQueueWaitOptions = {
|
|
190
|
+
interval?: number;
|
|
191
|
+
timeout?: number;
|
|
192
|
+
cancellationSignal?: CancellationSignal;
|
|
193
|
+
};
|
|
194
|
+
export type TaskQueueWaitResult = {
|
|
195
|
+
cancelled: boolean;
|
|
196
|
+
};
|
|
178
197
|
export declare const defaultQueueConfig: Required<QueueConfig>;
|
|
179
198
|
export declare abstract class TaskQueue<Definitions extends TaskDefinitionMap = TaskDefinitionMap> extends Transactional<QueueConfig & {
|
|
180
199
|
namespace: string;
|
|
@@ -189,6 +208,12 @@ export declare abstract class TaskQueue<Definitions extends TaskDefinitionMap =
|
|
|
189
208
|
abstract readonly maxTries: number;
|
|
190
209
|
batch(): TaskQueueEnqueueBatch<Definitions>;
|
|
191
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
|
+
*/
|
|
192
217
|
abstract enqueueMany<Type extends TaskTypes<Definitions>>(items: EnqueueManyItem<Definitions, Type>[], options?: EnqueueManyOptions & {
|
|
193
218
|
returnTasks?: false;
|
|
194
219
|
}): Promise<void>;
|
|
@@ -211,6 +236,15 @@ export declare abstract class TaskQueue<Definitions extends TaskDefinitionMap =
|
|
|
211
236
|
abstract getTree(rootId: string | string[], options?: {
|
|
212
237
|
transaction?: Transaction;
|
|
213
238
|
}): Promise<Task[]>;
|
|
239
|
+
/**
|
|
240
|
+
* Waits for the specified tasks to reach a finalized state (Completed, Cancelled, or Dead) or be removed/archived from queue (non-existent).
|
|
241
|
+
* @param ids The IDs of the tasks to wait for.
|
|
242
|
+
* @param options Timeout and cancellation options.
|
|
243
|
+
*/
|
|
244
|
+
abstract waitForTasks(ids: string[], options?: {
|
|
245
|
+
timeout?: number;
|
|
246
|
+
cancellationSignal?: CancellationSignal;
|
|
247
|
+
}): Promise<TaskQueueWaitResult>;
|
|
214
248
|
abstract cancel(id: string, options?: {
|
|
215
249
|
transaction?: Transaction;
|
|
216
250
|
}): Promise<void>;
|
package/task-queue/task-queue.js
CHANGED
|
@@ -1,3 +1,55 @@
|
|
|
1
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
+
var dispose, inner;
|
|
5
|
+
if (async) {
|
|
6
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
+
dispose = value[Symbol.asyncDispose];
|
|
8
|
+
}
|
|
9
|
+
if (dispose === void 0) {
|
|
10
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.dispose];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
+
}
|
|
18
|
+
else if (async) {
|
|
19
|
+
env.stack.push({ async: true });
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
+
return function (env) {
|
|
25
|
+
function fail(e) {
|
|
26
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
+
env.hasError = true;
|
|
28
|
+
}
|
|
29
|
+
var r, s = 0;
|
|
30
|
+
function next() {
|
|
31
|
+
while (r = env.stack.pop()) {
|
|
32
|
+
try {
|
|
33
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
+
if (r.dispose) {
|
|
35
|
+
var result = r.dispose.call(r.value);
|
|
36
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
+
}
|
|
38
|
+
else s |= 1;
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
fail(e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
+
if (env.hasError) throw env.error;
|
|
46
|
+
}
|
|
47
|
+
return next();
|
|
48
|
+
};
|
|
49
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
+
var e = new Error(message);
|
|
51
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
+
});
|
|
1
53
|
import { defineEnum } from '../enumeration/enumeration.js';
|
|
2
54
|
import { inject, injectArgument, Injector } from '../injector/index.js';
|
|
3
55
|
import { Logger } from '../logger/logger.js';
|
|
@@ -29,33 +81,41 @@ export class TaskProcessResult {
|
|
|
29
81
|
}
|
|
30
82
|
export const TaskStatus = defineEnum('TaskStatus', {
|
|
31
83
|
/**
|
|
32
|
-
* The task is
|
|
84
|
+
* The task is ready to be processed and is waiting for a worker.
|
|
33
85
|
*/
|
|
34
86
|
Pending: 'pending',
|
|
35
87
|
/**
|
|
36
|
-
* The task is currently being processed.
|
|
88
|
+
* The task is currently being processed by a worker.
|
|
37
89
|
*/
|
|
38
90
|
Running: 'running',
|
|
39
91
|
/**
|
|
40
|
-
* The task has been completed successfully.
|
|
92
|
+
* The task has been completed successfully and all its lifecycle requirements met.
|
|
41
93
|
*/
|
|
42
94
|
Completed: 'completed',
|
|
43
95
|
/**
|
|
44
|
-
* The task has been cancelled and will not be processed.
|
|
96
|
+
* The task has been cancelled and will not be processed further.
|
|
45
97
|
*/
|
|
46
98
|
Cancelled: 'cancelled',
|
|
47
99
|
/**
|
|
48
|
-
* 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.
|
|
49
105
|
*/
|
|
50
106
|
Waiting: 'waiting',
|
|
51
107
|
/**
|
|
52
|
-
* The task has
|
|
108
|
+
* The task has finished execution but is waiting for its completion dependencies (children) to finish.
|
|
53
109
|
*/
|
|
54
|
-
|
|
110
|
+
WaitingChildren: 'waiting-children',
|
|
111
|
+
/**
|
|
112
|
+
* The task has been manually paused and will not be dequeued until resumed.
|
|
113
|
+
*/
|
|
114
|
+
Paused: 'paused',
|
|
55
115
|
});
|
|
56
|
-
export const
|
|
57
|
-
|
|
58
|
-
|
|
116
|
+
export const TaskDependencyType = defineEnum('TaskDependencyType', {
|
|
117
|
+
Schedule: 'schedule',
|
|
118
|
+
Complete: 'complete',
|
|
59
119
|
});
|
|
60
120
|
export const defaultTaskPriority = 1000;
|
|
61
121
|
export const defaultQueueConfig = {
|
|
@@ -103,60 +163,66 @@ export class TaskQueue extends Transactional {
|
|
|
103
163
|
*/
|
|
104
164
|
async processWorker(cancellationSignal, handler, options) {
|
|
105
165
|
for await (const task of this.getConsumer(cancellationSignal, options)) {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
166
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
167
|
+
try {
|
|
168
|
+
const taskToken = __addDisposableResource(env_1, cancellationSignal.fork(), false);
|
|
169
|
+
const context = new TaskContext(this, task, taskToken, this.logger.with({ type: task.type }));
|
|
170
|
+
let isTaskActive = true;
|
|
171
|
+
context.logger.verbose(`Processing task`);
|
|
172
|
+
void (async () => {
|
|
173
|
+
while (taskToken.isUnset) {
|
|
174
|
+
await cancelableTimeout(Math.min(this.visibilityTimeout / 2, 5000), taskToken);
|
|
175
|
+
if (taskToken.isSet) {
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
const touchedTask = await this.touch(task);
|
|
180
|
+
if (isUndefined(touchedTask) && taskToken.isUnset) {
|
|
181
|
+
context.logger.warn(`Task lost lease. Aborting.`);
|
|
182
|
+
isTaskActive = false;
|
|
183
|
+
taskToken.set();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
context.logger.error('Error touching task', error);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
})();
|
|
191
|
+
try {
|
|
113
192
|
if (taskToken.isSet) {
|
|
114
|
-
|
|
193
|
+
throw new Error('Task cancelled before start');
|
|
115
194
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
195
|
+
const result = await handler(context);
|
|
196
|
+
if (isDefined(result) && isTaskActive) {
|
|
197
|
+
switch (result.payload.action) {
|
|
198
|
+
case 'complete':
|
|
199
|
+
context.logger.verbose(`Completing task`);
|
|
200
|
+
await this.complete(task, { result: result.payload.result });
|
|
201
|
+
break;
|
|
202
|
+
case 'fail':
|
|
203
|
+
context.logger.verbose(`Failing task`);
|
|
204
|
+
await this.fail(task, result.payload.error, { fatal: result.payload.fatal });
|
|
205
|
+
break;
|
|
206
|
+
case 'reschedule':
|
|
207
|
+
context.logger.verbose(`Rescheduling task`);
|
|
208
|
+
await this.reschedule(task.id, result.payload.timestamp);
|
|
209
|
+
break;
|
|
210
|
+
default:
|
|
211
|
+
throw new Error(`Unsupported task result action.`);
|
|
122
212
|
}
|
|
123
213
|
}
|
|
124
|
-
catch (error) {
|
|
125
|
-
context.logger.error('Error touching task', error);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
})();
|
|
129
|
-
try {
|
|
130
|
-
if (taskToken.isSet) {
|
|
131
|
-
throw new Error('Task cancelled before start');
|
|
132
214
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
case 'complete':
|
|
137
|
-
context.logger.verbose(`Completing task`);
|
|
138
|
-
await this.complete(task, { result: result.payload.result });
|
|
139
|
-
break;
|
|
140
|
-
case 'fail':
|
|
141
|
-
context.logger.verbose(`Failing task`);
|
|
142
|
-
await this.fail(task, result.payload.error, { fatal: result.payload.fatal });
|
|
143
|
-
break;
|
|
144
|
-
case 'reschedule':
|
|
145
|
-
context.logger.verbose(`Rescheduling task`);
|
|
146
|
-
await this.reschedule(task.id, result.payload.timestamp);
|
|
147
|
-
break;
|
|
148
|
-
default:
|
|
149
|
-
throw new Error(`Unsupported task result action.`);
|
|
150
|
-
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
context.logger.error('Error processing task', error);
|
|
217
|
+
await this.fail(task, error);
|
|
151
218
|
}
|
|
152
219
|
}
|
|
153
|
-
catch (
|
|
154
|
-
|
|
155
|
-
|
|
220
|
+
catch (e_1) {
|
|
221
|
+
env_1.error = e_1;
|
|
222
|
+
env_1.hasError = true;
|
|
156
223
|
}
|
|
157
224
|
finally {
|
|
158
|
-
|
|
159
|
-
taskToken.complete();
|
|
225
|
+
__disposeResources(env_1);
|
|
160
226
|
}
|
|
161
227
|
}
|
|
162
228
|
}
|
|
@@ -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
|
+
});
|