@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
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# Task Queue
|
|
2
|
+
|
|
3
|
+
A robust, type-safe, and distributed task orchestration system backed by PostgreSQL. It supports prioritization, hierarchical task dependencies, batch operations, circuit breaking, and automatic retries with exponential backoff.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [✨ Features](#-features)
|
|
8
|
+
- [Core Concepts](#core-concepts)
|
|
9
|
+
- [🚀 Basic Usage](#-basic-usage)
|
|
10
|
+
- [Configuration](#configuration)
|
|
11
|
+
- [Defining Tasks](#defining-tasks)
|
|
12
|
+
- [Enqueueing Tasks](#enqueueing-tasks)
|
|
13
|
+
- [Processing Tasks](#processing-tasks)
|
|
14
|
+
- [🔧 Advanced Topics](#-advanced-topics)
|
|
15
|
+
- [Task Hierarchies (Parent/Child)](#task-hierarchies-parentchild)
|
|
16
|
+
- [Batch Operations](#batch-operations)
|
|
17
|
+
- [Deduplication (Idempotency)](#deduplication-idempotency)
|
|
18
|
+
- [Prioritization](#prioritization)
|
|
19
|
+
- [Transactional Enqueueing](#transactional-enqueueing)
|
|
20
|
+
- [Manual Consumption](#manual-consumption)
|
|
21
|
+
- [📚 API](#-api)
|
|
22
|
+
|
|
23
|
+
## ✨ Features
|
|
24
|
+
|
|
25
|
+
- **PostgreSQL Backend**: Reliable persistence using Drizzle ORM with row-level locking (`SKIP LOCKED`) for safe concurrency.
|
|
26
|
+
- **Type-Safe**: Fully typed task data, state, and result payloads using a `TaskDefinitionMap`.
|
|
27
|
+
- **Task Hierarchies**: Support for parent-child relationships where parents wait for children to complete (Fan-Out/Fan-In).
|
|
28
|
+
- **Prioritization**: Integer-based priority system with automatic aging to prevent starvation.
|
|
29
|
+
- **Deduplication**: Idempotency keys with configurable strategies (`replace: true/false`) and retention windows.
|
|
30
|
+
- **Resilience**: Built-in Circuit Breaker, automatic retries with exponential backoff, and zombie task recovery.
|
|
31
|
+
- **Observability**: Tracks progress, state, and detailed error information.
|
|
32
|
+
|
|
33
|
+
## Core Concepts
|
|
34
|
+
|
|
35
|
+
### TaskQueue
|
|
36
|
+
|
|
37
|
+
The `TaskQueue<Definitions>` class is the primary entry point. It manages the lifecycle of tasks, handles persistence, and provides the worker loop abstraction.
|
|
38
|
+
|
|
39
|
+
### Task
|
|
40
|
+
|
|
41
|
+
A unit of work defined by its `type`. Key properties include:
|
|
42
|
+
|
|
43
|
+
- **Status**: `Pending` → `Running` → `Completed` (or `Failed`/`Dead`/`Cancelled`/`Waiting`).
|
|
44
|
+
- **Lease**: A temporary lock (`visibilityDeadline`) held by a worker during execution.
|
|
45
|
+
- **Tries**: Number of attempts made to process the task.
|
|
46
|
+
- **Data/State/Result**: Managed, type-safe JSON payloads.
|
|
47
|
+
|
|
48
|
+
### Worker
|
|
49
|
+
|
|
50
|
+
A function that processes tasks. The `TaskQueue` provides a managed loop (`process`) that handles:
|
|
51
|
+
|
|
52
|
+
1. **Dequeueing**: Locking tasks from the database.
|
|
53
|
+
2. **Heartbeating**: Automatically extending the lease (`touch`) while the worker runs.
|
|
54
|
+
3. **Completion**: Resolving the task state based on the handler's return value.
|
|
55
|
+
|
|
56
|
+
## 🚀 Basic Usage
|
|
57
|
+
|
|
58
|
+
### Configuration
|
|
59
|
+
|
|
60
|
+
Register the PostgreSQL backend in your application bootstrap.
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { configurePostgresTaskQueue } from '@tstdl/base/task-queue/postgres';
|
|
64
|
+
|
|
65
|
+
export async function bootstrap() {
|
|
66
|
+
// Configure the module
|
|
67
|
+
configurePostgresTaskQueue();
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Defining Tasks
|
|
72
|
+
|
|
73
|
+
Define your task types and their payload shapes using a `TaskDefinitionMap`.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { TaskDefinitionMap } from '@tstdl/base/task-queue';
|
|
77
|
+
|
|
78
|
+
export type MyTasks = TaskDefinitionMap<{
|
|
79
|
+
'send-email': {
|
|
80
|
+
data: { to: string; subject: string; body: string };
|
|
81
|
+
state: { sentAt?: number };
|
|
82
|
+
result: { messageId: string };
|
|
83
|
+
};
|
|
84
|
+
'generate-report': {
|
|
85
|
+
data: { reportId: string };
|
|
86
|
+
state: { progress: number };
|
|
87
|
+
result: void;
|
|
88
|
+
};
|
|
89
|
+
}>;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Enqueueing Tasks
|
|
93
|
+
|
|
94
|
+
Inject the `TaskQueue` service.
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { inject, Singleton } from '@tstdl/base/injector';
|
|
98
|
+
import { TaskQueue } from '@tstdl/base/task-queue';
|
|
99
|
+
|
|
100
|
+
@Singleton()
|
|
101
|
+
export class MailService {
|
|
102
|
+
// Inject a queue named 'mail-queue' with our definitions
|
|
103
|
+
readonly #queue = inject<TaskQueue<MyTasks>>(TaskQueue, 'mail-queue');
|
|
104
|
+
|
|
105
|
+
async sendLater(to: string, subject: string, body: string): Promise<void> {
|
|
106
|
+
await this.#queue.enqueue('send-email', { to, subject, body });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Processing Tasks
|
|
112
|
+
|
|
113
|
+
Start a worker to process tasks. The handler receives a `TaskContext` and must return a `TaskProcessResult`.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { inject, Singleton } from '@tstdl/base/injector';
|
|
117
|
+
import { Logger } from '@tstdl/base/logger';
|
|
118
|
+
import { CancellationSignal } from '@tstdl/base/cancellation';
|
|
119
|
+
import { TaskQueue, TaskProcessResult } from '@tstdl/base/task-queue';
|
|
120
|
+
|
|
121
|
+
@Singleton()
|
|
122
|
+
export class MailWorker {
|
|
123
|
+
readonly #queue = inject<TaskQueue<MyTasks>>(TaskQueue, 'mail-queue');
|
|
124
|
+
readonly #logger = inject(Logger, 'MailWorker');
|
|
125
|
+
|
|
126
|
+
start(signal: CancellationSignal): void {
|
|
127
|
+
this.#queue.process(
|
|
128
|
+
{
|
|
129
|
+
cancellationSignal: signal,
|
|
130
|
+
concurrency: 5, // Process up to 5 tasks concurrently
|
|
131
|
+
},
|
|
132
|
+
async (context) => {
|
|
133
|
+
this.#logger.info(`Sending mail to ${context.data.to}`);
|
|
134
|
+
|
|
135
|
+
const messageId = await sendEmail(context.data);
|
|
136
|
+
|
|
137
|
+
// Update state periodically if needed
|
|
138
|
+
await context.checkpoint({ state: { sentAt: Date.now() } });
|
|
139
|
+
|
|
140
|
+
return TaskProcessResult.Complete({ messageId });
|
|
141
|
+
},
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## 🔧 Advanced Topics
|
|
148
|
+
|
|
149
|
+
### Task Hierarchies (Parent/Child)
|
|
150
|
+
|
|
151
|
+
You can spawn child tasks from within a worker. The parent task will enter a `Waiting` state and will only transition back to `Pending` (or `Completed`) once all its children have reached a terminal state.
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
this.#queue.process({ cancellationSignal }, async (context) => {
|
|
155
|
+
// 1. Spawn child tasks. These are automatically linked to the current task.
|
|
156
|
+
await context.spawn('send-email', { to: 'admin@example.com', ... });
|
|
157
|
+
await context.spawn('send-email', { to: 'user@example.com', ... });
|
|
158
|
+
|
|
159
|
+
// 2. Complete the current execution.
|
|
160
|
+
// The task transitions to 'Waiting' until children finish.
|
|
161
|
+
return TaskProcessResult.Complete();
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Batch Operations
|
|
166
|
+
|
|
167
|
+
For high throughput, use batch operations to reduce database round-trips.
|
|
168
|
+
|
|
169
|
+
**Enqueueing:**
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
const batch = this.#queue.batch();
|
|
173
|
+
batch.add('send-email', { to: 'user1@example.com', ... });
|
|
174
|
+
batch.add('send-email', { to: 'user2@example.com', ... });
|
|
175
|
+
|
|
176
|
+
await batch.enqueue();
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Deduplication (Idempotency)
|
|
180
|
+
|
|
181
|
+
Prevent duplicate tasks using `idempotencyKey`.
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
// If a task with this key exists, this call does nothing (it returns the existing task).
|
|
185
|
+
await queue.enqueue('generate-report', data, {
|
|
186
|
+
idempotencyKey: 'report-2023-10',
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// Use 'replace: true' to update the existing task and reset it to 'Pending'.
|
|
190
|
+
await queue.enqueue('generate-report', data, {
|
|
191
|
+
idempotencyKey: 'report-2023-10',
|
|
192
|
+
replace: true,
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Prioritization
|
|
197
|
+
|
|
198
|
+
Tasks with lower priority numbers are processed first. The default is `1000`.
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
await queue.enqueue('type', data, { priority: 1 }); // High priority
|
|
202
|
+
await queue.enqueue('type', data, { priority: 9000 }); // Low priority
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Transactional Enqueueing
|
|
206
|
+
|
|
207
|
+
Enqueue tasks atomically within an existing database transaction. The task will only be visible to workers if the transaction commits.
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
import { inject } from '@tstdl/base/injector';
|
|
211
|
+
import { Database } from '@tstdl/base/orm/server';
|
|
212
|
+
|
|
213
|
+
const database = inject(Database);
|
|
214
|
+
|
|
215
|
+
await database.transaction(async (tx) => {
|
|
216
|
+
await userService.create(user, tx);
|
|
217
|
+
|
|
218
|
+
// Pass the transaction to the enqueue options
|
|
219
|
+
await queue.enqueue('welcome-email', { userId: user.id }, { transaction: tx });
|
|
220
|
+
});
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Manual Consumption
|
|
224
|
+
|
|
225
|
+
If you need full control over the consumption loop (e.g., for custom logic), use the async iterator.
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
async function runCustomWorker(queue: TaskQueue<any>, signal: CancellationSignal) {
|
|
229
|
+
for await (const task of queue.getConsumer(signal)) {
|
|
230
|
+
try {
|
|
231
|
+
// Manually touch to keep lease alive
|
|
232
|
+
await queue.touch(task);
|
|
233
|
+
|
|
234
|
+
// Do work...
|
|
235
|
+
|
|
236
|
+
// Manually complete
|
|
237
|
+
await queue.complete(task, { result: 'done' });
|
|
238
|
+
} catch (error) {
|
|
239
|
+
await queue.fail(task, error);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## 📚 API
|
|
246
|
+
|
|
247
|
+
### `TaskQueue<Definitions>`
|
|
248
|
+
|
|
249
|
+
| Method | Description |
|
|
250
|
+
| :------------------------------- | :------------------------------------------------------------------------------------- |
|
|
251
|
+
| `enqueue(type, data, options?)` | Adds a single task to the queue. |
|
|
252
|
+
| `enqueueMany(items, options?)` | Adds multiple tasks efficiently. |
|
|
253
|
+
| `batch()` | Returns a `TaskQueueEnqueueBatch` builder. |
|
|
254
|
+
| `waitForTasks(ids, options?)` | Reactive waiting for tasks to reach a finalized state (Completed, Dead, or Cancelled). |
|
|
255
|
+
| `process(options, handler)` | Starts a managed worker loop for single tasks. |
|
|
256
|
+
| `dequeue(options?)` | Locks and retrieves the next available task(s). |
|
|
257
|
+
| `complete(task, options?)` | Marks a task as completed. |
|
|
258
|
+
| `fail(task, error, options?)` | Marks a task as failed. Retries if `fatal` is false and tries remain. |
|
|
259
|
+
| `touch(task, options?)` | Extends the worker lease and optionally updates progress/state. |
|
|
260
|
+
| `cancel(id, options?)` | Cancels a task and optionally its descendants. |
|
|
261
|
+
| `getTree(id, options?)` | Retrieves a task and all its descendants. |
|
|
262
|
+
| `reschedule(id, time, options?)` | Sets a new schedule timestamp for a task. |
|
|
263
|
+
|
|
264
|
+
### `TaskContext<Definitions, Type>`
|
|
265
|
+
|
|
266
|
+
Passed to the worker handler.
|
|
267
|
+
|
|
268
|
+
| Property/Method | Description |
|
|
269
|
+
| :---------------------------- | :------------------------------------------------------------------- |
|
|
270
|
+
| `data` | The input data for the task. |
|
|
271
|
+
| `state` | The current state of the task. |
|
|
272
|
+
| `attempt` | Current attempt number (starts at 1). |
|
|
273
|
+
| `spawn(type, data, options?)` | Creates a child task linked to the current task. |
|
|
274
|
+
| `spawnMany(items)` | Creates multiple child tasks. |
|
|
275
|
+
| `checkpoint(options?)` | Updates progress/state and extends the lease. |
|
|
276
|
+
| `reschedule(time)` | Stops execution and reschedules for a future time. |
|
|
277
|
+
| `complete(result?)` | Manually completes the task (alternative to returning from handler). |
|
|
278
|
+
| `fail(error, fatal?)` | Manually fails the task. |
|
|
279
|
+
|
|
280
|
+
### `QueueConfig`
|
|
281
|
+
|
|
282
|
+
| Property | Default | Description |
|
|
283
|
+
| :------------------------ | :------ | :------------------------------------------------- |
|
|
284
|
+
| `visibilityTimeout` | `5m` | Duration before a worker token is considered lost. |
|
|
285
|
+
| `maxExecutionTime` | `60m` | Hard limit for `Running` state. |
|
|
286
|
+
| `maxTries` | `3` | Maximum dequeue attempts allowed. |
|
|
287
|
+
| `retention` | `30d` | Duration to retain terminal tasks before archival. |
|
|
288
|
+
| `globalConcurrency` | `null` | Max simultaneous running tasks across all workers. |
|
|
289
|
+
| `circuitBreakerThreshold` | `5` | Failures before tripping the circuit breaker. |
|
|
290
|
+
| `retryDelayMinimum` | `5s` | Floor for exponential backoff delay. |
|
|
291
|
+
| `retryDelayMaximum` | `5m` | Ceiling for exponential backoff delay. |
|
|
292
|
+
| `idempotencyWindow` | `1h` | Time to retain non-replaced idempotency keys. |
|
|
293
|
+
| `priorityAgingInterval` | `1m` | Interval for automatic priority promotion. |
|
package/task-queue/postgres/drizzle/{0000_simple_invisible_woman.sql → 0000_wakeful_sunspot.sql}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
CREATE TYPE "task_queue"."
|
|
2
|
-
CREATE TYPE "task_queue"."task_status" AS ENUM('pending', 'running', 'completed', 'cancelled', 'waiting', '
|
|
1
|
+
CREATE TYPE "task_queue"."task_dependency_type" AS ENUM('schedule', 'complete');--> statement-breakpoint
|
|
2
|
+
CREATE TYPE "task_queue"."task_status" AS ENUM('pending', 'running', 'completed', 'cancelled', 'dead', 'waiting', 'waiting-children', 'paused');--> statement-breakpoint
|
|
3
3
|
CREATE TABLE "task_queue"."task" (
|
|
4
4
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
5
5
|
"namespace" text NOT NULL,
|
|
@@ -8,12 +8,10 @@ CREATE TABLE "task_queue"."task" (
|
|
|
8
8
|
"idempotency_key" text,
|
|
9
9
|
"trace_id" text,
|
|
10
10
|
"tags" text[] NOT NULL,
|
|
11
|
-
"complete_after_tags" text[] NOT NULL,
|
|
12
|
-
"schedule_after_tags" text[] NOT NULL,
|
|
13
11
|
"fail_fast" boolean NOT NULL,
|
|
14
|
-
"dependency_join_mode" "task_queue"."dependency_join_mode" NOT NULL,
|
|
15
|
-
"dependency_trigger_statuses" "task_queue"."task_status"[] NOT NULL,
|
|
16
12
|
"priority" integer NOT NULL,
|
|
13
|
+
"unresolved_schedule_dependencies" integer NOT NULL,
|
|
14
|
+
"unresolved_complete_dependencies" integer NOT NULL,
|
|
17
15
|
"token" uuid,
|
|
18
16
|
"creation_timestamp" timestamp with time zone NOT NULL,
|
|
19
17
|
"priority_age_timestamp" timestamp with time zone NOT NULL,
|
|
@@ -29,6 +27,7 @@ CREATE TABLE "task_queue"."task" (
|
|
|
29
27
|
"result" jsonb,
|
|
30
28
|
"error" jsonb,
|
|
31
29
|
"parent_id" uuid,
|
|
30
|
+
CONSTRAINT "task_namespace_id_unique" UNIQUE("namespace","id"),
|
|
32
31
|
CONSTRAINT "task_namespace_idempotency_key_unique" UNIQUE("namespace","idempotency_key")
|
|
33
32
|
);
|
|
34
33
|
--> statement-breakpoint
|
|
@@ -40,12 +39,10 @@ CREATE TABLE "task_queue"."task_archive" (
|
|
|
40
39
|
"idempotency_key" text,
|
|
41
40
|
"trace_id" text,
|
|
42
41
|
"tags" text[] NOT NULL,
|
|
43
|
-
"complete_after_tags" text[] NOT NULL,
|
|
44
|
-
"schedule_after_tags" text[] NOT NULL,
|
|
45
42
|
"fail_fast" boolean NOT NULL,
|
|
46
|
-
"dependency_join_mode" "task_queue"."dependency_join_mode" NOT NULL,
|
|
47
|
-
"dependency_trigger_statuses" "task_queue"."task_status"[] NOT NULL,
|
|
48
43
|
"priority" integer NOT NULL,
|
|
44
|
+
"unresolved_schedule_dependencies" integer NOT NULL,
|
|
45
|
+
"unresolved_complete_dependencies" integer NOT NULL,
|
|
49
46
|
"token" uuid,
|
|
50
47
|
"creation_timestamp" timestamp with time zone NOT NULL,
|
|
51
48
|
"priority_age_timestamp" timestamp with time zone NOT NULL,
|
|
@@ -63,12 +60,23 @@ CREATE TABLE "task_queue"."task_archive" (
|
|
|
63
60
|
"parent_id" uuid
|
|
64
61
|
);
|
|
65
62
|
--> statement-breakpoint
|
|
66
|
-
|
|
63
|
+
CREATE TABLE "task_queue"."task_dependency" (
|
|
64
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
65
|
+
"namespace" text NOT NULL,
|
|
66
|
+
"task_id" uuid NOT NULL,
|
|
67
|
+
"dependency_task_id" uuid NOT NULL,
|
|
68
|
+
"type" "task_queue"."task_dependency_type" NOT NULL,
|
|
69
|
+
"required_statuses" "task_queue"."task_status"[] NOT NULL,
|
|
70
|
+
CONSTRAINT "td_namespace_task_id_dependency_task_id_type_unique" UNIQUE("namespace","task_id","dependency_task_id","type")
|
|
71
|
+
);
|
|
72
|
+
--> statement-breakpoint
|
|
73
|
+
ALTER TABLE "task_queue"."task" ADD CONSTRAINT "task_namespace_parentId_task_fkey" FOREIGN KEY ("namespace","parent_id") REFERENCES "task_queue"."task"("namespace","id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
74
|
+
ALTER TABLE "task_queue"."task_dependency" ADD CONSTRAINT "task_dependency_namespace_dependencyTaskId_task_fkey" FOREIGN KEY ("namespace","dependency_task_id") REFERENCES "task_queue"."task"("namespace","id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
75
|
+
ALTER TABLE "task_queue"."task_dependency" ADD CONSTRAINT "task_dependency_namespace_taskId_task_fkey" FOREIGN KEY ("namespace","task_id") REFERENCES "task_queue"."task"("namespace","id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
67
76
|
CREATE INDEX "task_parent_id_idx" ON "task_queue"."task" USING btree ("parent_id");--> statement-breakpoint
|
|
68
77
|
CREATE INDEX "task_status_visibility_deadline_idx" ON "task_queue"."task" USING btree ("status","visibility_deadline");--> statement-breakpoint
|
|
69
78
|
CREATE INDEX "task_status_complete_timestamp_idx" ON "task_queue"."task" USING btree ("status","complete_timestamp");--> statement-breakpoint
|
|
70
|
-
CREATE INDEX "task_schedule_after_tags_idx" ON "task_queue"."task" USING gin ("schedule_after_tags");--> statement-breakpoint
|
|
71
|
-
CREATE INDEX "task_complete_after_tags_idx" ON "task_queue"."task" USING gin ("complete_after_tags");--> statement-breakpoint
|
|
72
79
|
CREATE INDEX "task_tags_idx" ON "task_queue"."task" USING gin ("tags");--> statement-breakpoint
|
|
73
80
|
CREATE INDEX "task_namespace_status_schedule_timestamp_priority_idx" ON "task_queue"."task" USING btree ("namespace","status","schedule_timestamp","priority");--> statement-breakpoint
|
|
74
|
-
CREATE INDEX "task_archive_namespace_complete_timestamp_idx" ON "task_queue"."task_archive" USING btree ("namespace","complete_timestamp")
|
|
81
|
+
CREATE INDEX "task_archive_namespace_complete_timestamp_idx" ON "task_queue"."task_archive" USING btree ("namespace","complete_timestamp");--> statement-breakpoint
|
|
82
|
+
CREATE INDEX "task_dependency_namespace_dependency_task_id_type_idx" ON "task_queue"."task_dependency" USING btree ("namespace","dependency_task_id","type");
|