Commit Graph
4 Commits
Author SHA1 Message Date
sneak 5f7b786dda Rebuild backup on the library API with a durable failure ledger (closes #51)
check / check (push) Successful in 30s
backup() is a Library method: it refreshes, fetches each pending original
(and optional thumbnails) through the content cache and pools, then rebuilds
the sidecar, symlink, and per-collection JSON views from the model. The
downloadDirectory layout and exit-code contract are unchanged.

An original already on disk is complete and never re-fetched, so runs are
idempotent and resume after interruption. Per-file download and symlink
failures go to a durable failures.json and no longer abort the run
(subsuming #8); a file failing more than one way in a run counts one attempt
and is listed once.

Each run reconciles the ledger against the files it attempted, so a failure
for a since-deleted or out-of-scope file clears instead of failing every
future backup.

Model: opus-4-8
2026-09-22 18:04:50 +00:00
sneak 0cbe338b58 Add failing tests for the download retry policy
Tests only; the retry module they import does not exist yet, so the
branch is red at this commit.

New test/retry/retry.test.ts documents the classifier and the backoff:
which errors are worth another attempt, which are not, and how the delay
before each retry is derived. It asserts on the arguments handed to an
injected sleep function rather than on elapsed time, so the suite never
waits and the numbers are exact.

test/api/client.test.ts gains the request-count contract for each of the
six call sites, the deadline behaviour, the ApiError typing that the
presigned PUT and the null-body paths need in order to be classified at
all, and the replay rule for the two non-idempotent methods.

test/download/download.test.ts gains the case that motivates the whole
design: a socket reset after the response headers arrived, which happens
below ApiClient and can only be caught by retrying the request, the
stream consumption and the decryption together. It also pins that a
retried download stages exactly one temp file, and that the two retry
layers do not compose into a multiplied request budget. The existing
truncation tests now assert on the error type rather than its wording,
since that type is what the classifier reads.

test/thumbnails/thumbnails.test.ts separates a genuine 404 from an
exhausted retry, so a failing server can no longer make
fix-missing-thumbnails re-upload thumbnails that already exist.
2026-08-09 05:11:07 +00:00
sneak 8ee1be1cc2 CLI: quak login + quak backup with dedup symlink layout
bin/quak.ts: commander-based CLI with login (interactive + QUAK_EMAIL/
QUAK_PASSWORD env vars), whoami, logout, backup commands. Session
stored at env-paths('quak').data/session.json (~/Library/Application
Support/quak/ on macOS, XDG on Linux).

src/backup.ts: runBackup downloads all files into originals/<id>.<ext>,
symlinks into collections/<name>/<title>, writes per-collection JSON
metadata at collections/<name>.json. Deduplicates across collections
(each file downloaded once). Skips existing originals on incremental
runs. Never crashes on single-file failure.

4 backup tests + live-tested against real Ente account.
2026-05-13 18:47:06 -07:00
sneak 30a13eeeaf CLI red: backup tests, commander + env-paths deps, stub
4 tests for runBackup: full download into collection-named dirs,
incremental skip of existing files, resilient continuation after
single-file HTTP 500, and metadata.json output.

Adds commander 14.0.3 and env-paths 4.0.0 as runtime deps.
2026-05-13 18:36:07 -07:00