quak backup no longer refreshes its library on a timer (closes #183) #190
@@ -788,7 +788,8 @@ subsequent runs, existing originals are skipped. If a download fails, the error
|
|||||||
is logged and the backup continues with the next file. The exit code is non-zero
|
is logged and the backup continues with the next file. The exit code is non-zero
|
||||||
if any files failed. `quak backup` opens its library with the thumbnail and
|
if any files failed. `quak backup` opens its library with the thumbnail and
|
||||||
originals precache off, so the only file content it fetches is the originals the
|
originals precache off, so the only file content it fetches is the originals the
|
||||||
backup stores.
|
backup stores. It also opens it with no background timer, so it asks the server
|
||||||
|
for changes only as it starts, not again while it downloads.
|
||||||
|
|
||||||
With `--verify`, or `lib.backup({ verify: true })`, a run also hashes each
|
With `--verify`, or `lib.backup({ verify: true })`, a run also hashes each
|
||||||
original already at its save path the way a download is checked (see "On-disk
|
original already at its save path the way a download is checked (see "On-disk
|
||||||
@@ -869,7 +870,7 @@ background, so an unreachable server does not block opening.
|
|||||||
| `client` | required | the account client (a `Client`, or any `LibraryClient`) |
|
| `client` | required | the account client (a `Client`, or any `LibraryClient`) |
|
||||||
| `cacheDirectory` | `quak/<userID>` under the per-user cache directory | where `metadata.json` and the content cache live |
|
| `cacheDirectory` | `quak/<userID>` under the per-user cache directory | where `metadata.json` and the content cache live |
|
||||||
| `downloadDirectory` | `photos` in the working directory | root of the save paths; an original stored there counts as cached |
|
| `downloadDirectory` | `photos` in the working directory | root of the save paths; an original stored there counts as cached |
|
||||||
| `refreshIntervalSeconds` | `3` | background refresh cadence |
|
| `refreshIntervalSeconds` | `3` | background refresh cadence; `Infinity` for no background timer |
|
||||||
| `precacheThumbnails` | `true` | prefetch every thumbnail, newest first |
|
| `precacheThumbnails` | `true` | prefetch every thumbnail, newest first |
|
||||||
| `precacheOriginals` | `true` | prefetch the favorites album and the latest-window originals |
|
| `precacheOriginals` | `true` | prefetch the favorites album and the latest-window originals |
|
||||||
| `precacheOriginalsDays` | `7` | length in days of that latest window |
|
| `precacheOriginalsDays` | `7` | length in days of that latest window |
|
||||||
|
|||||||
@@ -25,6 +25,13 @@ declares one.
|
|||||||
|
|
||||||
# Completed Steps
|
# Completed Steps
|
||||||
|
|
||||||
|
- 2026-10-14: `quak backup` no longer asks the server for changes every 3
|
||||||
|
seconds while it runs (issue 183). It opens its library with
|
||||||
|
`refreshIntervalSeconds: Infinity`, which the library now takes as no
|
||||||
|
background timer, so the backup refreshes only as it starts and no timed
|
||||||
|
refresh starts another ML data pass during the run. A test holds a backup's
|
||||||
|
download open while two hours pass and counts its `/collections/v2` requests.
|
||||||
|
|
||||||
- 2026-10-14: `test/cli/backup-end-to-end.test.ts` runs `quak backup` as cron
|
- 2026-10-14: `test/cli/backup-end-to-end.test.ts` runs `quak backup` as cron
|
||||||
does (issue 186): `backupCommand` and `run`, the real `loadSession` reading a
|
does (issue 186): `backupCommand` and `run`, the real `loadSession` reading a
|
||||||
session saved after logging in, and every request answered by a fake of the
|
session saved after logging in, and every request answered by a fake of the
|
||||||
|
|||||||
@@ -427,10 +427,13 @@ export const backupCommand = async (
|
|||||||
try {
|
try {
|
||||||
// The precache is off: the backup fetches what it needs, and must not
|
// The precache is off: the backup fetches what it needs, and must not
|
||||||
// also fill the cache with every thumbnail and the recent originals.
|
// also fill the cache with every thumbnail and the recent originals.
|
||||||
|
// No refresh starts on a timer: the backup lists its files once, from
|
||||||
|
// the refresh it waits for, and can run for hours.
|
||||||
const lib = await Library.open({
|
const lib = await Library.open({
|
||||||
client,
|
client,
|
||||||
downloadDirectory: dir,
|
downloadDirectory: dir,
|
||||||
cacheDirectory: ctx.cacheDir,
|
cacheDirectory: ctx.cacheDir,
|
||||||
|
refreshIntervalSeconds: Infinity,
|
||||||
precacheThumbnails: false,
|
precacheThumbnails: false,
|
||||||
precacheOriginals: false,
|
precacheOriginals: false,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -179,6 +179,9 @@ export interface LibraryOptions {
|
|||||||
// directory at open. The content cache treats an original already stored
|
// directory at open. The content cache treats an original already stored
|
||||||
// at its save path as present.
|
// at its save path as present.
|
||||||
downloadDirectory?: string;
|
downloadDirectory?: string;
|
||||||
|
// How long after one refresh ends the background timer starts the next.
|
||||||
|
// `Infinity` starts none: the library then refreshes only as it opens and
|
||||||
|
// when `fresh()` or `backup()` asks.
|
||||||
refreshIntervalSeconds?: number;
|
refreshIntervalSeconds?: number;
|
||||||
onProgress?: RefreshProgressCallback;
|
onProgress?: RefreshProgressCallback;
|
||||||
// The bounded request pools (issue #45), shared by the ML-data fetch (the
|
// The bounded request pools (issue #45), shared by the ML-data fetch (the
|
||||||
@@ -627,7 +630,8 @@ export class Library {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private scheduleNext(): void {
|
private scheduleNext(): void {
|
||||||
if (this.closed) return;
|
// `setTimeout` would turn an infinite delay into 1 ms.
|
||||||
|
if (this.closed || this.intervalMs === Infinity) return;
|
||||||
this.timer = setTimeout(() => {
|
this.timer = setTimeout(() => {
|
||||||
void this.runRefresh().then(() => this.scheduleNext());
|
void this.runRefresh().then(() => this.scheduleNext());
|
||||||
}, this.intervalMs);
|
}, this.intervalMs);
|
||||||
|
|||||||
Reference in New Issue
Block a user