@tstdl/base 0.93.198 → 0.93.200

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { createDecorator } from '../../reflection/index.js';
2
2
  import { any, Class, object, Property, Schema, schemaTestableToSchema } from '../../schema/index.js';
3
- import { isDefined } from '../../utils/type-guards.js';
3
+ import { isDefined, isUndefined } from '../../utils/type-guards.js';
4
4
  export class JsonSchema extends Schema {
5
5
  name = 'Json';
6
6
  innerSchema;
@@ -21,6 +21,7 @@ export function JsonProperty(options) {
21
21
  if (data.type == 'class') {
22
22
  return Class({ schema: json({ schema: schema ?? object({}, { unknownPropertiesKey: any(), unknownProperties: any(), factory: { type: data.constructor } }) }) })(args[0]);
23
23
  }
24
- return Property(json({ schema: schema ?? object({}, { unknownPropertiesKey: any(), unknownProperties: any(), factory: { type: metadata.type } }) }), optionsRest)(args[0], args[1], args[2]);
24
+ const propertyType = metadata.type;
25
+ return Property(json({ schema: schema ?? object({}, { unknownPropertiesKey: any(), unknownProperties: any(), factory: isUndefined(propertyType) ? undefined : { type: propertyType } }) }), optionsRest)(args[0], args[1], args[2]);
25
26
  });
26
27
  }
@@ -379,7 +379,8 @@ function getPostgresColumnEntries(type, dbSchema, tableName, path = new JsonPath
379
379
  assertDefined(propertyMetadata, `Property "${property}" of type "${type.name}" does not have reflection metadata (path: ${path.toString()}).`);
380
380
  const propertyPrefix = columnReflectionData?.embedded?.prefix;
381
381
  const nestedPrefix = [prefix, isNull(propertyPrefix) ? '' : propertyPrefix ?? `${columnName}_`].join('');
382
- return getPostgresColumnEntries(columnReflectionData?.embedded?.type ?? propertyMetadata.type, dbSchema, tableName, path.add(property), nestedPrefix, { ...options, inherited, table }, rootType);
382
+ const entryType = columnReflectionData?.embedded?.type ?? assertDefinedPass(propertyMetadata.type, 'Missing type for embedded property.');
383
+ return getPostgresColumnEntries(entryType, dbSchema, tableName, path.add(property), nestedPrefix, { ...options, inherited, table }, rootType);
383
384
  }
384
385
  const encrypted = columnReflectionData?.encrypted == true;
385
386
  const unwrappedSchemaIsUint8Array = isInstanceOf(unwrapSchema(schema).schema, Uint8ArraySchema);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.93.198",
3
+ "version": "0.93.200",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -153,8 +153,8 @@
153
153
  "type-fest": "^5.5"
154
154
  },
