178 lines
7.0 KiB
Markdown
178 lines
7.0 KiB
Markdown
# Telegram UX
|
|
|
|
Archive Control adds a separate handler/module to the existing bot. Existing
|
|
commands and conversations retain their current behavior.
|
|
|
|
## Authorization and shared state
|
|
|
|
The handler accepts private-chat users through the existing `@username`
|
|
allowlist for compatibility. A configured numeric Telegram user ID may pin an
|
|
entry; when pinned, both the ID and current allowlist rule must match. This
|
|
mitigates username reassignment while permitting a staged migration.
|
|
|
|
Jobs, placements, events, queues, and routes are shared administrative state and
|
|
store no initiating-user identity. UI session state records only what is needed
|
|
to resume the conversation/view and expires after 24 hours by default.
|
|
|
|
## Entry point and navigation
|
|
|
|
The existing “Archive/Unarchive Resources” entry opens one message:
|
|
|
|
```text
|
|
What do you want to do?
|
|
|
|
[ Archive ] [ Unarchive ]
|
|
[ Evict Cache ] [ Job Status ]
|
|
```
|
|
|
|
All subsequent pages edit this message. `Cancel` closes the active selection
|
|
flow. `Back` returns one level while retaining validated filters/selections.
|
|
Callback payloads contain opaque session/action IDs, not resource names or
|
|
paths, and are validated against persisted session revision and expiry.
|
|
|
|
## Archive and unarchive flow
|
|
|
|
### 1. Select source resource
|
|
|
|
Control queries relevant online nodes on demand. It groups identical resource
|
|
and selection replicas into one display choice while showing distinct
|
|
selections separately. The list is stable-sorted and paged:
|
|
|
|
```text
|
|
Which cached resource do you want to archive? (page 1/3)
|
|
filters: `documentary`, `2025`
|
|
|
|
1. `10.0 GB` Resource A — cache-1
|
|
2. `840 MB` Resource B — cache-2
|
|
|
|
[ 1 ] [ 2 ]
|
|
[ Prev ] [ Next ]
|
|
[ Remove filters ] [ Cancel ]
|
|
```
|
|
|
|
Size is selected-complete logical content, not total torrent size. New messages
|
|
add literal, case-insensitive filters and narrow the current results; Remove
|
|
filters resets the chain. If no item remains, the message explains whether no
|
|
source is online, no selected-complete data exists, or filters eliminated all
|
|
results.
|
|
|
|
### 2. Select source replica and target
|
|
|
|
If multiple identical-selection replicas exist, control may choose a healthy
|
|
source automatically using deterministic availability/route/free-space rules;
|
|
otherwise it lists the source replicas. One eligible target is selected
|
|
automatically; multiple targets are paged. Offline targets are not offered.
|
|
|
|
A resource already on a target is still eligible when the requested selection
|
|
has an unverified delta. The UI says that it will extend an existing placement.
|
|
|
|
### 3. Confirm or choose one entry
|
|
|
|
Before showing confirmation, control obtains fresh full trees from source and
|
|
target and calculates the transfer delta.
|
|
|
|
```text
|
|
Archive Resource A from cache-1 to archive-2?
|
|
Requested: 7 files, 10.0 GB
|
|
Already verified there: 2 files, 3.1 GB
|
|
Will transfer: 5 files, 6.9 GB
|
|
|
|
[ Confirm ]
|
|
[ Choose one entry… ] [ Cancel ]
|
|
```
|
|
|
|
Choose one entry opens a paged/filterable tree. Only source-selected-complete
|
|
files/directories are enabled. Selecting a directory expands it to descendant
|
|
file indices, returns to a freshly recomputed confirmation, and clearly states
|
|
the chosen subtree. The protocol supports multiple entries from v1, but the
|
|
initial UI exposes one.
|
|
|
|
Confirmation uses a persisted, single-use nonce bound to session revision,
|
|
operation, resource, source, target, selection, fingerprints, and placement
|
|
generation. Double taps or stale callbacks cannot create a second job.
|
|
|
|
## Evict Cache flow
|
|
|
|
The first page lists current cache placements. Selecting one triggers fresh
|
|
queries to the cache and relevant online archive nodes. Each row/confirmation
|
|
shows coverage:
|
|
|
|
- enabled when the union of verified archives covers every selected cache file;
|
|
- disabled with missing file count/size and unavailable archive explanation
|
|
otherwise.
|
|
|
|
There is no override button. Confirmation creates a durable three-step
|
|
eviction job; it never clears an archive placement or a transfer history row.
|
|
|
|
## Job Status
|
|
|
|
Status pages show live and retained jobs with operation, resource, endpoints,
|
|
state, current-step and overall percentages, bytes/s where meaningful, and
|
|
failure reason.
|
|
Routine edits are coalesced to one per five seconds by default. Step changes,
|
|
stall transitions, failures, commit, cleanup-required, and terminal states edit
|
|
immediately subject to Telegram rate-limit backoff.
|
|
|
|
State symbols:
|
|
|
|
| Symbol | Meaning |
|
|
| --- | --- |
|
|
| 🟡 | queued/not started |
|
|
| 🔵 | active, waiting, or stalled |
|
|
| 🟠 | committed but cleanup required |
|
|
| 🟢 | succeeded |
|
|
| 🔴 | failed or cancelled |
|
|
|
|
Transfer jobs display five numbered steps: Source Stage/HardLink, Syncthing,
|
|
Target Merge/Copy, QB Verification, and Staging Cleanup. Route setup and
|
|
preflight are named, unnumbered pre-steps. Eviction displays Verify Archive
|
|
Coverage, QB Remove Entry, and Safe File Unlink.
|
|
|
|
A stalled job keeps its last overall percentage:
|
|
|
|
```text
|
|
🔵 Archive: Resource A — cache-1 → archive-2
|
|
[2/5 Syncthing: 63.42%, overall 32.68%, stalled, last progress 38m ago]
|
|
Waiting indefinitely; retry occurs when progress/service connectivity returns.
|
|
```
|
|
|
|
Failure messages include stable phase and clear reason, while hiding secrets
|
|
and host-only paths.
|
|
|
|
## Clear and remove behavior
|
|
|
|
`Clear Finished` hides only green successful jobs and leaves a 30-day default
|
|
tombstone. Orange Cleanup Required is not clearable as finished.
|
|
|
|
`Remove One` first replaces buttons with current-page job numbers and Cancel.
|
|
A successful green row hides immediately. A queued job confirmation deletes
|
|
only its queue record/reservation. An active, failed-with-residue, or cancelling
|
|
job requires a second confirmation and begins/continues compensation; its row
|
|
remains until safe cleanup is known. A committed job can only retry staging
|
|
cleanup. No history action deletes a cache placement; that is exclusively Evict
|
|
Cache.
|
|
|
|
## Restart and rate-limit behavior
|
|
|
|
Sessions, pages, filters, chosen entries, confirmation bindings, and live status
|
|
views are persisted. On bot restart, active status messages resume updates when
|
|
the stored chat/message remains editable; otherwise users can reopen Job Status
|
|
without losing job state. “message is not modified” is treated as success.
|
|
Telegram retry-after values pause/coalesce edits without affecting orchestration.
|
|
|
|
## Interactive test entry
|
|
|
|
An opt-in `Archive Control (Test)` entry reuses this same handler with an
|
|
independent callback namespace and SQLite database. Its scripted backend
|
|
provides comprehensive, empty, and slow-route scenarios without contacting
|
|
control/client daemons, qBittorrent, or Syncthing. The production entry,
|
|
callback namespace, database, jobs, placements, and other bot features are
|
|
unchanged.
|
|
|
|
The test entry exposes administrator-only `/actest` controls to reset a
|
|
scenario, move a synthetic job through displayed states, fail the next selected
|
|
backend call, complete a slow route, inspect recent trace events, or export the
|
|
complete JSONL trace. The trace contains callback and filter inputs, session
|
|
state transitions, exact message/keyboard renders, backend results/errors, and
|
|
job transitions, so a UI report can be reproduced without live storage nodes.
|