mirror of
https://github.com/Dvorinka/Containr.git
synced 2026-10-28 15:51:26 +00:00
Build real cron engine + service-detail Cron UI
The cron backend was a stub: calculateNextRun returned now+1h for any input and executeCronJob slept 2s then wrote "success" without running the command. Now robfig/cron parses and validates schedules (400 on invalid), a 60s scheduler goroutine executes due enabled jobs, and commands run via docker exec sh -c inside the service's container with stdout+stderr captured into cron_executions. Added Client.ExecRun for attached output capture. UI: Cron tab on the service detail page with create/edit/enable-toggle, manual Run, and execution history with logs. Verified e2e against real Postgres + Docker (trigger and scheduler tick both produce real captured output). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
aab785afc1
commit
a1e43524f5
9 files changed
+498
-26
No files matched your search
@@ -1323,3 +1323,50 @@ export async function createGitWebhook(input: CreateGitWebhookInput): Promise<Gi
|
||||
}
|
||||
return payload.webhook;
|
||||
}
|
||||
|
||||
// --- Cron jobs ---
|
||||
|
||||
export type CronJobEntity = components['schemas']['CronJob'];
|
||||
export type CronExecutionEntity = components['schemas']['CronExecution'];
|
||||
export type CreateCronJobInput = components['schemas']['CreateCronJobRequest'];
|
||||
export type UpdateCronJobInput = components['schemas']['UpdateCronJobRequest'];
|
||||
|
||||
export async function listCronJobs(serviceId: string): Promise<CronJobEntity[]> {
|
||||
const payload = await requestJson<{ cron_jobs?: CronJobEntity[] }>(
|
||||
`/cron-jobs?service_id=${encodeURIComponent(serviceId)}`,
|
||||
);
|
||||
return payload.cron_jobs ?? [];
|
||||
}
|
||||
|
||||
export async function createCronJob(input: CreateCronJobInput): Promise<CronJobEntity> {
|
||||
const payload = await requestJson<{ cron_job?: CronJobEntity }>('/cron-jobs', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
if (!payload.cron_job?.id) {
|
||||
throw new ApiError('Create cron job response is invalid', 500);
|
||||
}
|
||||
return payload.cron_job;
|
||||
}
|
||||
|
||||
export async function updateCronJob(id: string, input: UpdateCronJobInput): Promise<void> {
|
||||
await requestJson(`/cron-jobs/${encodeURIComponent(id)}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteCronJob(id: string): Promise<void> {
|
||||
await requestJson(`/cron-jobs/${encodeURIComponent(id)}`, { method: 'DELETE' });
|
||||
}
|
||||
|
||||
export async function listCronExecutions(id: string): Promise<CronExecutionEntity[]> {
|
||||
const payload = await requestJson<{ executions?: CronExecutionEntity[] }>(
|
||||
`/cron-jobs/${encodeURIComponent(id)}/executions`,
|
||||
);
|
||||
return payload.executions ?? [];
|
||||
}
|
||||
|
||||
export async function triggerCronJob(id: string): Promise<void> {
|
||||
await requestJson(`/cron-jobs/${encodeURIComponent(id)}/trigger`, { method: 'POST' });
|
||||
}
|
||||
Reference in new issue
Block a user