@tstdl/base 0.93.141 → 0.93.142

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.
Files changed (71) hide show
  1. package/authentication/client/authentication.service.d.ts +1 -0
  2. package/authentication/client/authentication.service.js +3 -2
  3. package/circuit-breaker/circuit-breaker.d.ts +6 -4
  4. package/circuit-breaker/postgres/circuit-breaker.d.ts +1 -0
  5. package/circuit-breaker/postgres/circuit-breaker.js +8 -5
  6. package/circuit-breaker/tests/circuit-breaker.test.js +20 -0
  7. package/examples/document-management/main.js +2 -2
  8. package/notification/tests/notification-api.test.js +5 -1
  9. package/notification/tests/notification-flow.test.js +9 -6
  10. package/orm/decorators.d.ts +17 -4
  11. package/orm/decorators.js +9 -0
  12. package/orm/server/bootstrap.d.ts +11 -0
  13. package/orm/server/bootstrap.js +31 -0
  14. package/orm/server/drizzle/schema-converter.d.ts +3 -1
  15. package/orm/server/drizzle/schema-converter.js +71 -29
  16. package/orm/server/extension.d.ts +14 -0
  17. package/orm/server/extension.js +27 -0
  18. package/orm/server/index.d.ts +2 -0
  19. package/orm/server/index.js +2 -0
  20. package/orm/server/migration.d.ts +2 -3
  21. package/orm/server/migration.js +7 -21
  22. package/orm/server/repository.d.ts +1 -0
  23. package/orm/server/repository.js +19 -9
  24. package/orm/server/transaction.d.ts +1 -0
  25. package/orm/server/transaction.js +3 -0
  26. package/orm/tests/database-extension.test.js +63 -0
  27. package/orm/tests/database-migration.test.js +7 -6
  28. package/orm/tests/repository-compound-primary-key.test.d.ts +2 -0
  29. package/orm/tests/repository-compound-primary-key.test.js +234 -0
  30. package/orm/tests/schema-generation.test.d.ts +1 -0
  31. package/orm/tests/schema-generation.test.js +52 -5
  32. package/package.json +4 -4
  33. package/task-queue/README.md +0 -1
  34. package/task-queue/postgres/drizzle/0000_great_gwen_stacy.sql +84 -0
  35. package/task-queue/postgres/drizzle/meta/0000_snapshot.json +151 -68
  36. package/task-queue/postgres/drizzle/meta/_journal.json +2 -2
  37. package/task-queue/postgres/module.js +2 -1
  38. package/task-queue/postgres/schemas.d.ts +6 -0
  39. package/task-queue/postgres/task-queue.d.ts +18 -5
  40. package/task-queue/postgres/task-queue.js +593 -372
  41. package/task-queue/postgres/task.model.d.ts +9 -5
  42. package/task-queue/postgres/task.model.js +26 -26
  43. package/task-queue/task-context.d.ts +10 -5
  44. package/task-queue/task-context.js +5 -3
  45. package/task-queue/task-queue.d.ts +339 -35
  46. package/task-queue/task-queue.js +135 -31
  47. package/task-queue/tests/coverage-branch.test.js +45 -57
  48. package/task-queue/tests/coverage-enhancement.test.js +123 -117
  49. package/task-queue/tests/{extensive-dependencies.test.js → dag.test.js} +61 -32
  50. package/task-queue/tests/dependencies.test.js +139 -21
  51. package/task-queue/tests/enqueue-batch.test.js +125 -0
  52. package/task-queue/tests/fan-out-spawning.test.js +43 -2
  53. package/task-queue/tests/idempotent-replacement.test.js +54 -1
  54. package/task-queue/tests/missing-idempotent-tasks.test.js +9 -8
  55. package/task-queue/tests/queue.test.js +261 -25
  56. package/task-queue/tests/shutdown.test.js +41 -0
  57. package/task-queue/tests/transactions.test.d.ts +1 -0
  58. package/task-queue/tests/transactions.test.js +47 -0
  59. package/task-queue/tests/worker.test.js +46 -13
  60. package/task-queue/tests/zombie-parent.test.js +1 -1
  61. package/task-queue/tests/zombie-recovery.test.js +3 -3
  62. package/testing/integration-setup.js +5 -3
  63. package/utils/timing.d.ts +2 -2
  64. package/task-queue/postgres/drizzle/0000_wakeful_sunspot.sql +0 -82
  65. package/task-queue/tests/cascading-cancellations.test.js +0 -38
  66. package/task-queue/tests/complex.test.js +0 -122
  67. package/task-queue/tests/dag-dependencies.test.js +0 -41
  68. /package/{task-queue/tests/cascading-cancellations.test.d.ts → orm/tests/database-extension.test.d.ts} +0 -0
  69. /package/task-queue/tests/{complex.test.d.ts → dag.test.d.ts} +0 -0
  70. /package/task-queue/tests/{dag-dependencies.test.d.ts → enqueue-batch.test.d.ts} +0 -0
  71. /package/task-queue/tests/{extensive-dependencies.test.d.ts → shutdown.test.d.ts} +0 -0
