feat: centralize application framework primitives
This commit is contained in:
@@ -14,6 +14,8 @@ export interface QueueStore {
|
||||
remove(id: string): Promise<void>;
|
||||
due(now: number, limit: number): Promise<Job[]>;
|
||||
list(name?: string): Promise<Job[]>;
|
||||
findByIdempotencyKey?(name: string, key: string): Promise<Job | null>;
|
||||
size?(): Promise<number>;
|
||||
claim?(id: string, worker: string, leaseUntil: number): Promise<boolean>;
|
||||
}
|
||||
|
||||
@@ -48,6 +50,15 @@ export function memoryQueueStore(): QueueStore {
|
||||
.filter((job) => !name || job.name === name)
|
||||
.map((job) => structuredClone(job));
|
||||
},
|
||||
async findByIdempotencyKey(name, key) {
|
||||
const job = [...jobs.values()].find(
|
||||
(candidate) => candidate.name === name && candidate.idempotencyKey === key,
|
||||
);
|
||||
return job ? structuredClone(job) : null;
|
||||
},
|
||||
async size() {
|
||||
return jobs.size;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -73,6 +84,10 @@ export interface DurableQueue {
|
||||
list(name?: string): Promise<Job[]>;
|
||||
failed(): Job[];
|
||||
retry(id: string): Promise<boolean>;
|
||||
addBatch<T>(
|
||||
name: string,
|
||||
entries: readonly { data: T; options?: AddOptions }[],
|
||||
): Promise<Job<T>[]>;
|
||||
}
|
||||
|
||||
function positiveInteger(value: number, label: string): number {
|
||||
@@ -178,12 +193,12 @@ export function createDurableQueue(options: DurableQueueOptions = {}): DurableQu
|
||||
}
|
||||
|
||||
if (add.idempotencyKey) {
|
||||
const existing = (await store.list(name)).find(
|
||||
(job) => job.idempotencyKey === add.idempotencyKey,
|
||||
);
|
||||
const existing = store.findByIdempotencyKey
|
||||
? await store.findByIdempotencyKey(name, add.idempotencyKey)
|
||||
: (await store.list(name)).find((job) => job.idempotencyKey === add.idempotencyKey);
|
||||
if (existing) return existing as Job<T>;
|
||||
}
|
||||
if ((await store.list()).length >= capacity) {
|
||||
if ((store.size ? await store.size() : (await store.list()).length) >= capacity) {
|
||||
throw new Error(`WRN-QUEUE-CAPACITY: queue capacity of ${capacity} reached`);
|
||||
}
|
||||
|
||||
@@ -204,6 +219,12 @@ export function createDurableQueue(options: DurableQueueOptions = {}): DurableQu
|
||||
return structuredClone(job);
|
||||
},
|
||||
|
||||
async addBatch<T>(name: string, entries: readonly { data: T; options?: AddOptions }[]) {
|
||||
const output: Job<T>[] = [];
|
||||
for (const entry of entries) output.push(await this.add(name, entry.data, entry.options));
|
||||
return output;
|
||||
},
|
||||
|
||||
process(name, handler) {
|
||||
if (!name.trim()) throw new TypeError("queue worker name cannot be empty");
|
||||
handlers.set(name, handler as JobHandler);
|
||||
|
||||
Reference in New Issue
Block a user