155
155
  "peerDependencies": {
156
- "@aws-sdk/client-s3": "^3.1025",
157
- "@aws-sdk/s3-request-presigner": "^3.1025",
156
+ "@aws-sdk/client-s3": "3",
157
+ "@aws-sdk/s3-request-presigner": "3",
158
158
  "@genkit-ai/google-genai": "^1.31",
159
159
  "@google-cloud/storage": "^7.19",
160
160
  "@toon-format/toon": "^2.1.0",
@@ -19,7 +19,7 @@ export type TypeMetadata = MetadataBase<'type'> & {
19
19
  };
20
20
  export type PropertyMetadata = MetadataBase<'property'> & {
21
21
  key: string | symbol;
22
- type: AbstractConstructor;
22
+ type: AbstractConstructor | undefined;
23
23
  isAccessor: boolean;
24
24
  data: ContextDataMap;
25
25
  inherited: boolean;
@@ -36,7 +36,7 @@ export type ConstructorParameterMetadata = MetadataBase<'constructor-parameter'>
36
36
  data: ContextDataMap;
37
37
  };
38
38
  export type MethodParameterMetadata = MetadataBase<'method-parameter'> & {
39
- type: AbstractConstructor;
39
+ type: AbstractConstructor | undefined;
40
40
  index: number;
41
41
  data: ContextDataMap;
42
42
  };
@@ -85,20 +85,20 @@ export function getTypeInfoString(type) {
85
85
  lines.push(`${type.name}(${constructorParameters})`);
86
86
  for (const [key, propertyMetadata] of (metadata?.staticProperties ?? [])) {
87
87
  const propertyKey = isSymbol(key) ? `[${key.toString()}]` : key;
88
- lines.push(` static ${propertyKey}: ${propertyMetadata.type.name}`);
88
+ lines.push(` static ${propertyKey}: ${propertyMetadata.type?.name ?? '<unknown>'}`);
89
89
  }
90
90
  for (const [key, methodMetadata] of (metadata?.staticMethods ?? [])) {
91
91
  const propertyKey = isSymbol(key) ? `[${key.toString()}]` : key;
92
- const parameters = methodMetadata.parameters.map((parameter) => parameter.type.name).join(', ');
92
+ const parameters = methodMetadata.parameters.map((parameter) => parameter.type?.name ?? '<unknown>').join(', ');
93
93
  lines.push(` static ${propertyKey}(${parameters}): ${methodMetadata.returnType?.name ?? 'void'}`);
94
94
  }
95
95
  for (const [key, propertyMetadata] of (metadata?.properties ?? [])) {
96
96
  const propertyKey = isSymbol(key) ? `[${key.toString()}]` : key;
97
- lines.push(` ${propertyKey}: ${propertyMetadata.type.name}`);
97
+ lines.push(` ${propertyKey}: ${propertyMetadata.type?.name ?? '<unknown>'}`);
98
98
  }
99
99
  for (const [key, methodMetadata] of (metadata?.methods ?? [])) {
100
100
  const propertyKey = isSymbol(key) ? `[${key.toString()}]` : key;
101
- const parameters = methodMetadata.parameters.map((parameter) => parameter.type.name).join(', ');
101
+ const parameters = methodMetadata.parameters.map((parameter) => parameter.type?.name ?? '<unknown>').join(', ');
102
102
  lines.push(` ${propertyKey}(${parameters}): ${methodMetadata.returnType?.name ?? 'void'}`);
103
103
  }
104
104
  return lines.join('\n');
@@ -56,7 +56,7 @@ export function tryGetFunctionSchemaFromReflection(type, method) {
56
56
  }
57
57
  const parameterSchemas = methodMetadata.parameters.map((parameterMetadata) => {
58
58
  const parameterData = parameterMetadata.data.tryGet('schema') ?? {};
59
- return schemaReflectionDataToSchema(parameterData, parameterMetadata.type, { type, key: `${String(method)}(parameter:${parameterMetadata.index})` });
59
+ return schemaReflectionDataToSchema(parameterData, parameterMetadata.type ?? null, { type, key: `${String(method)}(parameter:${parameterMetadata.index})` });
60
60
  });
61
61
  const parameterNames = methodMetadata.parameters.map((parameterMetadata) => {
62
62
  const parameterData = parameterMetadata.data.tryGet('schema') ?? {};
@@ -219,7 +219,7 @@ function getObjectSchemaPropertiesFromReflection(metadata, type) {
219
219
  const properties = {};
220
220
  for (const [key, propertyMetadata] of metadata.properties) {
221
221
  const reflectionData = propertyMetadata.data.tryGet('schema');
222
- const propertySchema = schemaReflectionDataToSchema(reflectionData, propertyMetadata.type, { type, key });
222
+ const propertySchema = schemaReflectionDataToSchema(reflectionData, propertyMetadata.type ?? null, { type, key });
223
223
  properties[key] = propertySchema;
224
224
  }
225
225
  for (const [key] of metadata.methods) {
@@ -77,12 +77,15 @@ export declare class PostgresTaskQueue<Definitions extends TaskDefinitionMap = T
77
77
  transaction?: Transaction;
78
78
  }): Promise<TaskOfType<Definitions, Type>[]>;
79
79
  reschedule(id: string, timestamp: number, options?: {
80
+ refundRateLimit?: boolean;
80
81
  transaction?: Transaction;
81
82
  }): Promise<void>;
82
83
  rescheduleMany(ids: string[], timestamp: number, options?: {
84
+ refundRateLimit?: boolean;
83
85
  transaction?: Transaction;
84
86
  }): Promise<void>;
85
87
  rescheduleManyByTags(tags: OneOrMany<string>, timestamp: number, options?: {
88
+ refundRateLimit?: boolean;
86
89
  transaction?: Transaction;
87
90
  }): Promise<void>;
88
91
  touch<Type extends TaskTypes<Definitions>>(task: TaskOfType<Definitions, Type>, options?: {
@@ -187,6 +187,7 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
187
187
  },
188
188
  }));
189
189
  const itemsWithIdempotency = entitiesWithIndex.filter((e) => isNotNull(e.entity.idempotencyKey));
190
+ itemsWithIdempotency.sort((a, b) => a.entity.idempotencyKey.localeCompare(b.entity.idempotencyKey));
190
191
  const itemsWithoutIdempotency = entitiesWithIndex.filter((e) => isNull(e.entity.idempotencyKey));
191
192
  const hasDependencies = itemsWithDistinctDependencies.some((item) => ((item.scheduleAfter?.length ?? 0) > 0) || ((item.completeAfter?.length ?? 0) > 0) || (isDefined(item.parentId) && (item.parentRequires != false) && !(isArray(item.parentRequires) && (item.parentRequires.length == 0))));
192
193
  const mustUseTransaction = (entitiesWithIndex.length > 1) || hasDependencies;
@@ -382,7 +383,6 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
382
383
  decrementsToApply.set(dep.taskId, current);
383
384
  }
384
385
  const values = [...decrementsToApply]
385
- .toSorted(([idA], [idB]) => idA.localeCompare(idB))
386
386
  .map(([taskId, d]) => sql `(${taskId}::uuid, ${d.schedule}::int, ${d.complete}::int)`);
387
387
  const updates = session.$with('updates').as((qb) => qb
388
388
  .select({
@@ -391,8 +391,14 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
391
391
  completeIncrement: sql `(complete)::int`.as('complete_increment'),
392
392
  })
393
393
  .from(sql `(VALUES ${sql.join(values, sql `, `)}) AS t(id, schedule, complete)`));
394
+ const locked = session.$with('locked').as((qb) => qb
395
+ .select({ id: taskTable.id })
396
+ .from(taskTable)
397
+ .innerJoin(updates, eq(taskTable.id, updates.taskId))
398
+ .orderBy(asc(taskTable.id))
399
+ .for('update'));
394
400
  const updatedRows = await session
395
- .with(updates)
401
+ .with(updates, locked)
396
402
  .update(taskTable)
397
403
  .set({
398
404
  unresolvedScheduleDependencies: sql `${taskTable.unresolvedScheduleDependencies} + ${updates.scheduleIncrement}`,
@@ -400,7 +406,7 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
400
406
  status: caseWhen(and(eq(taskTable.status, TaskStatus.Pending), gt(sql `${taskTable.unresolvedScheduleDependencies} + ${updates.scheduleIncrement}`, 0)), TaskStatus.Waiting).else(taskTable.status),
401
407
  })
402
408
  .from(updates)
403
- .where(eq(taskTable.id, updates.taskId))
409
+ .where(and(eq(taskTable.id, updates.taskId), inArray(taskTable.id, session.select({ id: locked.id }).from(locked))))
404
410
  .returning({ id: taskTable.id, status: taskTable.status, namespace: taskTable.namespace });
405
411
  const notifiedNamespaces = new Set();
406
412
  for (const row of updatedRows) {
@@ -685,7 +691,7 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
685
691
  }
686
692
  async rescheduleMany(ids, timestamp, options) {
687
693
  const session = options?.transaction?.pgTransaction ?? this.#repository.session;
688
- await session
694
+ const result = await session
689
695
  .update(taskTable)
690
696
  .set({
691
697
  status: caseWhen(gt(taskTable.unresolvedScheduleDependencies, 0), enumValue(taskStatus, TaskStatus.Waiting)).else(enumValue(taskStatus, TaskStatus.Pending)),
@@ -694,11 +700,20 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
694
700
  visibilityDeadline: null,
695
701
  tries: caseWhen(eq(taskTable.status, enumValue(taskStatus, TaskStatus.Running)), greatest(0, sql `${taskTable.tries} - 1`)).else(taskTable.tries),
696
702
  })
697
- .where(and(inArray(taskTable.id, ids), notInArray(taskTable.status, terminalStatuses)));
703
+ .where(and(inArray(taskTable.id, ids), notInArray(taskTable.status, terminalStatuses)))
704
+ .returning({ id: taskTable.id });
705
+ if ((result.length > 0) && (options?.refundRateLimit == true)) {
706
+ try {
707
+ await this.#rateLimiter.refund(this.#namespace, result.length);
708
+ }
709
+ catch (error) {
710
+ this.#logger.error(error);
711
+ }
712
+ }
698
713
  }
699
714
  async rescheduleManyByTags(tags, timestamp, options) {
700
715
  const session = options?.transaction?.pgTransaction ?? this.#repository.session;
701
- await session
716
+ const result = await session
702
717
  .update(taskTable)
703
718
  .set({
704
719
  status: caseWhen(gt(taskTable.unresolvedScheduleDependencies, 0), enumValue(taskStatus, TaskStatus.Waiting)).else(enumValue(taskStatus, TaskStatus.Pending)),
@@ -707,7 +722,16 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
707
722
  visibilityDeadline: null,
708
723
  tries: caseWhen(eq(taskTable.status, enumValue(taskStatus, TaskStatus.Running)), greatest(0, sql `${taskTable.tries} - 1`)).else(taskTable.tries),
709
724
  })
710
- .where(and(eq(taskTable.namespace, this.#namespace), arrayOverlaps(taskTable.tags, toArray(tags)), notInArray(taskTable.status, terminalStatuses)));
725
+ .where(and(eq(taskTable.namespace, this.#namespace), arrayOverlaps(taskTable.tags, toArray(tags)), notInArray(taskTable.status, terminalStatuses)))
726
+ .returning({ id: taskTable.id });
727
+ if ((result.length > 0) && (options?.refundRateLimit == true)) {
728
+ try {
729
+ await this.#rateLimiter.refund(this.#namespace, result.length);
730
+ }
731
+ catch (error) {
732
+ this.#logger.error(error);
733
+ }
734
+ }
711
735
  }
712
736
  async touch(task, options) {
713
737
  if (isNull(task.token)) {
@@ -755,6 +779,12 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
755
779
  updateState: sql `(state)::jsonb`.as('update_state'),
756
780
  })
757
781
  .from(sql `(VALUES ${sql.join(rows, sql `, `)}) AS t(id, token, progress, state)`));
782
+ const locked = session.$with('locked').as((qb) => qb
783
+ .select({ id: taskTable.id })
784
+ .from(taskTable)
785
+ .innerJoin(updates, eq(taskTable.id, updates.updateId))
786
+ .orderBy(asc(taskTable.id))
787
+ .for('update'));
758
788
  const updated = session.$with('updated').as(() => session
759
789
  .update(taskTable)
760
790
  .set({
@@ -763,10 +793,10 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
763
793
  state: coalesce(updates.updateState, taskTable.state),
764
794
  })
765
795
  .from(updates)
766
- .where(and(eq(taskTable.id, updates.updateId), sql `${taskTable.token} IS NOT DISTINCT FROM ${updates.updateToken}`, eq(taskTable.status, TaskStatus.Running), gt(taskTable.startTimestamp, sql `${TRANSACTION_TIMESTAMP} - ${interval(this.maxExecutionTime, 'milliseconds')}`)))
796
+ .where(and(eq(taskTable.id, updates.updateId), inArray(taskTable.id, session.select({ id: locked.id }).from(locked)), sql `${taskTable.token} IS NOT DISTINCT FROM ${updates.updateToken}`, eq(taskTable.status, TaskStatus.Running), gt(taskTable.startTimestamp, sql `${TRANSACTION_TIMESTAMP} - ${interval(this.maxExecutionTime, 'milliseconds')}`)))
767
797
  .returning({ id: taskTable.id }));
768
798
  const result = await session
769
- .with(updates, updated)
799
+ .with(updates, locked, updated)
770
800
  .select({ id: updated.id })
771
801
  .from(updated);
772
802
  return result.map((r) => r.id);
@@ -810,6 +840,12 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
810
840
  updateProgress: sql `(progress)::numeric`.as('update_progress'),
811
841
  })
812
842
  .from(sql `(VALUES ${sql.join(rows, sql `, `)}) AS t(id, token, result, progress)`));
843
+ const locked = tx.pgTransaction.$with('locked').as((qb) => qb
844
+ .select({ id: taskTable.id })
845
+ .from(taskTable)
846
+ .innerJoin(updates, eq(taskTable.id, updates.updateId))
847
+ .orderBy(asc(taskTable.id))
848
+ .for('update'));
813
849
  const updated = tx.pgTransaction.$with('updated').as(() => tx.pgTransaction
814
850
  .update(taskTable)
815
851
  .set({
@@ -821,10 +857,10 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
821
857
  visibilityDeadline: null,
822
858
  })
823
859
  .from(updates)
824
- .where(and(eq(taskTable.id, updates.updateId), sql `${taskTable.token} IS NOT DISTINCT FROM ${updates.updateToken}`))
860
+ .where(and(eq(taskTable.id, updates.updateId), inArray(taskTable.id, tx.pgTransaction.select({ id: locked.id }).from(locked)), sql `${taskTable.token} IS NOT DISTINCT FROM ${updates.updateToken}`))
825
861
  .returning({ id: taskTable.id, status: taskTable.status }));
826
862
  const updatedRows = await tx.pgTransaction
827
- .with(updates, updated)
863
+ .with(updates, locked, updated)
828
864
  .select({ id: updated.id, status: updated.status })
829
865
  .from(updated);
830
866
  if (updatedRows.length > 0) {
@@ -879,6 +915,12 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
879
915
  updateComplete: sql `(complete_timestamp)`.as('update_complete'),
880
916
  })
881
917
  .from(sql `(VALUES ${sql.join(rows, sql `, `)}) AS t(id, token, tries, status, error, schedule_timestamp, complete_timestamp)`));
918
+ const locked = tx.pgTransaction.$with('locked').as((qb) => qb
919
+ .select({ id: taskTable.id })
920
+ .from(taskTable)
921
+ .innerJoin(updates, eq(taskTable.id, updates.updateId))
922
+ .orderBy(asc(taskTable.id))
923
+ .for('update'));
882
924
  const updated = tx.pgTransaction.$with('updated').as(() => tx.pgTransaction
883
925
  .update(taskTable)
884
926
  .set({
@@ -890,10 +932,10 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
890
932
  completeTimestamp: sql `${updates.updateComplete}`,
891
933
  })
892
934
  .from(updates)
893
- .where(and(eq(taskTable.id, updates.updateId), sql `${taskTable.token} IS NOT DISTINCT FROM ${updates.updateToken}`, eq(taskTable.tries, updates.updateTries)))
935
+ .where(and(eq(taskTable.id, updates.updateId), inArray(taskTable.id, tx.pgTransaction.select({ id: locked.id }).from(locked)), sql `${taskTable.token} IS NOT DISTINCT FROM ${updates.updateToken}`, eq(taskTable.tries, updates.updateTries)))
894
936
  .returning({ id: taskTable.id, status: taskTable.status }));
895
937
  const result = await tx.pgTransaction
896
- .with(updates, updated)
938
+ .with(updates, locked, updated)
897
939
  .select({ id: updated.id, status: updated.status })
898
940
  .from(updated);
899
941
  if (result.length > 0) {
@@ -916,7 +958,9 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
916
958
  await this.resolveDependenciesMany([{ id, status, namespace: options?.namespace }], options);
917
959
  }
918
960
  async resolveDependenciesMany(tasks, options) {
919
- const tasksToResolve = tasks.filter((t) => terminalStatuses.includes(t.status));
961
+ const tasksToResolve = tasks
962
+ .filter((t) => terminalStatuses.includes(t.status))
963
+ .toSorted((a, b) => a.id.localeCompare(b.id));
920
964
  if (tasksToResolve.length == 0) {
921
965
  return;
922
966
  }
@@ -1013,7 +1057,6 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
1013
1057
  }
1014
1058
  if (decrementsToApply.size > 0) {
1015
1059
  const decrementValues = [...decrementsToApply]
1016
- .toSorted(([idA], [idB]) => idA.localeCompare(idB))
1017
1060
  .map(([taskId, d]) => sql `(${taskId}::uuid, ${d.schedule}::int, ${d.complete}::int)`);
1018
1061
  const updates = tx.pgTransaction.$with('updates').as((qb) => qb
1019
1062
  .select({
@@ -1022,8 +1065,14 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
1022
1065
  completeDecrement: sql `(complete)::int`.as('complete_decrement'),
1023
1066
  })
1024
1067
  .from(sql `(VALUES ${sql.join(decrementValues, sql `, `)}) AS t(id, schedule, complete)`));
1068
+ const locked = tx.pgTransaction.$with('locked').as((qb) => qb
1069
+ .select({ id: taskTable.id })
1070
+ .from(taskTable)
1071
+ .innerJoin(updates, eq(taskTable.id, updates.taskId))
1072
+ .orderBy(asc(taskTable.id))
1073
+ .for('update'));
1025
1074
  const updatedRows = await tx.pgTransaction
1026
- .with(updates)
1075
+ .with(updates, locked)
1027
1076
  .update(taskTable)
1028
1077
  .set({
1029
1078
  unresolvedScheduleDependencies: greatest(0, sql `${taskTable.unresolvedScheduleDependencies} - ${updates.scheduleDecrement}`),
@@ -1034,7 +1083,7 @@ let PostgresTaskQueue = class PostgresTaskQueue extends TaskQueue {
1034
1083
  token: caseWhen(and(eq(taskTable.status, TaskStatus.WaitingChildren), eq(greatest(0, sql `${taskTable.unresolvedCompleteDependencies} - ${updates.completeDecrement}`), 0)), null).else(taskTable.token),
1035
1084
  })
1036
1085
  .from(updates)
1037
- .where(eq(taskTable.id, updates.taskId))
1086
+ .where(and(eq(taskTable.id, updates.taskId), inArray(taskTable.id, tx.pgTransaction.select({ id: locked.id }).from(locked))))
1038
1087
  .returning({
1039
1088
  id: taskTable.id,
1040
1089
  namespace: taskTable.namespace,
@@ -33,10 +33,12 @@ declare class TaskContextImplementation<Definitions extends TaskDefinitionMap, T
33
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
+ refundRateLimit?: boolean;
36
37
  transaction?: Transaction;
37
38
  }): Promise<void>;
38
39
  reschedule(rescheduleOptions: {
39
40
  delay: number;
41
+ refundRateLimit?: boolean;
40
42
  transaction?: Transaction;
41
43
  }): Promise<void>;
42
44
  fail(error: unknown, options?: {
@@ -83,12 +83,12 @@ class TaskContextImplementation {
83
83
  const items = queueOrItems.map((item) => ({ ...item, parentId: this.#task.id }));
84
84
  return await this.#queue.enqueueMany(items, { returnTasks: true });
85
85
  }
86
- async reschedule(timestampOrDelay) {
86
+ async reschedule(timestampOrDelay, maybeOptions) {
87
87
  const isTimestamp = isNumber(timestampOrDelay);
88
88
  const timestamp = isTimestamp ? timestampOrDelay : (currentTimestamp() + timestampOrDelay.delay);
89
- const transaction = isTimestamp ? undefined : timestampOrDelay.transaction;
89
+ const options = isTimestamp ? maybeOptions : timestampOrDelay;
90
90
  this.#logger.debug(`Rescheduling task for ${new Date(timestamp).toISOString()}.`);
91
- await this.#queue.reschedule(this.#task.id, timestamp, { transaction });
91
+ await this.#queue.reschedule(this.#task.id, timestamp, options);
92
92
  this.#signal.set();
93
93
  }
94
94
  async fail(error, options) {
@@ -31,13 +31,19 @@ export declare class TaskProcessResult<Result = unknown> {
31
31
  /**
32
32
  * Creates a result that reschedules the task to a specific timestamp.
33
33
  * @param timestamp The timestamp to reschedule to.
34
+ * @param options Optional refund flags.
34
35
  */
35
- static RescheduleTo<R>(timestamp: number): TaskProcessResult<R>;
36
+ static RescheduleTo<R>(timestamp: number, options?: {
37
+ refundRateLimit?: boolean;
38
+ }): TaskProcessResult<R>;
36
39
  /**
37
40
  * Creates a result that reschedules the task by a specific number of milliseconds.
38
41
  * @param milliseconds The number of milliseconds to reschedule by.
42
+ * @param options Optional refund flags.
39
43
  */
40
- static RescheduleBy<R>(milliseconds: number): TaskProcessResult<R>;
44
+ static RescheduleBy<R>(milliseconds: number, options?: {
45
+ refundRateLimit?: boolean;
46
+ }): TaskProcessResult<R>;
41
47
  }
42
48
  /**
43
49
  * Represents the status of a task in the queue.
@@ -521,27 +527,30 @@ export declare abstract class TaskQueue<Definitions extends TaskDefinitionMap =
521
527
  * Reschedules a task to run at a specific time.
522
528
  * @param id The ID of the task.
523
529
  * @param timestamp The timestamp when the task should run.
524
- * @param options Optional transaction.
530
+ * @param options Optional transaction and refund flags.
525
531
  */
526
532
  abstract reschedule(id: string, timestamp: number, options?: {
533
+ refundRateLimit?: boolean;
527
534
  transaction?: Transaction;
528
535
  }): Promise<void>;
529
536
  /**
530
537
  * Reschedules multiple tasks to run at a specific time.
531
538
  * @param ids The IDs of the tasks.
532
539
  * @param timestamp The timestamp when the tasks should run.
533
- * @param options Optional transaction.
540
+ * @param options Optional transaction and refund flags.
534
541
  */
535
542
  abstract rescheduleMany(ids: string[], timestamp: number, options?: {
543
+ refundRateLimit?: boolean;
536
544
  transaction?: Transaction;
537
545
  }): Promise<void>;
538
546
  /**
539
547
  * Reschedules tasks with the given tags to run at a specific time.
540
548
  * @param tags One or more tags.
541
549
  * @param timestamp The timestamp when the tasks should run.
542
- * @param options Optional transaction.
550
+ * @param options Optional transaction and refund flags.
543
551
  */
544
552
  abstract rescheduleManyByTags(tags: OneOrMany<string>, timestamp: number, options?: {
553
+ refundRateLimit?: boolean;
545
554
  transaction?: Transaction;
546
555
  }): Promise<void>;
547
556
  /**
@@ -87,17 +87,19 @@ export class TaskProcessResult {
87
87
  /**
88
88
  * Creates a result that reschedules the task to a specific timestamp.
89
89
  * @param timestamp The timestamp to reschedule to.
90
+ * @param options Optional refund flags.
90
91
  */
91
- static RescheduleTo(timestamp) {
92
- return new TaskProcessResult({ action: 'reschedule', timestamp });
92
+ static RescheduleTo(timestamp, options) {
93
+ return new TaskProcessResult({ action: 'reschedule', timestamp, ...options });
93
94
  }
94
95
  /**
95
96
  * Creates a result that reschedules the task by a specific number of milliseconds.
96
97
  * @param milliseconds The number of milliseconds to reschedule by.
98
+ * @param options Optional refund flags.
97
99
  */
98
- static RescheduleBy(milliseconds) {
100
+ static RescheduleBy(milliseconds, options) {
99
101
  const timestamp = currentTimestamp() + milliseconds;
100
- return this.RescheduleTo(timestamp);
102
+ return this.RescheduleTo(timestamp, options);
101
103
  }
102
104
  }
103
105
  /**
@@ -275,7 +277,7 @@ export class TaskQueue extends Transactional {
275
277
  break;
276
278
  case 'reschedule':
277
279
  context.logger.verbose('Rescheduling task');
278
- await this.reschedule(task.id, result.payload.timestamp);
280
+ await this.reschedule(task.id, result.payload.timestamp, { refundRateLimit: result.payload.refundRateLimit });
279
281
  break;
280
282
  default:
281
283
  throw new Error('Unsupported task result action.');
@@ -31,6 +31,7 @@ export type TaskProcessResultPayload<Result> = {
31
31
  } | {
32
32
  action: 'reschedule';
33
33
  timestamp: number;
34
+ refundRateLimit?: boolean;
34
35
  };
35
36
  export interface ProcessWorker<Definitions extends TaskDefinitionMap, Type extends TaskTypes<Definitions>> {
36
37
  /**
package/test2.js CHANGED
@@ -1,16 +1,34 @@
1
- import { inject, Singleton } from './injector/index.js';
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
2
10
  import { Application } from './application/application.js';
3
11
  import { provideModule } from './application/providers.js';
12
+ import { defineEnum } from './enumeration/enumeration.js';
4
13
  import { PrettyPrintLogFormatter, provideConsoleLogTransport } from './logger/index.js';
5
- import { object, string } from './schema/index.js';
6
- const schema = object({
7
- value: string({ lowercase: true })
14
+ import { Enumeration } from './schema/index.js';
15
+ import { getDesignType } from './utils/reflection.js';
16
+ const Status = defineEnum('Status', {
17
+ Active: 'active',
18
+ Inactive: 'inactive',
19
+ Suspended: 'suspended',
8
20
  });
21
+ class TestClass {
22
+ status;
23
+ }
24
+ __decorate([
25
+ Enumeration(Status),
26
+ __metadata("design:type", String)
27
+ ], TestClass.prototype, "status", void 0);
9
28
  function main() {
10
- const value = schema.parse({ value: 'HELLO WORLD' });
11
- console.log(value);
29
+ console.log(getDesignType(TestClass.prototype, 'status'));
12
30
  }
13
31
  Application.run('Test', [
14
32
  provideModule(main),
15
- provideConsoleLogTransport(PrettyPrintLogFormatter)
33
+ provideConsoleLogTransport(PrettyPrintLogFormatter),
16
34
  ]);