fix(sync): ignore terminal legacy generation capacity

This commit is contained in:
fy59 2026-09-22 13:15:49 +02:00
parent 0f7d793960
commit a88e85c235
2 changed files with 64 additions and 1 deletions

View file

@ -95,6 +95,54 @@ class GenerationArchiveTest(unittest.TestCase):
with sqlite3.connect(self.database) as database:
self.assertEqual(0, database.execute("SELECT COUNT(*) FROM sync_generation_archives").fetchone()[0])
def test_historical_acknowledged_rows_without_ack_ledger_do_not_exhaust_admission(self):
with sqlite3.connect(self.database) as database:
producer = generation.peer_identity(database, "desktop")
database.commit()
parent = None
for index in range(generation.MAX_RETAINED_PER_PEER):
suffix = f"{index + 1:012d}"
generation_id = f"gen_10000000-0000-4000-8000-{suffix}"
run_id = f"sy_20000000-0000-4000-8000-{suffix}"
database.execute(
"INSERT INTO sync_generations VALUES(?,?,?,?,?,?,?,?,?,?,?,?)",
(
generation_id,
run_id,
producer,
PEER,
"desktop",
f"2026-09-16T00:00:{index:02d}+00:00",
parent,
"0" * 64,
"acknowledged",
"{}",
str(self.owned / "staging" / generation_id),
f"2026-09-16T00:01:{index:02d}+00:00",
),
)
parent = generation_id
database.commit()
stage, manifest, _ = generation.capture_desktop(self.database, self.owned, PEER)
self.assertTrue(stage.is_dir())
self.assertEqual(parent, manifest["parent_generation_id"])
with sqlite3.connect(self.database) as database:
self.assertEqual(
0,
database.execute(
"SELECT COUNT(*) FROM sync_acknowledgements "
"WHERE generation_id LIKE 'gen_10000000-%'"
).fetchone()[0],
)
self.assertEqual(
0,
database.execute(
"SELECT COUNT(*) FROM sync_generation_archives "
"WHERE generation_id LIKE 'gen_10000000-%'"
).fetchone()[0],
)
def test_missing_then_late_ack_is_protected_until_correlated(self):
values = self.create_acknowledged()
stage, manifest, digest = generation.capture_desktop(self.database, self.owned, PEER)

View file

@ -364,7 +364,22 @@ def capture_desktop(database: Path, owned_root: Path, consumer: str,
archive_acknowledged(database, owned_root, consumer)
with closing(connect_database(database)) as admission:
require_schema(admission)
retained = admission.execute("SELECT COUNT(*) FROM sync_generations g WHERE consumer_peer_id=? AND status IN('captured','published','waiting_acknowledgement','acknowledged') AND NOT EXISTS(SELECT 1 FROM sync_generation_archives a WHERE a.generation_id=g.generation_id)", (consumer,)).fetchone()[0]
# WHY: early private generation builds can contain terminal
# acknowledged rows from before durable ACK-ledger insertion was
# enforced. They cannot be archived without fabricating missing ACK
# evidence, but they are terminal and must not permanently consume the
# active admission window. Current production acknowledgements always
# have a durable sync_acknowledgements row and remain counted until
# archive_acknowledged() safely moves them out of the active window.
retained = admission.execute(
"SELECT COUNT(*) FROM sync_generations g WHERE consumer_peer_id=? "
"AND (g.status IN('captured','published','waiting_acknowledgement') OR "
"(g.status='acknowledged' AND EXISTS(SELECT 1 FROM sync_acknowledgements k "
"WHERE k.generation_id=g.generation_id))) "
"AND NOT EXISTS(SELECT 1 FROM sync_generation_archives a "
"WHERE a.generation_id=g.generation_id)",
(consumer,),
).fetchone()[0]
if retained >= MAX_RETAINED_PER_PEER:
raise GenerationError("generation retention capacity exhausted")
stage = owned_root / "staging" / generation