@unchainedshop/plugins
Version:
Because of a Typescript issue with upstream "postfinancecheckout", the Postfinance plugin has been disabled from transpilation, import the source ts files from src and enable node_module tsc or copy over the src/payment/postfinance-checkout to your projec
117 lines (100 loc) • 3.69 kB
text/typescript
import later from '@breejs/later';
import { Work, WorkData } from '@unchainedshop/core-worker';
import { WorkerDirector } from '@unchainedshop/core';
export type IWorker<P extends { workerId?: string }> = {
key: string;
label: string;
version: string;
type: string;
external: boolean;
getFloorDate: (date?: Date) => Date;
actions: (
params: P,
unchainedAPI,
) => {
autorescheduleTypes: (options: { referenceDate: Date }) => Promise<Array<Work | null>>;
process: (options: { maxWorkItemCount?: number; referenceDate?: Date }) => Promise<void>;
reset: () => Promise<void>;
start: () => void;
stop: () => void;
};
};
interface WorkerParams {
workerId?: string;
worker: IWorker<any>;
}
export const BaseWorker: IWorker<WorkerParams> = {
key: 'shop.unchained.worker.base',
label: 'Base worker. Do not use this directly.',
version: '1.0.0',
type: 'BASE',
external: false,
getFloorDate: (date = new Date()) => {
const floored = new Date(Math.floor(date.getTime() / 1000) * 1000);
return floored;
},
actions: ({ workerId }: WorkerParams, unchainedAPI) => {
const workerActions = {
start() {
throw new Error(`Not implemented on ${this.constructor.key}`);
},
stop() {
throw new Error(`Not implemented on ${this.constructor.key}`);
},
reset: async (referenceDate = new Date()) => {
await unchainedAPI.modules.worker.markOldWorkAsFailed({
types: WorkerDirector.getActivePluginTypes({ external: false }),
worker: workerId,
referenceDate,
});
},
autorescheduleTypes: async ({ referenceDate }) => {
return Promise.all(
WorkerDirector.getAutoSchedules().map(async ([scheduleId, workConfig]) => {
if (!workConfig.schedule) {
await unchainedAPI.modules.worker.ensureNoWork({
type: workConfig.type,
priority: workConfig.priority || 0,
scheduleId,
});
return null;
}
const fixedSchedule = { ...workConfig.schedule };
fixedSchedule.schedules[0].s = [0]; // ignore seconds, always run on second 0
const nextDate = later.schedule(fixedSchedule).next(1, referenceDate) as Date;
nextDate.setMilliseconds(0);
const workData: WorkData = {
type: workConfig.type,
scheduleId,
scheduled: nextDate,
timeout: workConfig.timeout,
priority: workConfig.priority || 0,
retries: workConfig.retries || 0,
};
if (workConfig.input) {
workData.input = await workConfig.input(workData);
// A work input fn can skip auto scheduling a new record
// when it explicitly returns a falsish input instead of a dictionary
if (!workData.input) return null;
}
return unchainedAPI.modules.worker.ensureOneWork(workData);
}),
);
},
process: async ({ maxWorkItemCount, referenceDate }) => {
await workerActions.autorescheduleTypes({
referenceDate,
});
const processRecursively = async (recursionCounter = 0) => {
if (maxWorkItemCount && maxWorkItemCount < recursionCounter) return null;
const doneWork = await WorkerDirector.processNextWork(unchainedAPI, workerId);
if (doneWork) return processRecursively(recursionCounter + 1);
return null;
};
await processRecursively();
},
};
workerActions.reset();
return workerActions;
},
};