Archiv: je Version quellen.tar und arbeit.tar statt einzelner Dateien – SMB schafft 25 Dateien/s, am Stück 90 MB/s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
7ba08b68e0
commit
54d1d6a8da
3 files changed
+26
-26
No files matched your search
+20
-21
@@ -1,9 +1,12 @@
|
||||
"""Quellen und Arbeitsdateien fertiger Versionen ins Archiv verschieben (config.ARCHIV, auf dem Server eine Storage Box).
|
||||
Nichts liest danach noch daraus: neue Versionen recherchieren neu, fertige Läufe setzen nie fort. QUELLEN.md bleibt im Speicher,
|
||||
die Buchansicht zeigt sie. Erst kopieren, dann löschen – ein Abbruch lässt den Speicher vollständig, der nächste Start holt nach."""
|
||||
"""Quellen und Arbeitsdateien fertiger Versionen als tar ins Archiv (config.ARCHIV, auf dem Server die Storage Box).
|
||||
Je Version quellen.tar (ohne QUELLEN.md, die bleibt im Speicher und steht in der Buchansicht) und arbeit.tar. Ein tar statt
|
||||
einzelner Dateien, weil SMB je Datei mehrere Round-Trips braucht (25 Dateien/s), am Stück aber 90 MB/s schafft.
|
||||
Nichts liest danach noch daraus: neue Versionen recherchieren neu, fertige Läufe setzen nie fort.
|
||||
Erst packen, dann löschen – ein Abbruch lässt den Speicher vollständig, der nächste Start holt nach."""
|
||||
import asyncio
|
||||
import logging
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
from . import config, state
|
||||
@@ -25,32 +28,28 @@ def _eintraege(d: Path) -> list[Path]:
|
||||
|
||||
|
||||
def auslagern(key: str) -> None:
|
||||
"""Verschiebt quellen/ (außer QUELLEN.md) und arbeit/ nach ARCHIV/<key>/. Blockiert – im Thread aufrufen."""
|
||||
"""Packt quellen/ (außer QUELLEN.md) und arbeit/ nach ARCHIV/<key>/<ordner>.tar und löscht sie. Blockiert – im Thread aufrufen."""
|
||||
v = state.verzeichnis(key)
|
||||
ziel = config.ARCHIV / key
|
||||
ziel.mkdir(parents=True, exist_ok=True)
|
||||
for u in ORDNER:
|
||||
for p in _eintraege(v / u):
|
||||
_kopieren(p, config.ARCHIV / key / u / p.name)
|
||||
eintraege = _eintraege(v / u)
|
||||
if not eintraege:
|
||||
continue
|
||||
tmp = ziel / f"{u}.tar.tmp"
|
||||
r = subprocess.run(["tar", "-cf", str(tmp), "-C", str(v / u), *[p.name for p in eintraege]], capture_output=True, text=True)
|
||||
if r.returncode:
|
||||
raise OSError(f"tar {u}/ von {key}: {r.stderr.strip()[-300:]}")
|
||||
tmp.replace(ziel / f"{u}.tar")
|
||||
for p in eintraege:
|
||||
if p.is_dir() and not p.is_symlink():
|
||||
shutil.rmtree(p)
|
||||
else:
|
||||
p.unlink()
|
||||
|
||||
|
||||
def _kopieren(quelle: Path, ziel: Path) -> None:
|
||||
"""Ohne Rechte, Zeiten und Symlinks: CIFS kennt beides nicht. Links in Klonen entfallen."""
|
||||
if quelle.is_symlink():
|
||||
return
|
||||
if quelle.is_dir():
|
||||
ziel.mkdir(parents=True, exist_ok=True)
|
||||
for k in quelle.iterdir():
|
||||
_kopieren(k, ziel / k.name)
|
||||
elif quelle.is_file():
|
||||
ziel.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copyfile(quelle, ziel)
|
||||
|
||||
|
||||
async def _auslagern(key: str) -> None:
|
||||
state.ereignis(key, "archiv", "start", f"Quellen und Arbeitsdateien nach {config.ARCHIV / key}")
|
||||
state.ereignis(key, "archiv", "start", f"Quellen und Arbeitsdateien als tar nach {config.ARCHIV / key}")
|
||||
try:
|
||||
await asyncio.to_thread(auslagern, key)
|
||||
state.ereignis(key, "archiv", "ende", "ausgelagert")
|
||||
@@ -69,7 +68,7 @@ def anstossen(key: str) -> None:
|
||||
|
||||
|
||||
async def nachholen() -> None:
|
||||
"""Beim Start: alle fertigen Versionen mit Restbestand, nacheinander (Bestand und abgebrochene Kopien)."""
|
||||
"""Beim Start: alle fertigen Versionen mit Restbestand, nacheinander (Bestand und abgebrochene Läufe)."""
|
||||
if not config.ARCHIV:
|
||||
return
|
||||
for t in state.themen():
|
||||
|
||||
Reference in new issue
Block a user