mirror of https://github.com/OpenVidu/openvidu.git
76 lines
5.9 KiB
Markdown
76 lines
5.9 KiB
Markdown
|
|
# Backend (`@openvidu-dashboard/backend`)
|
||
|
|
|
||
|
|
Express 5, Inversify, Zod and the official `mongodb` driver; TypeScript 6 strict ESM, relative imports end in `.js`.
|
||
|
|
Behaviour is specified in `openspec/specs/*-api`, `api-conventions`, `auth`, `status-api` and `editions-info`.
|
||
|
|
|
||
|
|
## Structure
|
||
|
|
|
||
|
|
- `src/lifecycle/startup.ts`: `startDashboard(options)` reads the configuration, connects to MongoDB, applies the
|
||
|
|
writer schema gate, builds the container, calls `configure` and the startup hooks, then listens. `TOKENS`
|
||
|
|
(`src/di/tokens.ts`) are bound with `toResolvedValue` factories, without decorators, so esbuild and Vitest need no
|
||
|
|
metadata. Exit codes go through `Shutdown.run(code)`.
|
||
|
|
- Routes are declared once in the `RouteRegistry` (`src/api/route-registry.ts`): method, path under `/api/v1`, edition,
|
||
|
|
`feature` of a PRO route, security (`public`, `bearer`, `optional-bearer`), Zod schemas of params, query, body and
|
||
|
|
responses, and the handler. It drives validation, authentication and the OpenAPI document (only when `NODE_ENV` is
|
||
|
|
not `production`).
|
||
|
|
- PRO routes are only locks here: `registry.lock({ method, path, feature })` answers `403 PRO_FEATURE` after
|
||
|
|
authentication and stays out of the OpenAPI document. An edition that extends CE registers the full definition in the
|
||
|
|
lock's place (mount order kept) and swaps a CE route for its extension with `registry.replace()`; a `pro` startup
|
||
|
|
that leaves a lock without a definition exits with code 1, naming it.
|
||
|
|
- Extension tokens that `configure` can rebind: `Features`, `LicenseInfo`, `AnalyticsCatalogue` (metrics and
|
||
|
|
dimensions the analytics endpoints compute) and `OverviewExtension` (extra overview fields, merged before the
|
||
|
|
`ETag`). A `configure` that throws stops the startup with code 1.
|
||
|
|
- A resource slice is `src/<resource>/`: `*-schemas.ts` (Zod), `*-query.ts` (pure filter builders), `*-repository.ts`
|
||
|
|
(MongoDB), `*-service.ts` (paging, mapping), `*-responses.ts` (OpenAPI response schemas, checked against the mappers
|
||
|
|
in unit tests) and `*-routes.ts` (`register<Resource>Routes`: the CE routes and the locks of the PRO ones).
|
||
|
|
- Zod schemas live here because typings has no runtime dependencies; typings declares the matching types in
|
||
|
|
`src/api/`. Errors use `{ error: { code, message, details? } }` with `ErrorCode`.
|
||
|
|
- Shared query pieces in `src/api/`: `rangedQuery(now, shape)` for ranged queries (relative grammar resolved at parse
|
||
|
|
time) and `optionalRangeQuery(now, shape)` when the bounds are optional, `pageQuery()` for keyset pages on an index
|
||
|
|
ending in `_id`, `indexOrderedPage()` when the index does not order by `_id`, and `rankedPage()` with
|
||
|
|
`assertRankedRange()` (`src/api/ranked.ts`) for metric sorts ranked in memory at the cursor's `asOf`. Calendar math in
|
||
|
|
a time zone uses date-fns and `@date-fns/tz`.
|
||
|
|
- `src/stats/stats-mode.ts`: `StatsModeReader` reads the writer's `stats_detail` for `GET /info`.
|
||
|
|
- `src/analytics/` answers from the rollup collections only: `analytics-planner.ts` picks the granularity, source
|
||
|
|
collection and bucket grid, `analytics-counters.ts` folds the documents in process with the definitions of the
|
||
|
|
catalogue, `AnalyticsCache` keeps the folds of completed documents and `AnalyticsFeatureGate` rejects PRO metrics,
|
||
|
|
dimensions and node scopes on CE.
|
||
|
|
- `src/status/freshness.ts` marks active rooms and participants `stale` with the backend clock, from the typings
|
||
|
|
`freshnessWindows()`.
|
||
|
|
- `src/index.ts` exports what an extending backend builds on: the startup, tokens and registry, the generic query,
|
||
|
|
cursor, response and freshness pieces, and the list pieces that entity details extend.
|
||
|
|
- Exact identifiers (`RM_`, `PA_`, `EG_`, `IN_`, `TR_`) are matched with `ENTITY_ID_PATTERNS`, `isEntityId()` and
|
||
|
|
`entityIdKind()` from typings.
|
||
|
|
- Configuration variables are new `DASHBOARD_*`, or `DATABASE_*` for database connection settings; legacy names keep
|
||
|
|
their 3.9 meaning (`src/config/variables.ts`, unit-tested). The README lists them all.
|
||
|
|
|
||
|
|
## Rules
|
||
|
|
|
||
|
|
- Repositories own the queries. Every list, detail and time-series query is backed by an index and asserted with
|
||
|
|
`expectIndexBacked` (`test/support/query-plan.ts`: no COLLSCAN above 1 000 documents, bounded `totalDocsExamined`).
|
||
|
|
|
||
|
|
## Tests
|
||
|
|
|
||
|
|
- Unit tests: Vitest (`pnpm test`).
|
||
|
|
- Integration tests: `test/integration/`, Vitest projects `integration` and `integration-plans` (the `*query-plan`
|
||
|
|
suites, run after the rest so their data generation does not skew the latency budgets). `test/support/` starts a
|
||
|
|
replica set with Testcontainers on `openvidu/mongodb:8.0.29-r1` (the official `mongo:8.0` refuses Linux kernels 6.19
|
||
|
|
and newer), or uses `DASHBOARD_TEST_MONGO_URI`; `DASHBOARD_TEST_MONGO_IMAGE` overrides the image. Through pnpm
|
||
|
|
without Docker the suites report themselves skipped; `./dashboard.sh test-integration` fails instead.
|
||
|
|
- They also need `openssl` (test CA of the TLS case) and build the package to run `dist/server.js` as a process.
|
||
|
|
`test/support/boot.ts` starts the dashboard in-process on a fresh database with a controllable clock.
|
||
|
|
- `test/support/` is exported to the suites of extending packages as `@openvidu-dashboard/backend/testing` (source
|
||
|
|
only, never in `dist`), and the MongoDB global setup as `@openvidu-dashboard/backend/testing/global-mongo`.
|
||
|
|
- Query-plan suites generate data with `dashboard-ce/tools/data-generator` and report the p95 of their budget. Design
|
||
|
|
figures come from scenario M over 7 days on a MongoDB with room for it, run alone:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
DASHBOARD_TEST_MONGO_URI=<uri> ROOMS_PLAN_SCENARIO=M ROOMS_PLAN_DAYS=7 ROOMS_PLAN_REPORT=<file> \
|
||
|
|
pnpm --filter @openvidu-dashboard/backend exec vitest run --project integration-plans \
|
||
|
|
test/integration/rooms-query-plan.test.ts
|
||
|
|
```
|
||
|
|
|
||
|
|
The other suites take the prefixes `PARTICIPANTS_PLAN_`, `EGRESS_PLAN_`, `INGRESS_PLAN_`, `OVERVIEW_PLAN_` and
|
||
|
|
`ANALYTICS_PLAN_`. `DASHBOARD_TEST_LATENCY_BUDGETS=report` (set in CI) turns p95 overruns into warnings; plan
|
||
|
|
assertions fail either way.
|