Skip to content

Commit ea6abc4

Browse files
authored
fix(key-backup): count only the sessions actually written (#87)
Review finding on #77, after merge. The import counted every session it decrypted: ```python client.olm.store.save_inbound_group_session(session) imported += 1 ``` `save_inbound_group_session` ends in an `on_conflict_ignore()` insert, so a session already in the store is reported as imported while nothing is written. The run that produced #77 printed `Imported: 18275` against 18272 new rows — three were already there and counted anyway. That is the same defect #77 was written to fix, one size smaller: the original code counted sessions it *discarded*, and the inflated number is what kept it invisible. Sessions now go through `client.olm.inbound_group_store.add()` first, which is what nio does when it imports a key itself: ```python if self.inbound_group_store.add(session): self.save_inbound_group_session(session) ``` `add()` returns False for a session already held, and `Olm.load()` populates that in-memory set from the database at startup — which the script triggers via `client.load_store()`. So a re-import reports what it actually did instead of claiming the whole backup again. Sessions already present are reported on their own line, and a run where everything was already in the store no longer exits non-zero. ## Not covered by a test The path needs a live backup and a real megolm session; there is no fixture for either in this repo. The claim rests on nio's own source (`on_conflict_ignore` in `store/database.py`, the `add()`-then-save pattern in `crypto/olm_machine.py`) and on the counter mismatch observed against a live backup. Worth saying plainly rather than implying the change is covered.
2 parents b50bc29 + b1d339f commit ea6abc4

1 file changed

Lines changed: 19 additions & 4 deletions

File tree

skills/matrix-communication/scripts/matrix-key-backup.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ async def main():
460460
await client.sync(timeout=5000)
461461

462462
imported = 0
463+
already_present = 0
463464
failed = 0
464465

465466
# room_id is part of the megolm session identity, so it has to come
@@ -485,10 +486,22 @@ async def main():
485486
room_id,
486487
decrypted.get("forwarding_curve25519_key_chain") or [],
487488
)
488-
client.olm.store.save_inbound_group_session(session)
489489

490-
imported += 1
491-
if imported % 500 == 0:
490+
# Go through the in-memory store first, the way nio does
491+
# when it imports a key itself. add() returns False for a
492+
# session already held, and the database write is an
493+
# on_conflict_ignore insert - so counting every decrypted
494+
# session as imported would report writes that never
495+
# happened. Sessions loaded from the store at startup are
496+
# in that in-memory set, which is what makes this honest
497+
# on a re-import.
498+
if client.olm.inbound_group_store.add(session):
499+
client.olm.store.save_inbound_group_session(session)
500+
imported += 1
501+
else:
502+
already_present += 1
503+
504+
if imported and imported % 500 == 0:
492505
print(f" Imported {imported} sessions...")
493506

494507
except Exception as e: # noqa: BLE001 # intentional fail-soft: error surfaced to caller, not re-raised
@@ -498,8 +511,10 @@ async def main():
498511

499512
print("\n=== Import Complete ===")
500513
print(f"Imported: {imported}")
514+
if already_present:
515+
print(f"Already in the store: {already_present}")
501516
print(f"Failed: {failed}")
502-
if failed and not imported:
517+
if failed and not imported and not already_present:
503518
return 1
504519

505520
finally:

0 commit comments

Comments
 (0)