Merge remote-tracking branch 'origin/sub_laptop_2' into main_laptop_1
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from dataclasses import dataclass, field
|
||||
@@ -37,6 +38,8 @@ STORAGE_SCOPE = (
|
||||
PIPE_SCOPE = ("B04_PreProcess/drainage",)
|
||||
#: 노선 초기화(추천 [적용])가 다시 뜨는 초기값 사본.
|
||||
INITIAL_SCOPE = ("initial_snapshot",)
|
||||
#: 떠 두지 않는 자리 — 위성 조각(저장이 안 씀 · 다시 받음 · 590-2).
|
||||
SKIP_SCOPE = ("_derived/plan_tile",)
|
||||
#: 노선 아래 표(노선 행이 지워지면 함께 지워짐 · CASCADE).
|
||||
ROUTE_CHILDREN = ("route_points", "route_statistics", "longitudinal_sections", "cross_sections")
|
||||
|
||||
@@ -68,8 +71,13 @@ def _files(root: Path, scope: tuple[str, ...]) -> dict[str, Path]:
|
||||
if target.is_file():
|
||||
out[relative] = target
|
||||
elif target.is_dir():
|
||||
for path in target.rglob("*"):
|
||||
if path.is_file():
|
||||
for folder, dirs, names in os.walk(target):
|
||||
here = Path(folder)
|
||||
dirs[:] = [
|
||||
d for d in dirs if (here / d).relative_to(root).as_posix() not in SKIP_SCOPE
|
||||
]
|
||||
for name in names:
|
||||
path = here / name
|
||||
out[path.relative_to(root).as_posix()] = path
|
||||
return out
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
"""위성 조각 저장본 한도(590-2 · 요구 452 · 453) — 프로젝트당 한 벌 `_derived/plan_tile`.
|
||||
|
||||
다시 받을 수 있는 저장본 · 프로젝트당 `limit` 바이트를 넘으면 오래 안 본 것부터 한도 80 % 까지
|
||||
지움. 크기는 서버 메모리에 두고 프로젝트를 처음 볼 때 한 번만 폴더를 셈(그때 넘쳤으면 바로 지움).
|
||||
본 때 = 파일 수정시각 · 볼 때 하루 넘게 묵은 것만 새로 찍음(시놀로지 동기 일감을 줄임).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
TOUCH_AFTER_S = 86400
|
||||
KEEP_RATIO = 0.8
|
||||
|
||||
_SIZES: dict[Path, int] = {}
|
||||
_LOCK = threading.Lock()
|
||||
|
||||
|
||||
def _tiles(folder: Path) -> list[tuple[float, int, Path]]:
|
||||
"""(본 때, 크기, 경로) — 받는 중인 `.part` 는 뺌."""
|
||||
out = []
|
||||
for path in folder.rglob("*.jpeg"):
|
||||
try:
|
||||
stat = path.stat()
|
||||
except FileNotFoundError:
|
||||
continue
|
||||
out.append((stat.st_mtime, stat.st_size, path))
|
||||
return out
|
||||
|
||||
|
||||
def seen(path: Path) -> None:
|
||||
"""조각을 봄 — 하루 넘게 묵었으면 본 때를 지금으로."""
|
||||
try:
|
||||
if time.time() - path.stat().st_mtime > TOUCH_AFTER_S:
|
||||
os.utime(path)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def prune(folder: Path, limit: int) -> int:
|
||||
"""한도를 넘으면 오래 안 본 것부터 한도 80 % 까지 지움 → 지운 수."""
|
||||
tiles = sorted(_tiles(folder))
|
||||
total = sum(size for _, size, _ in tiles)
|
||||
removed = 0
|
||||
if total > limit:
|
||||
for _, size, path in tiles:
|
||||
if total <= limit * KEEP_RATIO:
|
||||
break
|
||||
path.unlink(missing_ok=True)
|
||||
total -= size
|
||||
removed += 1
|
||||
_SIZES[folder] = total
|
||||
return removed
|
||||
|
||||
|
||||
def note(folder: Path, added: int, limit: int) -> int:
|
||||
"""`folder`(프로젝트 조각 뿌리)에 `added` 바이트가 늘었음(0 = 열기만) → 지운 수."""
|
||||
with _LOCK:
|
||||
if folder not in _SIZES:
|
||||
return prune(folder, limit)
|
||||
_SIZES[folder] += added
|
||||
return prune(folder, limit) if _SIZES[folder] > limit else 0
|
||||
Reference in New Issue
Block a user