mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-12 12:05:07 +00:00
feat(serve): hot-reload service repos on a timer without a restart
Add serve.services_refresh_interval; refresh pulls the repos and re-imports only the changed services, staging any with active jobs until they finish. Report skipped/broken services in the log and on /api/services.
This commit is contained in:
@@ -62,7 +62,7 @@ If the update check fails (for example, no network), `update_available` and `lat
|
||||
|
||||
### `GET /api/services`
|
||||
|
||||
Show the streaming services available on this server, filtered by your allowlist. Each entry gives the service's tag, matching rules, capability flags, and its CLI parameters (useful when you make a UI that accepts service-specific options).
|
||||
Show the streaming services available on this server, filtered by your allowlist. Each entry gives the service's tag, matching rules, capability flags, and its CLI parameters (useful when you make a UI that accepts service-specific options). `load_errors` lists the services the server skipped because they failed to import, at startup or after a service repository refresh; the server also writes each one to its log. An entry marked `pending_update` has newer code staged: it keeps its current code until its running or queued jobs finish.
|
||||
|
||||
=== "Request"
|
||||
|
||||
@@ -100,7 +100,8 @@ Show the streaming services available on this server, filtered by your allowlist
|
||||
"has_drm": true,
|
||||
"auth_methods": ["cookies"]
|
||||
}
|
||||
]
|
||||
],
|
||||
"load_errors": []
|
||||
}
|
||||
```
|
||||
|
||||
@@ -118,6 +119,7 @@ Field notes:
|
||||
| `needs_auth` | Whether the service overrides `authenticate()`. |
|
||||
| `has_search` | Whether the service supports `POST /api/search`. |
|
||||
| `has_drm` | Whether the service overrides a Widevine or PlayReady license hook. |
|
||||
| `pending_update` | Set to `true` while a service repository refresh waits for this service's jobs to finish before it swaps in the new code. Absent otherwise. |
|
||||
| `auth_methods` | Declared or inferred auth methods, e.g. `["cookies"]`, `["credentials"]`. |
|
||||
|
||||
| Status | Meaning |
|
||||
@@ -773,7 +775,7 @@ The `409` guard is about active file I/O, not an arbitrary lock. An in-flight jo
|
||||
|
||||
### `POST /api/maintenance/refresh-services`
|
||||
|
||||
git-pull every service repository configured under `directories.services`. `refreshed` becomes `true` when all repos updated successfully, or when you configure no repository.
|
||||
git-pull every service repository configured under `directories.services` and re-import the services that changed, without a restart. `refreshed` becomes `true` when all repos updated successfully, or when you configure no repository. `deferred` lists the services that have a running or queued job: they keep their current code until that job finishes, then swap. `load_errors` lists the services whose new code failed to import; the server drops them until the next successful refresh.
|
||||
|
||||
=== "Response `200`"
|
||||
|
||||
@@ -781,7 +783,13 @@ git-pull every service repository configured under `directories.services`. `refr
|
||||
{
|
||||
"refreshed": true,
|
||||
"repos": [
|
||||
{ "spec": "github.com/example/services", "updated": true, "changes": ["~EXAMPLE"] }
|
||||
{
|
||||
"spec": "github.com/example/services",
|
||||
"updated": true,
|
||||
"changes": ["~EXAMPLE", "+EXAMPLE2"],
|
||||
"deferred": ["EXAMPLE"],
|
||||
"load_errors": []
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -183,7 +183,7 @@ request and response in full.
|
||||
|---|---|---|
|
||||
| `POST` | `/api/maintenance/clear-cache` | Clear the cache directory. |
|
||||
| `POST` | `/api/maintenance/clear-temp` | Clear the temp directory. |
|
||||
| `POST` | `/api/maintenance/refresh-services` | `git pull` each configured service repository. |
|
||||
| `POST` | `/api/maintenance/refresh-services` | `git pull` each configured service repository and re-import the services that changed. |
|
||||
|
||||
### Remote-download sessions
|
||||
|
||||
|
||||
@@ -550,7 +550,7 @@ unshackle util COMMAND [ARGS]...
|
||||
unshackle util refresh-services
|
||||
```
|
||||
|
||||
Force a refresh (git pull / hard reset) of all service repos configured under `directories.services`.
|
||||
Force a refresh (git pull / hard reset) of all service repos configured under `directories.services`. This updates the clones on disk. A server that is already running reloads the changed services through `POST /api/maintenance/refresh-services` or `serve.services_refresh_interval` instead.
|
||||
|
||||
### `util crop PATH ASPECT`
|
||||
|
||||
|
||||
@@ -76,6 +76,14 @@ directories:
|
||||
services_repo_force: true
|
||||
```
|
||||
|
||||
!!! info "Refresh inside `serve`"
|
||||
A running server does not restart to pick up a refresh. Both the periodic refresh
|
||||
(`serve.services_refresh_interval`, see [serve](services.md#serve)) and the manual
|
||||
`POST /api/maintenance/refresh-services` endpoint hard-reset the clones and then re-import
|
||||
only the services that changed. A service with a running or queued download job keeps its
|
||||
current code until that job finishes, then swaps; `GET /api/services` marks it with
|
||||
`pending_update` in the meantime.
|
||||
|
||||
!!! warning "Read-only installs and reinstalls"
|
||||
If the services directory lives inside the installed package, a reinstall can delete the
|
||||
`_repos` clones. They are re-cloned on next use. On **read-only installs** you must
|
||||
|
||||
@@ -117,6 +117,7 @@ is the [REST API](../../dev/rest-api/index.md) section. These are the config key
|
||||
| `max_sessions` | int | `100` | Maximum concurrent sessions. |
|
||||
| `history_limit` | int | `100` | How many finished jobs to retain in history. |
|
||||
| `compression_level` | int | `1` | gzip level for responses. |
|
||||
| `services_refresh_interval` | int (s) | `0` | How often the server pulls the git-backed service repositories in `directories.services` and hot-reloads the services that changed. `0` turns it off. A service with a running or queued job swaps to the new code as soon as its last job finishes. |
|
||||
| `global_speed_limit` | str | *(unlimited)* | Server-wide download speed cap, e.g. `10M`, `1.5G` or plain bytes/sec (same format as `speed_limit`). One shared budget across all concurrent jobs; per-job speed limits are ignored while it is set. |
|
||||
| `cdm_overrides` | list or bool | *(unset)* | Allowed per-request CDM overrides: a list of permitted device names, or `true` for any. Unset rejects every override. |
|
||||
| `allow_job_credentials` | bool | `false` | Permit clients to supply credentials per job. |
|
||||
@@ -141,11 +142,12 @@ serve:
|
||||
api_secret: change-me
|
||||
remote_only: true
|
||||
services: [EXAMPLE1, EXAMPLE2]
|
||||
services_refresh_interval: 3600 # pull the service repositories hourly and reload what changed
|
||||
# server-wide download defaults (same keys as the `dl:` block)
|
||||
downloads: 3
|
||||
best_available: true
|
||||
users:
|
||||
a1b2c3d4: # this user's API key
|
||||
a1b2c3d4: # this user's API key
|
||||
services: [EXAMPLE1] # may only use EXAMPLE1
|
||||
e5f6a7b8:
|
||||
server_cdm: true # this key may have the server do the licensing
|
||||
|
||||
Reference in New Issue
Block a user