Fullfører oppgave 17.6: Periodisk CAS tmp-opprydding
Legger til cleanup_tmp() i CasStore som sletter orphaned .tmp-filer eldre enn 1 time. Disse oppstår når en skriveprosess krasjer midt i en atomisk CAS-skriveoperasjon (skriv til tmp, rename til endelig path). Ny bakgrunnsloop start_tmp_cleanup_loop() kjører hver time og fjerner foreldede temp-filer. Følger samme mønster som pruning- og disk-monitor-loopene. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a3f8ca2dfa
commit
ce56e31de2
3 changed files with 81 additions and 2 deletions
|
|
@ -167,6 +167,83 @@ impl CasStore {
|
||||||
fn tmp_path(&self, hash: &str) -> PathBuf {
|
fn tmp_path(&self, hash: &str) -> PathBuf {
|
||||||
self.root.join("tmp").join(format!("{hash}.tmp"))
|
self.root.join("tmp").join(format!("{hash}.tmp"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Slett temp-filer eldre enn `max_age` fra CAS tmp-katalogen.
|
||||||
|
/// Returnerer (antall slettet, bytes frigitt).
|
||||||
|
pub async fn cleanup_tmp(&self, max_age: std::time::Duration) -> std::io::Result<(usize, u64)> {
|
||||||
|
let tmp_dir = self.root.join("tmp");
|
||||||
|
if !tmp_dir.exists() {
|
||||||
|
return Ok((0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut deleted = 0usize;
|
||||||
|
let mut freed = 0u64;
|
||||||
|
let now = std::time::SystemTime::now();
|
||||||
|
|
||||||
|
let mut entries = tokio::fs::read_dir(&tmp_dir).await?;
|
||||||
|
while let Some(entry) = entries.next_entry().await? {
|
||||||
|
let meta = match entry.metadata().await {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(_) => continue,
|
||||||
|
};
|
||||||
|
if !meta.is_file() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let modified = match meta.modified() {
|
||||||
|
Ok(t) => t,
|
||||||
|
Err(_) => continue,
|
||||||
|
};
|
||||||
|
let age = now.duration_since(modified).unwrap_or_default();
|
||||||
|
if age > max_age {
|
||||||
|
let size = meta.len();
|
||||||
|
if let Ok(()) = tokio::fs::remove_file(entry.path()).await {
|
||||||
|
deleted += 1;
|
||||||
|
freed += size;
|
||||||
|
tracing::debug!(
|
||||||
|
file = %entry.file_name().to_string_lossy(),
|
||||||
|
age_secs = age.as_secs(),
|
||||||
|
size,
|
||||||
|
"Slettet gammel temp-fil"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((deleted, freed))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start periodisk opprydding av CAS tmp-filer.
|
||||||
|
/// Kjører hver time, sletter filer eldre enn 1 time.
|
||||||
|
pub fn start_tmp_cleanup_loop(cas: CasStore) {
|
||||||
|
tokio::spawn(async move {
|
||||||
|
// Vent 45 sekunder etter oppstart
|
||||||
|
tokio::time::sleep(std::time::Duration::from_secs(45)).await;
|
||||||
|
tracing::info!("CAS tmp-opprydding startet (intervall: 1t, TTL: 1t)");
|
||||||
|
|
||||||
|
let max_age = std::time::Duration::from_secs(3600); // 1 time
|
||||||
|
let interval = std::time::Duration::from_secs(3600); // 1 time
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match cas.cleanup_tmp(max_age).await {
|
||||||
|
Ok((deleted, freed)) => {
|
||||||
|
if deleted > 0 {
|
||||||
|
tracing::info!(
|
||||||
|
deleted,
|
||||||
|
freed_kb = freed / 1024,
|
||||||
|
"CAS tmp-opprydding: {} filer slettet, {} KB frigitt",
|
||||||
|
deleted,
|
||||||
|
freed / 1024,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::warn!(error = %e, "CAS tmp-opprydding feilet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tokio::time::sleep(interval).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@ async fn main() {
|
||||||
// Start nattlig bandwidth-parsing (oppgave 15.7)
|
// Start nattlig bandwidth-parsing (oppgave 15.7)
|
||||||
bandwidth::start_bandwidth_parser(db.clone());
|
bandwidth::start_bandwidth_parser(db.clone());
|
||||||
|
|
||||||
|
// Start periodisk CAS tmp-opprydding (oppgave 17.6)
|
||||||
|
cas::start_tmp_cleanup_loop(cas.clone());
|
||||||
|
|
||||||
let index_cache = publishing::new_index_cache();
|
let index_cache = publishing::new_index_cache();
|
||||||
let dynamic_page_cache = publishing::new_dynamic_page_cache();
|
let dynamic_page_cache = publishing::new_dynamic_page_cache();
|
||||||
let state = AppState { db, jwks, stdb, cas, index_cache, dynamic_page_cache, maintenance, priority_rules };
|
let state = AppState { db, jwks, stdb, cas, index_cache, dynamic_page_cache, maintenance, priority_rules };
|
||||||
|
|
|
||||||
3
tasks.md
3
tasks.md
|
|
@ -194,8 +194,7 @@ Ref: Kodegjennomgang av `b4c4bb8` (Lydstudio: lydredigering via FFmpeg).
|
||||||
- [x] 17.3 Fade/silence-logikk: fiks negativ fade-out start (clamp til 0), og adaptiv silence-margin (margin skal ikke overstige halve regionens varighet). Gi feilmelding ved ugyldige fade-varigheter.
|
- [x] 17.3 Fade/silence-logikk: fiks negativ fade-out start (clamp til 0), og adaptiv silence-margin (margin skal ikke overstige halve regionens varighet). Gi feilmelding ved ugyldige fade-varigheter.
|
||||||
- [x] 17.4 Frontend input-begrensninger: legg til `min`/`max` på alle tallfelter i OperationPanel (silenceThreshold, fadeMs, normTarget, compRatio). Hindre ugyldig input.
|
- [x] 17.4 Frontend input-begrensninger: legg til `min`/`max` på alle tallfelter i OperationPanel (silenceThreshold, fadeMs, normTarget, compRatio). Hindre ugyldig input.
|
||||||
- [x] 17.5 Job-polling opprydding: rydd opp interval/timeout ved navigering bort fra studio-siden. Vis feilmelding etter N mislykkede polling-forsøk. Wrap metadata JSON.parse i try/catch.
|
- [x] 17.5 Job-polling opprydding: rydd opp interval/timeout ved navigering bort fra studio-siden. Vis feilmelding etter N mislykkede polling-forsøk. Wrap metadata JSON.parse i try/catch.
|
||||||
- [~] 17.6 Temp-fil opprydding: legg til periodisk jobb i maskinrommet som sletter gamle temp-filer i CAS tmp-katalog. Bruk `/tmp` eller sett TTL.
|
- [x] 17.6 Temp-fil opprydding: legg til periodisk jobb i maskinrommet som sletter gamle temp-filer i CAS tmp-katalog. Bruk `/tmp` eller sett TTL.
|
||||||
> Påbegynt: 2026-03-18T05:54
|
|
||||||
- [ ] 17.7 FFmpeg feilmeldinger til bruker: propager stderr fra FFmpeg-feil til frontend via strukturert feilrespons. Vis i RenderDialog.
|
- [ ] 17.7 FFmpeg feilmeldinger til bruker: propager stderr fra FFmpeg-feil til frontend via strukturert feilrespons. Vis i RenderDialog.
|
||||||
|
|
||||||
## Fase 18: AI-verktøy (arbeidsflate)
|
## Fase 18: AI-verktøy (arbeidsflate)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue