···310310 use cid::Cid as IpldCid;
311311 use jacquard_api::com_atproto::sync::subscribe_repos::RepoOp;
312312 use jacquard_common::CowStr;
313313- use jacquard_common::types::string::{Did, Nsid};
313313+ use jacquard_common::types::string::Did;
314314 use jacquard_common::types::tid::Tid;
315315 use jacquard_repo::car::reader::ParsedCar;
316316 use jacquard_repo::commit::Commit;
+149
src/storage/repo.rs
···658658 assert_eq!(next1, None);
659659 }
660660661661+ // --- scan_repos ---
662662+663663+ fn mk_state(db: &DbRef, d: &Did<'static>, state: RepoState, status: AccountStatus) {
664664+ put_info(
665665+ db,
666666+ d,
667667+ &RepoInfo {
668668+ state,
669669+ status,
670670+ error: None,
671671+ },
672672+ )
673673+ .unwrap();
674674+ }
675675+676676+ #[test]
677677+ fn scan_repos_empty_returns_empty() {
678678+ let db = open_temporary().unwrap();
679679+ let (entries, next) = scan_repos(&db, None, 10).unwrap();
680680+ assert!(entries.is_empty());
681681+ assert_eq!(next, None);
682682+ }
683683+684684+ #[test]
685685+ fn scan_repos_returns_all_regardless_of_status() {
686686+ let db = open_temporary().unwrap();
687687+ let alice = did("did:web:alice.test");
688688+ let bob = did("did:web:bob.test");
689689+ let carol = did("did:web:carol.test");
690690+ mk_state(&db, &alice, RepoState::Active, AccountStatus::Active);
691691+ mk_state(&db, &bob, RepoState::Takendown, AccountStatus::Takendown);
692692+ mk_state(&db, &carol, RepoState::Suspended, AccountStatus::Suspended);
693693+694694+ let (entries, next) = scan_repos(&db, None, 10).unwrap();
695695+ assert_eq!(entries.len(), 3);
696696+ assert_eq!(entries[0].did, alice);
697697+ assert_eq!(entries[0].info.status, AccountStatus::Active);
698698+ assert_eq!(entries[1].did, bob);
699699+ assert_eq!(entries[1].info.status, AccountStatus::Takendown);
700700+ assert_eq!(entries[2].did, carol);
701701+ assert_eq!(entries[2].info.status, AccountStatus::Suspended);
702702+ assert_eq!(next, None);
703703+ }
704704+705705+ #[test]
706706+ fn scan_repos_prev_is_none_when_absent() {
707707+ let db = open_temporary().unwrap();
708708+ let d = did("did:web:example.test");
709709+ mk_state(&db, &d, RepoState::Active, AccountStatus::Active);
710710+711711+ let (entries, _) = scan_repos(&db, None, 10).unwrap();
712712+ assert_eq!(entries.len(), 1);
713713+ assert!(entries[0].prev.is_none());
714714+ }
715715+716716+ #[test]
717717+ fn scan_repos_prev_is_some_when_present() {
718718+ let db = open_temporary().unwrap();
719719+ let d = did("did:web:example.test");
720720+ mk_state(&db, &d, RepoState::Active, AccountStatus::Active);
721721+ put_prev(
722722+ &db,
723723+ &d,
724724+ &RepoPrev {
725725+ rev: tid("3lczouzaqmo2e"),
726726+ prev_data: vec![1, 2, 3],
727727+ },
728728+ )
729729+ .unwrap();
730730+731731+ let (entries, _) = scan_repos(&db, None, 10).unwrap();
732732+ assert_eq!(entries.len(), 1);
733733+ let prev = entries[0].prev.as_ref().unwrap();
734734+ assert_eq!(prev.rev.as_str(), "3lczouzaqmo2e");
735735+ assert_eq!(prev.prev_data, vec![1, 2, 3]);
736736+ }
737737+738738+ #[test]
739739+ fn scan_repos_paginates() {
740740+ let db = open_temporary().unwrap();
741741+ let alice = did("did:web:alice.test");
742742+ let bob = did("did:web:bob.test");
743743+ let carol = did("did:web:carol.test");
744744+ for d in [&alice, &bob, &carol] {
745745+ mk(&db, d, AccountStatus::Active);
746746+ }
747747+748748+ let (page0, next0) = scan_repos(&db, None, 2).unwrap();
749749+ assert_eq!(page0.len(), 2);
750750+ assert_eq!(page0[0].did, alice);
751751+ assert_eq!(page0[1].did, bob);
752752+ assert_eq!(next0, Some(carol.clone()));
753753+754754+ let (page1, next1) = scan_repos(&db, next0.as_ref(), 2).unwrap();
755755+ assert_eq!(page1.len(), 1);
756756+ assert_eq!(page1[0].did, carol);
757757+ assert_eq!(next1, None);
758758+ }
759759+760760+ #[test]
761761+ fn scan_repos_cursor_is_inclusive() {
762762+ let db = open_temporary().unwrap();
763763+ let alice = did("did:web:alice.test");
764764+ let bob = did("did:web:bob.test");
765765+ mk(&db, &alice, AccountStatus::Active);
766766+ mk(&db, &bob, AccountStatus::Active);
767767+768768+ // Starting at alice returns alice onwards, not skipping it.
769769+ let (entries, _) = scan_repos(&db, Some(&alice), 10).unwrap();
770770+ assert_eq!(entries.len(), 2);
771771+ assert_eq!(entries[0].did, alice);
772772+ assert_eq!(entries[1].did, bob);
773773+ }
774774+775775+ #[test]
776776+ fn scan_repos_limit_exceeds_total() {
777777+ let db = open_temporary().unwrap();
778778+ let d = did("did:web:example.test");
779779+ mk(&db, &d, AccountStatus::Active);
780780+781781+ let (entries, next) = scan_repos(&db, None, 100).unwrap();
782782+ assert_eq!(entries.len(), 1);
783783+ assert_eq!(next, None);
784784+ }
785785+786786+ #[test]
787787+ fn scan_repos_info_fields_preserved() {
788788+ let db = open_temporary().unwrap();
789789+ let d = did("did:web:broken.test");
790790+ mk_state(&db, &d, RepoState::Error, AccountStatus::Deactivated);
791791+ // Write error message via put_info
792792+ put_info(
793793+ &db,
794794+ &d,
795795+ &RepoInfo {
796796+ state: RepoState::Error,
797797+ status: AccountStatus::Deactivated,
798798+ error: Some("something broke".to_owned()),
799799+ },
800800+ )
801801+ .unwrap();
802802+803803+ let (entries, _) = scan_repos(&db, None, 10).unwrap();
804804+ assert_eq!(entries.len(), 1);
805805+ assert_eq!(entries[0].info.state, RepoState::Error);
806806+ assert_eq!(entries[0].info.status, AccountStatus::Deactivated);
807807+ assert_eq!(entries[0].info.error.as_deref(), Some("something broke"));
808808+ }
809809+661810 #[test]
662811 fn put_and_get_prev() {
663812 let db = open_temporary().unwrap();