- Send now and Remind answer straight away with who they're going to and queue the feedback-send task; the Feedback page refreshes to show progress. - One-off background tasks (enqueueTask in src/jobs/index.js): pg-boss with retries, or in-process after the response when the queue is off. - Reminders are claimed with the 24-hour rule, so two tasks at once never remind the same person twice. - Tests: tests/tasks.test.js, tests/feedbackPage.test.ts, e2e/feedback.spec.ts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
35 lines
1.6 KiB
JavaScript
35 lines
1.6 KiB
JavaScript
/**
|
|
* 2.1.1: one-off background tasks (jobs/index.js enqueueTask). Without the queue (timers or jobs
|
|
* off) a task runs in this process right after the caller gets its answer.
|
|
*/
|
|
let finish;
|
|
const mockTask = jest.fn(() => new Promise(resolve => { finish = resolve; }));
|
|
jest.mock('../src/utils/feedback', () => ({ runFeedbackTask: (...a) => mockTask(...a) }));
|
|
|
|
const jobs = require('../src/jobs');
|
|
|
|
describe('enqueueTask without the queue', () => {
|
|
test('answers before the task has run, then runs it', async () => {
|
|
const answer = await jobs.enqueueTask('feedback-send', { formId: 'f1', kind: 'send' });
|
|
expect(answer).toEqual({ queued: false });
|
|
expect(mockTask).not.toHaveBeenCalled(); // not yet: after the response
|
|
await new Promise(r => setImmediate(r));
|
|
expect(mockTask).toHaveBeenCalledWith({ formId: 'f1', kind: 'send' });
|
|
finish({ invited: 3 });
|
|
});
|
|
|
|
test('a failing task is logged, not thrown at the caller', async () => {
|
|
const warn = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
mockTask.mockImplementationOnce(() => Promise.reject(new Error('SMTP down')));
|
|
await expect(jobs.enqueueTask('feedback-send', { formId: 'f1', kind: 'send' })).resolves.toEqual({ queued: false });
|
|
await new Promise(r => setImmediate(r));
|
|
await new Promise(r => setImmediate(r));
|
|
expect(warn).toHaveBeenCalledWith('[jobs] task feedback-send failed:', 'SMTP down');
|
|
warn.mockRestore();
|
|
});
|
|
|
|
test('an unknown task is refused', async () => {
|
|
await expect(jobs.enqueueTask('nope', {})).rejects.toThrow('Unknown task nope');
|
|
});
|
|
});
|