docs: publish archive control design set
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user