@@ -1,13 +1,20 @@
1
1
  /** biome-ignore-all lint/nursery/noExcessiveClassesPerFile: <explanation> */
2
2
  import { BaseEntity, type Json, type Timestamp } from '../../orm/index.js';
3
- import type { ObjectLiteral, TypedOmit } from '../../types/types.js';
3
+ import type { ObjectLiteral } from '../../types/types.js';
4
4
  import { type Task, TaskDependencyType, TaskStatus } from '../task-queue.js';
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
+ export declare const terminalStatuses: TaskStatus[];
6
+ export declare const finalizedStatuses: TaskStatus[];
7
+ export declare const nonFinalizedStatuses: TaskStatus[];
8
+ export declare const queueableStatuses: TaskStatus[];
9
+ export declare const waitableStatuses: TaskStatus[];
10
+ export declare const queueableOrWaitableStatuses: TaskStatus[];
11
+ export declare abstract class PostgresTaskBase<Data extends ObjectLiteral = ObjectLiteral, State extends ObjectLiteral = ObjectLiteral, Result extends ObjectLiteral = ObjectLiteral> extends BaseEntity implements Task {
6
12
  namespace: string;
7
13
  type: string;
8
14
  status: TaskStatus;
9
15
  idempotencyKey: string | null;
10
16
  traceId: string | null;
17
+ parentId: string | null;
11
18
  tags: string[];
12
19
  failFast: boolean;
13
20
  priority: number;
@@ -30,15 +37,12 @@ export declare abstract class PostgresTaskBase<Data extends ObjectLiteral = Obje
30
37
  }
31
38
  export declare class PostgresTask<Data extends ObjectLiteral = ObjectLiteral, State extends ObjectLiteral = ObjectLiteral, Result extends ObjectLiteral = ObjectLiteral> extends PostgresTaskBase<Data, State, Result> implements Task {
32
39
  static readonly entityName = "Task";
33
- parentId: string | null;
34
40
  }
35
41
  export declare class PostgresTaskArchive<Data extends ObjectLiteral = ObjectLiteral, State extends ObjectLiteral = ObjectLiteral, Result extends ObjectLiteral = ObjectLiteral> extends PostgresTaskBase<Data, State, Result> implements PostgresTask<Data, State, Result> {
36
42
  static readonly entityName = "TaskArchive";
37
- parentId: string | null;
38
43
  }
39
44
  export declare class PostgresTaskDependency extends BaseEntity {
40
45
  static readonly entityName = "TaskDependency";
41
- namespace: string;
42
46
  taskId: string;
43
47
  dependencyTaskId: string;
44
48
  type: TaskDependencyType;
@@ -10,13 +10,21 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  };
11
11
  import { BaseEntity, ForeignKey, Index, JsonProperty, Table, TimestampProperty, Unique, UuidProperty } from '../../orm/index.js';
