openvidu/openvidu-dashboard/openspec/specs/status-api/spec.md

87 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# status-api Specification
## Purpose
The server status endpoint: a cheap document with the writer schema status, the legacy migration and the writer
health that every page of the dashboard polls at a fixed cadence, whatever the page and its auto-refresh.
## Requirements
### Requirement: Status endpoint
Edition: CE. `GET /api/v1/status` SHALL require a bearer token, take no parameters and answer `200` with `generatedAt`
(the MongoDB clock), `schema` and `migration` with the same shapes and sources as `GET /api/v1/info`, and
`writer { lastSeenAt?, nodes, aliveNodes, batchIntervalMs? }`. A node's fresh window is `max(30 s, 1.5 × I + 5 s)`, I
being its `batchIntervalMs` (10 s when absent). The response carries `Cache-Control: private, no-store`.
#### Scenario: Running migration
- **GIVEN** two nodes last seen 4 s and 12 s ago, both with `batchIntervalMs: 10000`, writer schema 1 equal to the dashboard's and a migration with `processed` 400000 of `total` 1200000
- **WHEN** the client requests `GET /api/v1/status` with a valid token
- **THEN** the response is `200`, `writer.lastSeenAt` is the 4 s old timestamp, `writer.nodes` is `2`, `writer.aliveNodes` is `2`, `writer.batchIntervalMs` is `10000`, `schema.status` is `"ok"` and `migration` is `{ state: "running", progress: { processed: 400000, total: 1200000, startedAt } }`
#### Scenario: Writer never seen
- **GIVEN** empty `nodes` and `schema_meta` collections
- **WHEN** the client requests the status
- **THEN** `writer` is `{ nodes: 0, aliveNodes: 0 }`, `schema.status` is `"uninitialized"` and `migration.state` is `"none"`
#### Scenario: A node stopped reporting
- **GIVEN** `node-a` seen 4 s ago and `node-b` seen 50 s ago
- **WHEN** the client requests the status
- **THEN** `writer.nodes` is `2` and `writer.aliveNodes` is `1`
#### Scenario: Each node judged by its own interval
- **GIVEN** `node-a` with `batchIntervalMs: 60000` seen 80 s ago and `node-b` with `batchIntervalMs: 10000` seen 40 s ago
- **WHEN** the client requests the status
- **THEN** `writer.aliveNodes` is `1` (`node-a`, whose fresh window is 95 s) and `writer.batchIntervalMs` is `60000`
#### Scenario: Largest interval of the last hour
- **GIVEN** `node-a` with `batchIntervalMs: 10000` seen 5 s ago, `node-b` with `30000` seen 20 minutes ago and `node-c` with `60000` seen 2 hours ago
- **WHEN** the client requests the status
- **THEN** `writer.batchIntervalMs` is `30000`
#### Scenario: Nodes without a reported interval
- **GIVEN** one node seen 25 s ago whose document has no `batchIntervalMs`
- **WHEN** the client requests the status
- **THEN** `writer.aliveNodes` is `1`, judged with the 30 s window of a 10 s interval, and `writer` has no `batchIntervalMs`
#### Scenario: No token
- **WHEN** the client requests `GET /api/v1/status` without `Authorization`
- **THEN** the response is `401` with code `UNAUTHORIZED`
#### Scenario: Writer fields
- **WHEN** a client with a bearer token requests `GET /api/v1/status`
- **THEN** `writer.lastSeenAt` is the newest `nodes.lastSeenAt`, `writer.nodes` the node count, `writer.aliveNodes` the
nodes whose `lastSeenAt` is within their own fresh window of `generatedAt`, and `writer.batchIntervalMs` the largest
`nodes.batchIntervalMs` among the nodes whose `lastSeenAt` is within one hour of `generatedAt`, absent when none of
them reports one
### Requirement: Cheap status reads
Edition: CE. Each status request SHALL read only the `schema_meta` and `nodes` collections, both whole and bounded by
the number of server nodes, plus the MongoDB clock; it SHALL compute no storage, database or retention facts, which
stay in `GET /api/v1/info`.
#### Scenario: Commands of one request
- **GIVEN** a database generated by the data generator at scenario M
- **WHEN** the client requests the status with MongoDB command monitoring on
- **THEN** the only `find` commands target `schema_meta` and `nodes`, and no `aggregate`, `collStats` or `buildInfo` command is sent
### Requirement: Freshness windows
Edition: CE. Freshness windows SHALL derive from a batch interval I (`writer.batchIntervalMs` of the status, 10 s
when absent) through the typings helper `freshnessWindows`: fresh `max(30 s, 1.5 × I + 5 s)`, silent
`max(60 s, 2 × I + 15 s)` and stale `max(90 s, 60 s + I + 15 s)`. Clients SHALL judge the writer fresh and silent
by comparing `generatedAt − writer.lastSeenAt` with these windows, never with fixed thresholds.
#### Scenario: Default interval
- **GIVEN** a status whose `writer.batchIntervalMs` is `10000`, or absent
- **WHEN** a client derives the windows
- **THEN** fresh is 30 000 ms, silent 60 000 ms and stale 90 000 ms
#### Scenario: Slow writer
- **GIVEN** a status whose `writer.batchIntervalMs` is `60000`
- **WHEN** a client derives the windows
- **THEN** fresh is 95 000 ms, silent 135 000 ms and stale 135 000 ms
#### Scenario: Last batch 70 s old at a 60 s interval
- **GIVEN** a status with `writer.batchIntervalMs: 60000` and `writer.lastSeenAt` 70 s before `generatedAt`
- **WHEN** a client judges the writer
- **THEN** the writer is fresh and not silent