diff --git a/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/.openspec.yaml b/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/.openspec.yaml new file mode 100644 index 000000000..97e364202 --- /dev/null +++ b/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-10-27 diff --git a/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/design.md b/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/design.md new file mode 100644 index 000000000..bc0df7fef --- /dev/null +++ b/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/design.md @@ -0,0 +1,27 @@ +# Design + +## Context + +- On the first `SIGINT`, `SIGTERM` or `SIGQUIT` the server calls `Stop(false)`: it drains the router and waits, every + 5 s, until it has no participants. A second signal calls `Stop(true)`, which does not wait; the server then closes + its rooms with `SERVER_SHUTDOWN` and `openvidu.Stop` flushes telemetry and the analytics queues for at most 5 s. +- `docker-compose down` sends one `SIGTERM` and kills the container after its stop grace period. + +## Goals / Non-Goals + +**Goals:** +- The spec says what a planned stop and a forced stop leave in the store. + +**Non-Goals:** +- Closing rooms on the first signal, which would cut the graceful drain of media nodes. + +## Decisions + +### Describe the drain + +The drain is the server's contract with clients and with the scale-in of media nodes; the analytics writer follows it. +The requirement now covers the drain, the second signal and the kill during the drain. + +### Data model + +- No change. diff --git a/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/proposal.md b/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/proposal.md new file mode 100644 index 000000000..a3d023932 --- /dev/null +++ b/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/proposal.md @@ -0,0 +1,39 @@ +# Proposal + +## Why + +The "Graceful shutdown" requirement says that on `SIGTERM` a node with active rooms closes them with `SERVER_SHUTDOWN` +and flushes their end. The server does not do that: the first `SIGTERM` drains it (no new participants, wait for the +present ones to leave) and only a second signal closes the rooms. A forced stop of a node (`docker-compose down`, which +kills it after its grace period) therefore ends while it drains, writes nothing more, and the reconciler closes its +sessions as for a crashed node. The integration test of that case expects leave events and fails. + +## What Changes + +- The requirement describes the drain: during it the participants that leave are written as usual; a second signal + closes the rooms with `SERVER_SHUTDOWN`; once the rooms are closed, the flush works as before. +- A node killed while it drains is left to the reconciler, as a crashed one. +- No server or writer behaviour changes. + +Scope excludes the following: +- The drain itself and the stop of media nodes in the deployments. + +Edition: CE and PRO (server). Repositories: the specs of the dashboard, and the end-to-end reconciler tests of the +deployments (forced media node stop). + +CHANGELOG: none. + +## Capabilities + +### New Capabilities + +None. + +### Modified Capabilities + +- `server-analytics-writer`: "Graceful shutdown" describes the drain and the forced stop. + +## Impact + +- Specs only, and the forced media node stop case of the end-to-end reconciler tests, which now expects the + reconciler to close the sessions of a node stopped by force. diff --git a/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/specs/server-analytics-writer/spec.md b/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/specs/server-analytics-writer/spec.md new file mode 100644 index 000000000..9dadf97ee --- /dev/null +++ b/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/specs/server-analytics-writer/spec.md @@ -0,0 +1,24 @@ +## MODIFIED Requirements + +### Requirement: Graceful shutdown +Edition: CE and PRO. On a first `SIGTERM` or `SIGINT` the server drains: it takes no new participants and waits for +the present ones to leave, whose leave events are written as usual; a second signal closes the rooms with +`SERVER_SHUTDOWN`. Once the rooms are closed the server SHALL flush the telemetry stats workers and operation queue +into the writer and write every queued event and stat before exiting, waiting at most 5 s; entries not written in that +window SHALL be counted as dropped. A node killed while it drains writes nothing more and its open sessions are left +to the reconciler. + +#### Scenario: Planned restart +- **GIVEN** a node with active rooms and participants +- **WHEN** it receives `SIGTERM` and then a second `SIGTERM` +- **THEN** the database holds the `ROOM_ENDED (ROOM_END_SERVER_SHUTDOWN)` and `PARTICIPANT_LEFT` events and the entities are `closed`/`left` with the final stats flushed + +#### Scenario: Killed while draining +- **GIVEN** a node with active participants that receives one `SIGTERM` +- **WHEN** it is killed before they leave, as `docker-compose down` does after its grace period +- **THEN** no end event of those sessions is written and the reconciler closes them as for a crashed node, with `closedBy: "reconciler"` + +#### Scenario: Database unavailable at shutdown +- **GIVEN** an unreachable database +- **WHEN** the node receives `SIGTERM` +- **THEN** the process exits within 5 s of the signal and logs the number of dropped entries diff --git a/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/tasks.md b/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/tasks.md new file mode 100644 index 000000000..99f2fdad7 --- /dev/null +++ b/openvidu-dashboard/openspec/changes/graceful-shutdown-drain/tasks.md @@ -0,0 +1,14 @@ +# Tasks + +## 1. Tests + +- [ ] 1.1 Make the forced media node stop case of the end-to-end reconciler tests expect the reconciler to close the + sessions of the node. Verify by running it on the deployment playground. + +## 2. Docs and CHANGELOG + +- [x] 2.1 No CHANGELOG line and no `AGENTS.md` change. Verify by reading the change against both. + +## 3. Integration check + +- [x] 3.1 Run the spec validation and the format check of the dashboard. Verify that they pass.