feat(transcode): the local cache disables itself, and drains at boot
Completes the pattern the thumbnail migration established, for `.transcoded/`. `initialize` no longer creates the tree. Creating it at boot is exactly what kept `.thumbnails/` alive across restarts — the import removed it, the next boot put it back, and the absence the read path gates on was unreachable by construction. The write path already calls `create_dir_all` on the parent before writing, so eager creation achieved nothing except defeating the drain. It now probes instead: one `stat`, cached for the process lifetime, and the local-cache reads short-circuit on a relaxed atomic load when the tree is gone. Fails open, so a service built without `initialize` behaves as before. One difference from the thumbnail tiers, and it is not a stalled migration: callers with no content hash — external mounts — cannot use the content-keyed tier at all, so they still read and write here. On an install without such mounts the directory drains once and stays gone; on one with them it persists, correctly. `transcode_import?repair=true` joins the startup defaults on the same terms as the thumbnail imports, and with the weakest safety argument needed of the three: a transcode is a pure function of its source, so anything deleted in error is recomputed on the next request. The `default_startup_jobs` test failed on the change rather than being updated silently, which is what it is for. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+17
-3
@@ -2401,8 +2401,15 @@ fn parse_startup_job(raw: &str) -> Result<StartupJob, String> {
|
||||
/// Set `OXICLOUD_STARTUP_JOBS=` (empty) to disable startup jobs
|
||||
/// entirely; any explicit value replaces this list rather than adding
|
||||
/// to it.
|
||||
const DEFAULT_STARTUP_JOBS: &str =
|
||||
"thumb_derived_import?repair=true,thumb_attached_import?repair=true";
|
||||
/// `transcode_import` joins them for the same reason and on the same
|
||||
/// terms. Its artifacts are the most disposable of the three — a
|
||||
/// transcode is a pure function of its source, so anything deleted in
|
||||
/// error is recomputed on the next request — and its `.skip` markers
|
||||
/// collapse to one row per distinct content, which is the saving that
|
||||
/// only happens once the import runs.
|
||||
const DEFAULT_STARTUP_JOBS: &str = "thumb_derived_import?repair=true,\
|
||||
thumb_attached_import?repair=true,\
|
||||
transcode_import?repair=true";
|
||||
|
||||
/// Parse the whole `OXICLOUD_STARTUP_JOBS` value. Empty → no startup
|
||||
/// jobs (an explicit opt-out); unset → [`DEFAULT_STARTUP_JOBS`].
|
||||
@@ -3999,7 +4006,14 @@ mod tests {
|
||||
fn default_startup_jobs_drain_both_thumbnail_tiers() {
|
||||
let jobs = AppConfig::default().startup_jobs;
|
||||
let names: Vec<&str> = jobs.iter().map(|j| j.name.as_str()).collect();
|
||||
assert_eq!(names, ["thumb_derived_import", "thumb_attached_import"]);
|
||||
assert_eq!(
|
||||
names,
|
||||
[
|
||||
"thumb_derived_import",
|
||||
"thumb_attached_import",
|
||||
"transcode_import"
|
||||
]
|
||||
);
|
||||
assert!(jobs.iter().all(|j| j.args.repair));
|
||||
assert!(jobs.iter().all(|j| !j.args.deep && !j.args.force));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user