12
12
  import { Array as ArrayProperty, BooleanProperty, Enumeration, Integer, NumberProperty, StringProperty } from '../../schema/index.js';
13
+ import { isNotNull } from 'drizzle-orm';
13
14
  import { TaskDependencyType, TaskStatus } from '../task-queue.js';
15
+ export const terminalStatuses = [TaskStatus.Completed, TaskStatus.Cancelled, TaskStatus.Dead, TaskStatus.TimedOut, TaskStatus.Expired, TaskStatus.Skipped, TaskStatus.Orphaned];
16
+ export const finalizedStatuses = terminalStatuses;
17
+ export const nonFinalizedStatuses = [TaskStatus.Pending, TaskStatus.Retrying, TaskStatus.Waiting, TaskStatus.WaitingChildren, TaskStatus.Running];
18
+ export const queueableStatuses = [TaskStatus.Pending, TaskStatus.Retrying];
19
+ export const waitableStatuses = [TaskStatus.Waiting, TaskStatus.WaitingChildren];
20
+ export const queueableOrWaitableStatuses = [...queueableStatuses, ...waitableStatuses];
14
21
  export class PostgresTaskBase extends BaseEntity {
15
22
  namespace;
16
23
  type;
17
24
  status;
18
25
  idempotencyKey;
19
26
  traceId;
27
+ parentId;
20
28
  tags;
21
29
  failFast;
22
30
  priority;
@@ -57,6 +65,10 @@ __decorate([
57
65
  StringProperty({ nullable: true }),
58
66
  __metadata("design:type", Object)
59
67
  ], PostgresTaskBase.prototype, "traceId", void 0);
68
+ __decorate([
69
+ UuidProperty({ nullable: true }),
70
+ __metadata("design:type", Object)
71
+ ], PostgresTaskBase.prototype, "parentId", void 0);
60
72
  __decorate([
61
73
  ArrayProperty(String),
62
74
  __metadata("design:type", Array)
@@ -135,32 +147,25 @@ __decorate([
135
147
  ], PostgresTaskBase.prototype, "error", void 0);
136
148
  let PostgresTask = class PostgresTask extends PostgresTaskBase {
137
149
  static entityName = 'Task';
138
- parentId;
139
150
  };
140
- __decorate([
141
- UuidProperty({ nullable: true }),
142
- __metadata("design:type", Object)
143
- ], PostgresTask.prototype, "parentId", void 0);
144
151
  PostgresTask = __decorate([
145
152
  Table('task', { schema: 'task_queue' }),
146
153
  Unique(['namespace', 'idempotencyKey']),
147
- Unique(['namespace', 'id']),
148
- Index(['namespace', 'status', 'scheduleTimestamp', 'priority']),
149
- Index(['tags'], { using: 'gin' }),
150
- Index(['status', 'completeTimestamp']),
151
- Index(['status', 'visibilityDeadline']),
152
- Index(['parentId']),
153
- ForeignKey(() => PostgresTask, ['namespace', 'parentId'], ['namespace', 'id'])
154
+ Index(['namespace', 'tags'], { using: 'gin' }),
155
+ Index(['namespace', 'priority', 'scheduleTimestamp'], { where: () => ({ status: { $in: queueableStatuses } }) }),
156
+ Index(['namespace', 'type', 'priority', 'scheduleTimestamp'], { where: () => ({ status: { $in: queueableStatuses } }) }),
157
+ Index(['namespace', 'priorityAgeTimestamp'], { where: () => ({ status: { $in: queueableStatuses } }) }),
158
+ Index(['namespace', 'timeToLive'], { where: () => ({ status: { $in: queueableOrWaitableStatuses } }) }),
159
+ Index(['namespace', 'visibilityDeadline'], { where: () => ({ status: TaskStatus.Running }) }),
160
+ Index(['namespace', 'startTimestamp'], { where: () => ({ status: TaskStatus.Running }) }),
161
+ Index(['namespace', 'completeTimestamp'], { where: () => ({ status: { $in: terminalStatuses } }) }),
162
+ Index(['parentId'], { where: (table) => isNotNull(table.parentId) }),
163
+ ForeignKey(() => PostgresTask, ['parentId'], ['id'])
154
164
  ], PostgresTask);
155
165
  export { PostgresTask };
156
166
  let PostgresTaskArchive = class PostgresTaskArchive extends PostgresTaskBase {
157
167
  static entityName = 'TaskArchive';
158
- parentId;
159
168
  };
160
- __decorate([
161
- UuidProperty({ nullable: true }),
162
- __metadata("design:type", Object)
163
- ], PostgresTaskArchive.prototype, "parentId", void 0);
164
169
  PostgresTaskArchive = __decorate([
165
170
  Table('task_archive', { schema: 'task_queue' }),
166
171
  Index(['namespace', 'completeTimestamp'])
@@ -168,16 +173,11 @@ PostgresTaskArchive = __decorate([
168
173
  export { PostgresTaskArchive };
169
174
  let PostgresTaskDependency = class PostgresTaskDependency extends BaseEntity {
170
175
  static entityName = 'TaskDependency';
171
- namespace;
172
176
  taskId;
173
177
  dependencyTaskId;
174
178
  type;
175
179
  requiredStatuses;
176
180
  };
177
- __decorate([
178
- StringProperty(),
179
- __metadata("design:type", String)
180
- ], PostgresTaskDependency.prototype, "namespace", void 0);
181
181
  __decorate([
182
182
  UuidProperty(),
183
183
  __metadata("design:type", String)
@@ -196,9 +196,9 @@ __decorate([
196
196
  ], PostgresTaskDependency.prototype, "requiredStatuses", void 0);
197
197
  PostgresTaskDependency = __decorate([
198
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' })
199
+ Unique(['taskId', 'dependencyTaskId', 'type']),
200
+ Index(['dependencyTaskId', 'type']),
201
+ ForeignKey(() => PostgresTask, ['taskId'], ['id'], { onDelete: 'cascade' }),
202
+ ForeignKey(() => PostgresTask, ['dependencyTaskId'], ['id'], { onDelete: 'cascade' })
203
203
  ], PostgresTaskDependency);
204
204
  export { PostgresTaskDependency };
@@ -3,7 +3,7 @@ import type { Logger } from '../logger/index.js';
3
3
  import type { Transaction } from '../orm/server/index.js';
4
4
  import { TaskQueue, type EnqueueManyItem, type EnqueueOptions } from './task-queue.js';
5
5
  import type { TaskData, TaskDefinitionMap, TaskOfType, TaskResult, TaskState, TaskTypes } from './types.js';
6
- export declare class TaskContext<Definitions extends TaskDefinitionMap, Type extends TaskTypes<Definitions> = TaskTypes<Definitions>> {
6
+ declare class TaskContextImplementation<Definitions extends TaskDefinitionMap, Type extends TaskTypes<Definitions> = TaskTypes<Definitions>> {
7
7
  #private;
8
8
  constructor(queue: TaskQueue<Definitions>, task: TaskOfType<Definitions, Type>, signal: CancellationToken, logger: Logger);
9
9
  get id(): string;
@@ -27,10 +27,10 @@ export declare class TaskContext<Definitions extends TaskDefinitionMap, Type ext
27
27
  state?: TaskState<Definitions, Type>;
28
28
  transaction?: Transaction;
29
29
  }): Promise<void>;
30
- spawn<Type extends TaskTypes<Definitions>>(type: Type, data: TaskData<Definitions, Type>, options?: Omit<EnqueueOptions, 'parentId'>): Promise<TaskOfType<Definitions, Type>>;
31
- spawn<OtherDefinitions extends TaskDefinitionMap, T extends TaskTypes<OtherDefinitions>>(queue: TaskQueue<OtherDefinitions>, type: T, data: OtherDefinitions[T]['data'], options?: Omit<EnqueueOptions, 'parentId'>): Promise<TaskOfType<OtherDefinitions, T>>;
32
- spawnMany<Type extends TaskTypes<Definitions>>(items: EnqueueManyItem<Definitions, Type>[]): Promise<TaskOfType<Definitions, Type>[]>;
33
- spawnMany<OtherDefinitions extends TaskDefinitionMap, Type extends TaskTypes<OtherDefinitions>>(queue: TaskQueue<OtherDefinitions>, items: EnqueueManyItem<OtherDefinitions, Type>[]): Promise<TaskOfType<OtherDefinitions, Type>[]>;
30
+ spawn<SpawnType extends TaskTypes<Definitions>>(type: SpawnType, data: TaskData<Definitions, SpawnType>, options?: Omit<EnqueueOptions, 'parentId'>): Promise<TaskOfType<Definitions, SpawnType>>;
31
+ spawn<OtherDefinitions extends TaskDefinitionMap, SpawnType extends TaskTypes<OtherDefinitions>>(queue: TaskQueue<OtherDefinitions>, type: SpawnType, data: OtherDefinitions[SpawnType]['data'], options?: Omit<EnqueueOptions, 'parentId'>): Promise<TaskOfType<OtherDefinitions, SpawnType>>;
32
+ spawnMany<SpawnType extends TaskTypes<Definitions>>(items: EnqueueManyItem<Definitions, SpawnType>[]): Promise<TaskOfType<Definitions, SpawnType>[]>;
33
+ spawnMany<OtherDefinitions extends TaskDefinitionMap, SpawnType extends TaskTypes<OtherDefinitions>>(queue: TaskQueue<OtherDefinitions>, items: EnqueueManyItem<OtherDefinitions, SpawnType>[]): Promise<TaskOfType<OtherDefinitions, SpawnType>[]>;
34
34
  /** Stop execution and reschedule the task for later without incrementing tries if possible */
35
35
  reschedule(timestamp: number, options?: {
36
36
  transaction?: Transaction;
@@ -44,3 +44,8 @@ export declare class TaskContext<Definitions extends TaskDefinitionMap, Type ext
44
44
  transaction?: Transaction;
45
45
  }): Promise<void>;
46
46
  }
47
+ export type TaskContext<Definitions extends TaskDefinitionMap, Type extends TaskTypes<Definitions> = TaskTypes<Definitions>> = Type extends any ? TaskContextImplementation<Definitions, Type> : never;
48
+ export declare const TaskContext: {
49
+ new <Definitions extends TaskDefinitionMap, Type extends TaskTypes<Definitions>>(queue: TaskQueue<Definitions>, task: TaskOfType<Definitions, Type>, signal: CancellationToken, logger: Logger): TaskContext<Definitions, Type>;
50
+ };
51
+ export {};
@@ -1,7 +1,7 @@
1
1
  import { currentTimestamp } from '../utils/date-time.js';
2
2
  import { isInstanceOf, isNumber, isUndefined } from '../utils/type-guards.js';
3
3
  import { TaskQueue } from './task-queue.js';
4
- export class TaskContext {
4
+ class TaskContextImplementation {
5
5
  #queue;
6
6
  #logger;
7
7
  #signal;
@@ -70,14 +70,15 @@ 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, options);
73
+ return await queueOrType.enqueue(type, data, { ...options, parentId: this.#task.id });
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
79
  if (isForOtherQueue) {
80
- return await queueOrItems.enqueueMany(itemsOrNothing, { returnTasks: true });
80
+ const items = itemsOrNothing.map((item) => ({ ...item, parentId: this.#task.id }));
81
+ return await queueOrItems.enqueueMany(items, { returnTasks: true });
81
82
  }
82
83
  const items = queueOrItems.map((item) => ({ ...item, parentId: this.#task.id }));
83
84
  return await this.#queue.enqueueMany(items, { returnTasks: true });
@@ -95,3 +96,4 @@ export class TaskContext {
95
96
  this.#signal.set();
96
97
  }
97
98
  }
99
+ export const TaskContext = TaskContextImplementation;