mirror of
https://github.com/euzu/tuliprox.git
synced 2026-10-20 23:02:34 +02:00
Feature/maintenance (#916)
* Maintenance mode * fix(hls): release origin slot before next origin I/O
This commit is contained in:
@@ -269,7 +269,8 @@ playlist_manager:playlist.read,playlist.write,source.read
|
||||
|
||||
Available Permissions: `config.read/write`, `source.read/write`, `user.read/write`, `playlist.read/write`,
|
||||
`library.read/write`,
|
||||
`system.read/write`, `epg.read/write`, `recording.read/create/manage/delete`. Note: Write does not imply Read. A group must explicitly
|
||||
`system.read/write`, `epg.read/write`, `recording.read/create/manage/delete`, `maintenance.read/write`.
|
||||
Note: Write does not imply Read. A group must explicitly
|
||||
grant both if users need
|
||||
to view
|
||||
and edit content.
|
||||
@@ -481,6 +482,7 @@ negative pattern does, so `["*", "!system.info"]` reads the way it looks.
|
||||
| `user.connection.denied` | warn | A user was refused a connection because their limits were full. |
|
||||
| `recording.queue.changed` | info | The recording queue changed. |
|
||||
| `recording.rules.changed` | info | The recording rule set changed. |
|
||||
| `maintenance.changed` | warn | An input was put into or taken out of maintenance mode. |
|
||||
| `scheduled_task.failed` | error | A scheduled task could not complete. |
|
||||
| `notification.dead_lettered` | error | A notification was permanently undeliverable and has been dropped. |
|
||||
| `user.created` | info | An API-proxy user account was created. |
|
||||
@@ -1197,6 +1199,7 @@ custom_stream_response_timeout_secs: 20
|
||||
* `user_account_expired.ts` (User's `exp_date` reached)
|
||||
* `panel_api_provisioning.ts` (Loops while a new Provider Account is generated via Panel API)
|
||||
* `hls_session_or_lease_expired.ts` (Shared-HLS session or access lease expired; restart stream)
|
||||
* `maintenance.ts` (The input is in maintenance mode; see [Maintenance mode](../rest-api-cookbook.md#maintenance-mode))
|
||||
|
||||
> **Note**: These Video files are all available in the docker image.
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ That makes it usable both for IPTV players and for media-server-oriented workflo
|
||||
- enforce user connection limits
|
||||
- prioritize higher-value sessions over lower-priority traffic
|
||||
- serve custom fallback videos for failure cases
|
||||
- put inputs into maintenance mode: new streams get a maintenance video, the provider is not contacted
|
||||
- persist optional stream history for per-variant connect/disconnect, startup-failure, and reconnect telemetry
|
||||
- aggregate optional QoS snapshots from stream history to rank equivalent channel variants by reliability
|
||||
|
||||
@@ -63,7 +64,8 @@ Tuliprox also includes:
|
||||
|
||||
Tuliprox supports role-based access control (RBAC) for the Web UI:
|
||||
|
||||
- fine-grained permissions across 7 domains (config, source, user, playlist, library, system, epg)
|
||||
- fine-grained permissions across 9 domains (config, source, user, playlist, library, system, epg, recording,
|
||||
maintenance)
|
||||
- custom groups with configurable permission sets
|
||||
- user-to-group assignments with union-based permission resolution
|
||||
- compact bitmask encoding in JWT claims for low-overhead permission checks
|
||||
|
||||
@@ -428,6 +428,12 @@ constant; pre-bump tokens become stale:
|
||||
Operators do **not** need to manually invalidate tokens on a schema bump; the next sign-in issues a
|
||||
token with the current schema and the user's derived `subject_id`.
|
||||
|
||||
## 10.1 Maintenance mode
|
||||
|
||||
A recording whose input is in maintenance when it would start is not started: it fails with
|
||||
`Input is in maintenance mode` without requesting a provider slot. Running recordings, including their internal
|
||||
reconnects, continue. Nothing is retried automatically when maintenance ends; use **Retry** on the failed task.
|
||||
|
||||
## 11. The removed `/file/record` route
|
||||
|
||||
`POST /file/record` and the whole `/api/v1/file/download/*` family are
|
||||
|
||||
@@ -349,6 +349,58 @@ Notes:
|
||||
are `null` for semantic errors without a source position (e.g. an invalid regex value).
|
||||
- The preview reads the target's already-processed playlist; it never contacts providers or triggers an update.
|
||||
|
||||
## Maintenance mode
|
||||
|
||||
An input can be taken out of service while its provider is down. While an input is in maintenance:
|
||||
|
||||
- every **new** stream request for it (live, VOD, series, catch-up, HLS entry, redirect mode) gets the
|
||||
`maintenance.ts` custom video instead of a provider connection,
|
||||
- playlist and EPG updates keep serving the last persisted playlist and EPG without contacting the provider,
|
||||
- probes, metadata resolution and Stalker refreshes for the input are paused,
|
||||
- DVR recordings that would start fail with `Input is in maintenance mode`; use **Retry** afterwards.
|
||||
|
||||
Running streams, seeks within them, and running recordings continue. The state is stored in
|
||||
`<storage_dir>/maintenance.json` and survives restarts. A corrupt file is moved aside as
|
||||
`maintenance.json.corrupt` and the server starts with no input in maintenance. A file that cannot be read at all
|
||||
(for example because of its permissions) stays in place; changes are then refused with `500` instead of overwriting
|
||||
it. A one-shot CLI update reads the file but never changes it. Entries for inputs that are removed
|
||||
from `source.yml` are dropped on the next source reload.
|
||||
|
||||
The dashboard shows a **Maintenance** card that turns red while any input is in maintenance.
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
BASE_URL="http://localhost:8901"
|
||||
TOKEN="PUT_YOUR_TOKEN_HERE"
|
||||
|
||||
# Put one input into maintenance, with an optional remark
|
||||
curl -s -X PUT "$BASE_URL/api/v1/maintenance/provider_a" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data-raw '{"reason":"Provider down"}'
|
||||
|
||||
# Take every input out of maintenance (`*`, URL-encoded as %2A)
|
||||
curl -s -X DELETE "$BASE_URL/api/v1/maintenance/%2A" -H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Current state
|
||||
curl -s "$BASE_URL/api/v1/maintenance" -H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
Every call answers with the complete state:
|
||||
|
||||
```json
|
||||
{
|
||||
"entries": { "provider_a": { "since": 1760350000, "reason": "Provider down" } },
|
||||
"inputs": ["provider_a", "provider_b"]
|
||||
}
|
||||
```
|
||||
|
||||
- `*` addresses all inputs known at the time of the call; an input literally named `*` cannot be addressed alone.
|
||||
- Putting an input that is already in maintenance updates its remark and keeps `since`.
|
||||
- Unknown inputs answer `404`, remarks longer than 500 characters `400`.
|
||||
- Without Web UI authentication the endpoints are as open as the other `/api/v1` routes.
|
||||
|
||||
## Available `/api/v1` Endpoints
|
||||
|
||||
This is a compact operator-oriented overview of the `/api/v1` REST API groups currently registered by the backend.
|
||||
@@ -369,6 +421,14 @@ This is a compact operator-oriented overview of the `/api/v1` REST API groups cu
|
||||
| `GET` | `/api/v1/qos-snapshots/{stream_identity_key}` | QoS detail for one stream |
|
||||
| `GET` | `/api/v1/geoip/update` | Trigger GeoIP DB update |
|
||||
|
||||
### Maintenance mode
|
||||
|
||||
| Method | Path | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `GET` | `/api/v1/maintenance` | Inputs in maintenance and all known input names (`maintenance.read`) |
|
||||
| `PUT` | `/api/v1/maintenance/{input}` | Put an input (or `*` for all) into maintenance, optional `{"reason": "..."}` body (`maintenance.write`) |
|
||||
| `DELETE` | `/api/v1/maintenance/{input}` | Take an input (or `*` for all) out of maintenance (`maintenance.write`) |
|
||||
|
||||
### Recordings
|
||||
|
||||
Recording REST is **commands only**. There is no list, task, status or quota
|
||||
@@ -659,6 +719,8 @@ With Web UI authentication enabled, many endpoints require matching permissions
|
||||
- `recording.create`
|
||||
- `recording.manage`
|
||||
- `recording.delete`
|
||||
- `maintenance.read`
|
||||
- `maintenance.write`
|
||||
|
||||
If a request is rejected, verify the logged-in Web UI user's RBAC group assignments first.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user