mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-12 12:05:07 +00:00
feat(remote): reopen a lost remote session and resume at the current title
This commit is contained in:
@@ -45,6 +45,7 @@ Health check. **This is the only route exempt from authentication**: you can cal
|
||||
"status": "ok",
|
||||
"version": "5.3.0",
|
||||
"code_hash": "1d22a1e",
|
||||
"draining": false,
|
||||
"update_check": {
|
||||
"update_available": false,
|
||||
"current_version": "5.3.0",
|
||||
@@ -55,6 +56,8 @@ Health check. **This is the only route exempt from authentication**: you can cal
|
||||
|
||||
`code_hash` fingerprints the framework source the server operates, so it names the code itself rather than the release. It is the same value for a git checkout and for an installed package built from that checkout. It changes when you edit anything under `unshackle/core`, `unshackle/commands`, `unshackle/utils`, or `unshackle/vaults`. Service modules are not included. unshackle sets the value to `null` only when it cannot read the source files.
|
||||
|
||||
`draining` is `true` while the server refuses new remote sessions and jobs before a restart.
|
||||
|
||||
If the update check fails (for example, no network), `update_available` and `latest_version` are `null` while `current_version` still reports the installed version.
|
||||
|
||||
| Status | Meaning |
|
||||
@@ -1243,6 +1246,7 @@ Return remote session metadata and validity.
|
||||
"service": "EXAMPLE",
|
||||
"valid": true,
|
||||
"expires_in": 300,
|
||||
"draining": false,
|
||||
"track_count": 4,
|
||||
"title_count": 10
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ while the server restarts.
|
||||
| `SESSION_NOT_FOUND` | 404 | The remote-dl session does not exist or has expired. |
|
||||
| `TRACK_NOT_FOUND` | 404 | A referenced track ID is not present in the remote session. |
|
||||
| `CONFLICT` | 409 | The target resource is in a state that disallows the action (retrying a running job, prioritising a non-queued job, clearing cache during an active download). |
|
||||
| `SERVER_DRAINING` | 409 | The server is about to restart and starts no new remote session or download job. Open work continues. Retryable after the restart. |
|
||||
| `SERVER_DRAINING` | 409 | The server is about to restart and starts no new remote session or download job. Open work continues. Retryable after the restart. A `dl --remote` client waits for the restart and opens a new remote session. |
|
||||
| `SERVICE_ERROR` | 422 | The streaming service's API returned an error, or the service does not support the requested operation. |
|
||||
| `DRM_ERROR` | 422 | DRM or license acquisition failed. |
|
||||
| `RATE_LIMITED` | 429 | The streaming service is rate-limiting requests. Retryable. |
|
||||
|
||||
@@ -625,11 +625,15 @@ existing file as a directory, and logs a warning.
|
||||
"service": "EXAMPLE",
|
||||
"valid": true,
|
||||
"expires_in": 300,
|
||||
"draining": false,
|
||||
"track_count": 12,
|
||||
"title_count": 40
|
||||
}
|
||||
```
|
||||
|
||||
`draining` is `true` after the operator starts a drain before a restart. The client reads
|
||||
it before each title, so it knows of the restart before it occurs.
|
||||
|
||||
!!! warning "`expires_in` is the configured TTL, not time remaining"
|
||||
The `expires_in` value reports the store's configured `session_ttl`, not the
|
||||
seconds left before this specific remote session expires.
|
||||
@@ -660,6 +664,26 @@ remote session API and a good template for any client.
|
||||
(merging returned `session_headers`/`session_cookie_jar`, re-parsing `manifests`) →
|
||||
get the licence in proxy mode or `server_cdm` mode → `close()` (`DELETE`, saving any returned
|
||||
`cache`).
|
||||
- **Server restarts.** The server keeps remote sessions in memory only, so a restart
|
||||
loses them all. The client recovers in two ways:
|
||||
- A drain announced through `draining`: the client finishes the current title, then
|
||||
closes its remote session, so the drain can end and the refreshed cache comes back.
|
||||
It waits until `/api/health` reports the restarted server without `draining`,
|
||||
opens a new remote session, and continues with the next title.
|
||||
- A lost remote session (`SESSION_NOT_FOUND`, a connection error, a timeout, a closed
|
||||
tunnel or a gateway error page): the client waits for `/api/health`, then checks the
|
||||
old remote session. A live remote session takes the call again only after a connection
|
||||
error, because a timed-out call can already have run. A lost one is replaced: the
|
||||
client opens a new remote session, sends `titles` and the current title's `tracks`
|
||||
again, and then sends the failed call again. A title or track that the new remote
|
||||
session gives another ID keeps its old ID on the client, and the client sends the
|
||||
new ID. The client matches a title by season and episode number, and a track by its
|
||||
attributes.
|
||||
|
||||
The client waits up to 30 minutes for the server, which covers a deploy's drain. It
|
||||
stops with an error if the new remote session licenses differently from the old one,
|
||||
for example after a change to the API key's `server_cdm` grant. An interactive login
|
||||
asks for its input again.
|
||||
- **Server resolution.** `resolve_server()` reads `config.remote_services.<name>`
|
||||
into `{url, api_key, services, server_cdm}`, injecting the `server_cdm` flag into
|
||||
the services map as `_server_cdm`.
|
||||
|
||||
Reference in New Issue
Block a user