mirror of
https://github.com/Dvorinka/Primora.git
synced 2026-10-29 00:01:20 +00:00
feat: phase 7 automation & realtime — scheduled jobs, domain events, SSE
Scheduled jobs (migration 00009): cron expressions + @every descriptors, in-process scheduler (15s scan, missed-run collapse), signed HTTP POST delivery (X-Primora-Signature), AES-256-GCM sealed secrets returned once, run history with status/duration/http-code, manual execution, retention pruning. Viewer reads, admin/developer writes. Domain events: publishEvent fans document/object/issue/deploy/job mutations to realtime subscribers and matching webhooks through one path. Webhook event filter extended to job.run, document.*, object.*. Realtime: GET /projects/:id/realtime/stream SSE with 25s keepalives and ?token=/?api_key= auth for EventSource clients. Automation dashboard page: Schedules tab (CRUD, run history, manual run, secret-once banner) + Live events tab (live badge, pause/clear). Demo mode parity. primora jobs:* CLI group, six primora_*_job* MCP tools, AutomationService in the generated client. Fixes folded in: gzip middleware buffered SSE flushes (broke EventSource on both streams — */stream now bypasses compression); event payloads double-marshaled json.RawMessage as base64; compose hardcoded localhost trusted origins so non-default ports broke sign-in; frontend auth base URL baked an absolute localhost instead of resolving /auth on origin. Verified live: stack up on :8085, signed delivery HMAC-checked at sink, @every 30s schedule firing, run history rendering, document.created landing in the live events feed. 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
4b7fdf35ad
commit
9e9a3d5f98
49 files changed
+3555
-32
No files matched your search
@@ -0,0 +1,194 @@
|
||||
/* generated using openapi-typescript-codegen -- do not edit */
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
import type { CreateScheduledJobRequest } from '../models/CreateScheduledJobRequest';
|
||||
import type { ScheduledJobCreateResponse } from '../models/ScheduledJobCreateResponse';
|
||||
import type { ScheduledJobListResponse } from '../models/ScheduledJobListResponse';
|
||||
import type { ScheduledJobRun } from '../models/ScheduledJobRun';
|
||||
import type { ScheduledJobRunListResponse } from '../models/ScheduledJobRunListResponse';
|
||||
import type { UpdateScheduledJobRequest } from '../models/UpdateScheduledJobRequest';
|
||||
import type { CancelablePromise } from '../core/CancelablePromise';
|
||||
import { OpenAPI } from '../core/OpenAPI';
|
||||
import { request as __request } from '../core/request';
|
||||
export class AutomationService {
|
||||
/**
|
||||
* @returns ScheduledJobListResponse Scheduled jobs for the project
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static listScheduledJobs({
|
||||
projectId,
|
||||
}: {
|
||||
projectId: string,
|
||||
}): CancelablePromise<ScheduledJobListResponse> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'GET',
|
||||
url: '/projects/{projectID}/jobs',
|
||||
path: {
|
||||
'projectID': projectId,
|
||||
},
|
||||
errors: {
|
||||
401: `Error response`,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Runs a signed POST to the job URL on a cron schedule (standard 5-field cron or @every/@hourly descriptors). Payload is signed X-Primora-Signature like webhook deliveries; an empty secret generates one returned once. HTTPS required for public targets, HTTP allowed for private/self-hosted.
|
||||
* @returns ScheduledJobCreateResponse Job created
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static createScheduledJob({
|
||||
projectId,
|
||||
requestBody,
|
||||
}: {
|
||||
projectId: string,
|
||||
requestBody: CreateScheduledJobRequest,
|
||||
}): CancelablePromise<ScheduledJobCreateResponse> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'POST',
|
||||
url: '/projects/{projectID}/jobs',
|
||||
path: {
|
||||
'projectID': projectId,
|
||||
},
|
||||
body: requestBody,
|
||||
mediaType: 'application/json',
|
||||
errors: {
|
||||
400: `Error response`,
|
||||
401: `Error response`,
|
||||
409: `Error response`,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @returns ScheduledJobCreateResponse Job updated
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static updateScheduledJob({
|
||||
projectId,
|
||||
jobId,
|
||||
requestBody,
|
||||
}: {
|
||||
projectId: string,
|
||||
jobId: string,
|
||||
requestBody: UpdateScheduledJobRequest,
|
||||
}): CancelablePromise<ScheduledJobCreateResponse> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'PATCH',
|
||||
url: '/projects/{projectID}/jobs/{jobID}',
|
||||
path: {
|
||||
'projectID': projectId,
|
||||
'jobID': jobId,
|
||||
},
|
||||
body: requestBody,
|
||||
mediaType: 'application/json',
|
||||
errors: {
|
||||
404: `Error response`,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @returns void
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static deleteScheduledJob({
|
||||
projectId,
|
||||
jobId,
|
||||
}: {
|
||||
projectId: string,
|
||||
jobId: string,
|
||||
}): CancelablePromise<void> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'DELETE',
|
||||
url: '/projects/{projectID}/jobs/{jobID}',
|
||||
path: {
|
||||
'projectID': projectId,
|
||||
'jobID': jobId,
|
||||
},
|
||||
errors: {
|
||||
404: `Error response`,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Recent executions, newest first. History is capped at 200 runs per job.
|
||||
* @returns ScheduledJobRunListResponse Job run history
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static listScheduledJobRuns({
|
||||
projectId,
|
||||
jobId,
|
||||
limit = 50,
|
||||
}: {
|
||||
projectId: string,
|
||||
jobId: string,
|
||||
limit?: number,
|
||||
}): CancelablePromise<ScheduledJobRunListResponse> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'GET',
|
||||
url: '/projects/{projectID}/jobs/{jobID}/runs',
|
||||
path: {
|
||||
'projectID': projectId,
|
||||
'jobID': jobId,
|
||||
},
|
||||
query: {
|
||||
'limit': limit,
|
||||
},
|
||||
errors: {
|
||||
404: `Error response`,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Triggers an out-of-schedule manual run. Returns the run row in "running" state.
|
||||
* @returns ScheduledJobRun Manual run queued
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static runScheduledJob({
|
||||
projectId,
|
||||
jobId,
|
||||
}: {
|
||||
projectId: string,
|
||||
jobId: string,
|
||||
}): CancelablePromise<ScheduledJobRun> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'POST',
|
||||
url: '/projects/{projectID}/jobs/{jobID}/run',
|
||||
path: {
|
||||
'projectID': projectId,
|
||||
'jobID': jobId,
|
||||
},
|
||||
errors: {
|
||||
404: `Error response`,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Server-sent events stream of project domain events — document/object mutations, new issues, deploy markers, job runs. EventSource clients pass `?api_key=` or `?token=` since headers cannot be set.
|
||||
* @returns any text/event-stream of {type, occurred_at, data} messages
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static streamRealtimeEvents({
|
||||
projectId,
|
||||
apiKey,
|
||||
token,
|
||||
}: {
|
||||
projectId: string,
|
||||
apiKey?: string,
|
||||
token?: string,
|
||||
}): CancelablePromise<any> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'GET',
|
||||
url: '/projects/{projectID}/realtime/stream',
|
||||
path: {
|
||||
'projectID': projectId,
|
||||
},
|
||||
query: {
|
||||
'api_key': apiKey,
|
||||
'token': token,
|
||||
},
|
||||
errors: {
|
||||
401: `Error response`,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user