296 lines
20 KiB
JavaScript
296 lines
20 KiB
JavaScript
import { createRoute, z } from '@hono/zod-openapi';
|
|
import { boss } from '../jobs/boss/client.js';
|
|
import { QUEUE_MOCK_JOB } from '../jobs/boss/workers.js';
|
|
const tags = ['PgBoss'];
|
|
export const postBossJobRoute = createRoute({
|
|
method: 'post',
|
|
path: '/api/boss/job',
|
|
tags,
|
|
request: {
|
|
body: {
|
|
content: {
|
|
'application/json': {
|
|
schema: z.object({
|
|
delayMs: z.number().default(100),
|
|
shouldFail: z.boolean().default(false),
|
|
retryLimit: z.number().optional()
|
|
}),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
responses: {
|
|
200: {
|
|
content: {
|
|
'application/json': {
|
|
schema: z.object({
|
|
jobId: z.string().nullable(),
|
|
message: z.string()
|
|
}),
|
|
},
|
|
},
|
|
description: 'PgBoss job started',
|
|
},
|
|
500: {
|
|
content: {
|
|
'application/json': {
|
|
schema: z.object({ error: z.string() }),
|
|
},
|
|
},
|
|
description: 'Server error',
|
|
},
|
|
},
|
|
});
|
|
export const postBossJobHandler = async (c) => {
|
|
if (!boss) {
|
|
// Check if there was an initialization error we can report
|
|
const { bossInitError } = await import('../jobs/boss/client.js');
|
|
return c.json({ error: `PgBoss not initialized. Init error: ${bossInitError}` }, 500);
|
|
}
|
|
const { delayMs, shouldFail, retryLimit } = c.req.valid('json');
|
|
const payload = { delayMs, shouldFail };
|
|
const options = retryLimit !== undefined ? { retryLimit } : {};
|
|
try {
|
|
const jobId = await boss.send(QUEUE_MOCK_JOB, payload, options);
|
|
return c.json({ jobId, message: 'Job submitted to PgBoss' }, 200);
|
|
}
|
|
catch (error) {
|
|
return c.json({ error: error.message }, 500);
|
|
}
|
|
};
|
|
export const getBossJobRoute = createRoute({
|
|
method: 'get',
|
|
path: '/api/boss/job/{id}',
|
|
tags,
|
|
request: {
|
|
params: z.object({
|
|
id: z.string(),
|
|
}),
|
|
},
|
|
responses: {
|
|
200: {
|
|
content: {
|
|
'application/json': {
|
|
schema: z.object({
|
|
id: z.string(),
|
|
name: z.string(),
|
|
data: z.any(),
|
|
state: z.string(),
|
|
createdOn: z.string().optional(),
|
|
startedOn: z.string().optional(),
|
|
completedOn: z.string().optional(),
|
|
}),
|
|
},
|
|
},
|
|
description: 'Job status',
|
|
},
|
|
404: {
|
|
content: {
|
|
'application/json': {
|
|
schema: z.object({ error: z.string() }),
|
|
},
|
|
},
|
|
description: 'Job not found',
|
|
},
|
|
500: {
|
|
content: {
|
|
'application/json': {
|
|
schema: z.object({ error: z.string() }),
|
|
},
|
|
},
|
|
description: 'Server error',
|
|
},
|
|
},
|
|
});
|
|
export const getBossJobHandler = async (c) => {
|
|
const { id } = c.req.valid('param');
|
|
// Use pg directly to bypass PostgREST schema permissions
|
|
const { Client } = await import('pg');
|
|
const client = new Client({ connectionString: process.env.DATABASE_URL, });
|
|
try {
|
|
await client.connect();
|
|
const result = await client.query('SELECT * FROM pgboss.job WHERE id = $1', [id]);
|
|
const job = result.rows[0];
|
|
if (!job) {
|
|
return c.json({ error: 'Job not found' }, 404);
|
|
}
|
|
return c.json({
|
|
id: job.id,
|
|
name: job.name,
|
|
data: job.data,
|
|
state: job.state,
|
|
createdOn: job.createdon,
|
|
startedOn: job.startedon,
|
|
completedOn: job.completedon,
|
|
output: job.output,
|
|
}, 200);
|
|
}
|
|
catch (error) {
|
|
console.error('Error in getBossJobHandler:', error);
|
|
return c.json({ error: error.message }, 500);
|
|
}
|
|
finally {
|
|
await client.end().catch(() => { });
|
|
}
|
|
};
|
|
export const cancelBossJobRoute = createRoute({
|
|
method: 'post',
|
|
path: '/api/boss/job/{id}/cancel',
|
|
tags,
|
|
request: {
|
|
params: z.object({
|
|
id: z.string(),
|
|
}),
|
|
},
|
|
responses: {
|
|
200: {
|
|
content: {
|
|
'application/json': {
|
|
schema: z.object({ message: z.string() }),
|
|
},
|
|
},
|
|
description: 'Job cancelled',
|
|
},
|
|
500: {
|
|
content: {
|
|
'application/json': {
|
|
schema: z.object({ error: z.string() }),
|
|
},
|
|
},
|
|
description: 'Server error',
|
|
},
|
|
},
|
|
});
|
|
export const cancelBossJobHandler = async (c) => {
|
|
if (!boss)
|
|
return c.json({ error: 'PgBoss not initialized' }, 500);
|
|
const { id } = c.req.valid('param');
|
|
try {
|
|
await boss.cancel(QUEUE_MOCK_JOB, id);
|
|
return c.json({ message: 'Job cancelled' }, 200);
|
|
}
|
|
catch (error) {
|
|
return c.json({ error: error.message }, 500);
|
|
}
|
|
};
|
|
export const resumeBossJobRoute = createRoute({
|
|
method: 'post',
|
|
path: '/api/boss/job/{id}/resume',
|
|
tags,
|
|
request: {
|
|
params: z.object({
|
|
id: z.string(),
|
|
}),
|
|
},
|
|
responses: {
|
|
200: {
|
|
content: {
|
|
'application/json': {
|
|
schema: z.object({ message: z.string() }),
|
|
},
|
|
},
|
|
description: 'Job resumed',
|
|
},
|
|
500: {
|
|
content: {
|
|
'application/json': {
|
|
schema: z.object({ error: z.string() }),
|
|
},
|
|
},
|
|
description: 'Server error',
|
|
},
|
|
},
|
|
});
|
|
export const resumeBossJobHandler = async (c) => {
|
|
if (!boss)
|
|
return c.json({ error: 'PgBoss not initialized' }, 500);
|
|
const { id } = c.req.valid('param');
|
|
try {
|
|
await boss.resume(QUEUE_MOCK_JOB, id);
|
|
return c.json({ message: 'Job resumed' }, 200);
|
|
}
|
|
catch (error) {
|
|
return c.json({ error: error.message }, 500);
|
|
}
|
|
};
|
|
export const completeBossJobRoute = createRoute({
|
|
method: 'post',
|
|
path: '/api/boss/job/{id}/complete',
|
|
tags,
|
|
request: {
|
|
params: z.object({
|
|
id: z.string(),
|
|
}),
|
|
},
|
|
responses: {
|
|
200: {
|
|
content: {
|
|
'application/json': {
|
|
schema: z.object({ message: z.string() }),
|
|
},
|
|
},
|
|
description: 'Job completed',
|
|
},
|
|
500: {
|
|
content: {
|
|
'application/json': {
|
|
schema: z.object({ error: z.string() }),
|
|
},
|
|
},
|
|
description: 'Server error',
|
|
},
|
|
},
|
|
});
|
|
export const completeBossJobHandler = async (c) => {
|
|
if (!boss)
|
|
return c.json({ error: 'PgBoss not initialized' }, 500);
|
|
const { id } = c.req.valid('param');
|
|
try {
|
|
await boss.complete(QUEUE_MOCK_JOB, id);
|
|
return c.json({ message: 'Job completed' }, 200);
|
|
}
|
|
catch (error) {
|
|
return c.json({ error: error.message }, 500);
|
|
}
|
|
};
|
|
export const failBossJobRoute = createRoute({
|
|
method: 'post',
|
|
path: '/api/boss/job/{id}/fail',
|
|
tags,
|
|
request: {
|
|
params: z.object({
|
|
id: z.string(),
|
|
}),
|
|
},
|
|
responses: {
|
|
200: {
|
|
content: {
|
|
'application/json': {
|
|
schema: z.object({ message: z.string() }),
|
|
},
|
|
},
|
|
description: 'Job failed',
|
|
},
|
|
500: {
|
|
content: {
|
|
'application/json': {
|
|
schema: z.object({ error: z.string() }),
|
|
},
|
|
},
|
|
description: 'Server error',
|
|
},
|
|
},
|
|
});
|
|
export const failBossJobHandler = async (c) => {
|
|
if (!boss)
|
|
return c.json({ error: 'PgBoss not initialized' }, 500);
|
|
const { id } = c.req.valid('param');
|
|
try {
|
|
await boss.fail(QUEUE_MOCK_JOB, id);
|
|
return c.json({ message: 'Job failed' }, 200);
|
|
}
|
|
catch (error) {
|
|
return c.json({ error: error.message }, 500);
|
|
}
|
|
};
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9zcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9lbmRwb2ludHMvYm9zcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFlLENBQUMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRWhFLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHekQsTUFBTSxJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUV4QixNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxXQUFXLENBQUM7SUFDeEMsTUFBTSxFQUFFLE1BQU07SUFDZCxJQUFJLEVBQUUsZUFBZTtJQUNyQixJQUFJO0lBQ0osT0FBTyxFQUFFO1FBQ0wsSUFBSSxFQUFFO1lBQ0YsT0FBTyxFQUFFO2dCQUNMLGtCQUFrQixFQUFFO29CQUNoQixNQUFNLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQzt3QkFDYixPQUFPLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUM7d0JBQ2hDLFVBQVUsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQzt3QkFDdEMsVUFBVSxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUU7cUJBQ3BDLENBQUM7aUJBQ0w7YUFDSjtTQUNKO0tBQ0o7SUFDRCxTQUFTLEVBQUU7UUFDUCxHQUFHLEVBQUU7WUFDRCxPQUFPLEVBQUU7Z0JBQ0wsa0JBQWtCLEVBQUU7b0JBQ2hCLE1BQU0sRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDO3dCQUNiLEtBQUssRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFO3dCQUM1QixPQUFPLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRTtxQkFDdEIsQ0FBQztpQkFDTDth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
|