asynchronous operation
Separate lengthy or retryable operations from API responses.
job registration
- job.report returns job information immediately and the handler runs asynchronously.
- config.attempts has a maximum of 10 attempts and the backoff is doubled for each failure.
- You can run it up to 30 days later with config.delay.
- Input must be a JSON value and stores up to 64KB.
// server/api/report.post.ts
export default async (data: {
name: string;
rows: { item: string; amount: number }[];
}) => {
const work = await job.report(data);
return { jobId: work.id };
};Job handler
- The file path becomes the call path with the type associated with it. server/tasks/report.job.ts is registered as job.report(data).
- config.filter revalidates input just before executing the worker.
- Results are also stored as JSON values of up to 64KB.
- The completion result returns the message, the storage path in files, and the full download URL of the execution environment.
- app.url provides the full -test address during review and the full production address in production.
- An asynchronous job finishes after the original HTTP request, so it cannot return excel.download directly.
- Persist job output with excel.save, then remove it after expiry or overwrite a stable path.
- Restart recovery and retry overwriting the same XLSX path will not accumulate results.
// server/tasks/report.job.ts
export const config = {
filter: {
name: z.string().regex(/^[a-z0-9-]{1,40}$/),
rows: z.array(
z.object({
item: z.string().min(1).max(100),
amount: z.number().min(0)
})
).min(1).max(1000)
},
sample: {
name: "weekly-sales",
rows: [
{ item: "Chocolate cake", amount: 42000 },
{ item: "Cheesecake", amount: 38000 }
]
},
attempts: 3,
backoff: 1000,
timeout: 30_000
};
export default async (data: Input<typeof config.filter>) => {
const rows = [
["Item", "Amount"],
...data.rows.map((row) => [row.item, row.amount])
];
const path = `reports/${data.name}.xlsx`;
const file = await excel.save(path, rows);
return {
message: "The report has been saved.",
path: file.path,
url: new URL(`/download/${data.name}`, app.url).toString(),
rows: data.rows.length,
size: file.size,
completedAt: now()
};
};status inquiry
- The status is queued, delayed, active, completed, or failed.
- When completed, check the save completion message, save path, and download URL in the output.
- Server data operations are performed during the execution reservation period and for 7 days after completion. Stored in Redis for website use only.
- Operations on local data are kept only in memory and disappear when the process is restarted.
- Even without SSE, you can display progress by calling job.$get at regular intervals.
// server/api/report/[id].get.ts
export default async (_data: unknown, context: ApiContext) => {
const work = await job.$get(context.params.id);
if (!work) return { state: "expired" };
return {
state: work.state,
output: work.output,
error: work.error
};
};Download generated file
- files objects are also exposed to the default /files/* paths.
- The download route is storage.get, which supports both local files and object storage.
- Content-Disposition: Specifies browser download with attachment.
- Dynamic file names are used in the storage path after checking if they are in an allowed format.
// server/routes/download/[name].get.ts
const xlsx = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
const reportName = /^[a-z0-9-]{1,40}$/;
export default async (_data: unknown, context: ApiContext) => {
const name = context.params.name;
if (!reportName.test(name)) {
return new Response("The report name is incorrect.", { status: 400 });
}
const file = await storage.get(`reports/${name}.xlsx`);
if (!file) {
return new Response("Report file does not exist.", { status: 404 });
}
return new Response(file, {
headers: {
"cache-control": "no-store",
"content-disposition": `attachment; filename="${name}.xlsx"`,
"content-type": xlsx
}
});
};Queue is used for slow file, AI, mail, and external API follow-up operations. Not used for simple CRUD, immediate results, or initial recording of payment status.