Skip to content

Commit 982952d

Browse files
committed
feat: garbage collect unreferenced objects
1 parent fe1de8e commit 982952d

1 file changed

Lines changed: 56 additions & 0 deletions

File tree

  • src/endstone_endkeep/repository
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from __future__ import annotations
2+
3+
import os
4+
from dataclasses import dataclass
5+
from pathlib import Path
6+
7+
from .manifest import RepositoryManifest
8+
from .objects import ObjectStore
9+
10+
11+
@dataclass(frozen=True)
12+
class GcResult:
13+
removed_objects: int
14+
removed_bytes: int
15+
retained_objects: int
16+
17+
18+
def referenced_object_hashes(manifest: RepositoryManifest) -> set[str]:
19+
referenced: set[str] = set()
20+
for node in manifest.chain:
21+
referenced.add(node.object.logical_sha256)
22+
referenced.add(node.sidecar.logical_sha256)
23+
return referenced
24+
25+
26+
def collect_orphan_objects(objects: ObjectStore, manifest: RepositoryManifest) -> GcResult:
27+
referenced = referenced_object_hashes(manifest)
28+
removed = 0
29+
removed_bytes = 0
30+
retained = 0
31+
modified_dirs: set[Path] = set()
32+
33+
if not objects.objects_root.exists():
34+
return GcResult(0, 0, 0)
35+
36+
for path in objects.objects_root.glob("*/*.zst"):
37+
logical_hash = path.stem
38+
if logical_hash in referenced:
39+
retained += 1
40+
continue
41+
size = path.stat().st_size
42+
path.unlink()
43+
removed += 1
44+
removed_bytes += size
45+
modified_dirs.add(path.parent)
46+
47+
for directory in sorted(modified_dirs):
48+
ObjectStore._fsync_directory(directory)
49+
try:
50+
directory.rmdir()
51+
except OSError:
52+
pass
53+
if modified_dirs:
54+
ObjectStore._fsync_directory(objects.objects_root)
55+
56+
return GcResult(removed, removed_bytes, retained)

0 commit comments

Comments
 (0)