feat(apiserver): SSE job-event stream + EventBroker (Phase 2, ADR-004)
Add a Server-Sent Events endpoint /xce/v1/events streaming job lifecycle events (job.created/updated/deleted/finished) to subscribers. The DefaultHandler now publishes every job event to a process-wide EventBroker; the SSE handler subscribes and streams JSON frames with a keep-alive comment during idle. - backend/broker.go: thread-safe fan-out Broker (drops for slow consumers so the notification path never blocks), Event type with job_status string. - backend/handler.go: OnJob* publish to DefaultBroker. - controllers/events.go: SSE handler (gin, text/event-stream, keep-alive). - router + whitelist + rbac: /xce/v1/events route, event:subscribe permission granted to mcp_readonly/mcp_operator/cluster_admin. - Tests: broker fan-out/slow-consumer/unsubscribe, handler publishes, SSE end-to-end via httptest. Verified live on t1: SSE stream delivered job.updated PEND→RUN events for a submitted job. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
f096be1db5
commit
898de0cebd
9 changed files with 420 additions and 0 deletions
|
|
@ -13,14 +13,17 @@ type DefaultHandler struct{}
|
|||
|
||||
func (h *DefaultHandler) OnJobCreated(job *models.JobInfo) {
|
||||
store.Jobs.Put(uint64(job.Unique_JobID), *job)
|
||||
DefaultBroker.Publish(Event{Type: EventJobCreated, JobID: uint64(job.Unique_JobID), Status: models.JobStateStr(job.JobStatus), Job: job})
|
||||
}
|
||||
|
||||
func (h *DefaultHandler) OnJobUpdated(job *models.JobInfo) {
|
||||
store.Jobs.Put(uint64(job.Unique_JobID), *job)
|
||||
DefaultBroker.Publish(Event{Type: EventJobUpdated, JobID: uint64(job.Unique_JobID), Status: models.JobStateStr(job.JobStatus), Job: job})
|
||||
}
|
||||
|
||||
func (h *DefaultHandler) OnJobDeleted(jobid uint64) {
|
||||
store.Jobs.Delete(jobid)
|
||||
DefaultBroker.Publish(Event{Type: EventJobDeleted, JobID: jobid})
|
||||
}
|
||||
|
||||
func (h *DefaultHandler) OnJobFinished(jobid uint64, exitCode int) {
|
||||
|
|
@ -34,6 +37,7 @@ func (h *DefaultHandler) OnJobFinished(jobid uint64, exitCode int) {
|
|||
existing.JobStatus = models.JOBSTAT["EXIT"]
|
||||
}
|
||||
store.Jobs.Put(jobid, existing)
|
||||
DefaultBroker.Publish(Event{Type: EventJobFinished, JobID: jobid, ExitCode: exitCode})
|
||||
}
|
||||
|
||||
func (h *DefaultHandler) OnQueueUpdated(queue *models.QueueInfo) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue