Skip to content

Execution SSE flow

The system uses an event-driven pipeline to run code and stream progress to the browser with Server-Sent Events. The Editor subscribes to a per-execution SSE stream and renders updates as the execution advances. When the result is ready, the stream delivers a result_stored event that already carries the final payload, so the browser can render immediately.

The flow starts when the API receives a request to execute a script. It writes an execution record in MongoDB and publishes an execution_requested event to Kafka. The coordinator and saga orchestrator pick it up, allocate resources, and send a command to the Kubernetes worker. The worker creates the pod and emits pod_created/pod_running. The pod monitor watches Kubernetes and emits pod and terminal execution events. The result processor listens for terminal events, writes the final state into the executions collection, and publishes a result_stored event.

The SSE router maintains a small pool of Kafka consumers and routes only the events that belong to a given execution into Redis, which backs the browser's SSE connection. Progress events like pod_running arrive quickly and render status changes without polling. The stream closes when result_stored is delivered — emitted only after the result processor has written the final output to MongoDB, with the event containing the final result payload.

Using result_stored as the terminal signal removes artificial waiting. Earlier iterations ended the SSE stream on execution_completed/failed/timeout and slept on the server to "give Mongo time" to commit. That pause is unnecessary once the stream ends only after the result processor confirms persistence.

This approach preserves clean attribution and ordering. The coordinator enriches pod creation commands with user information so pods are labeled correctly. The pod monitor converts Kubernetes phases into domain events. Timeout classification is deterministic: any pod finishing with reason=DeadlineExceeded results in an execution_timeout event. The result processor is the single writer of terminal state, so the UI never races the database — when the browser sees result_stored, the result is already present.