mirror of https://github.com/OpenVidu/openvidu.git
87 lines
5.0 KiB
Markdown
87 lines
5.0 KiB
Markdown
# 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
|