I'm seeing it take 20+s in prod right now for limit=1000, which is way too slow.
$ time curl -v 'https://atproto.brid.gy/xrpc/com.atproto.sync.listRepos?limit=1000'
...
0.022u 0.028s 0:22.79 0.1% 0+0k 0+0io 2pf+0w
Not sure why though. All it does is call storage.load_repos and then construct the output, and all load_repos does is query AtpRepos, load their head AtpBlocks, and then return.
|
def list_repos(input, limit=500, cursor=None): |
|
"""Handler for ``com.atproto.sync.listRepos`` XRPC method.""" |
|
STATUSES = {'tombstoned': 'deactivated'} |
|
|
|
repos = [] |
|
for repo in server.storage.load_repos(limit=limit, after=cursor, minimal=True): |
|
repo_obj = { |
|
'did': repo.did, |
|
'head': repo.head.cid.encode('base32'), |
|
'rev': util.int_to_tid(repo.head.seq, clock_id=0), |
|
'active': repo.status is None, |
|
} |
|
if repo.status: |
|
repo_obj['status'] = STATUSES.get(repo.status) or repo.status |
|
repos.append(repo_obj) |
|
|
|
ret = {'repos': repos} |
|
if len(repos) == limit: |
|
ret['cursor'] = repos[-1]['did'] |
|
|
|
return ret |
|
def load_repos(self, after=None, limit=500, minimal=False): |
|
query = AtpRepo.query() |
|
if after: |
|
query = query.filter(AtpRepo.key > AtpRepo(id=after).key) |
|
|
|
# duplicates parts of Repo.load but batches reading blocks from storage |
|
atp_repos = query.fetch(limit=limit) |
|
|
|
cids = [CID.decode(r.head) for r in atp_repos] |
|
blocks = self.read_many(cids) # dict mapping CID to block |
|
heads = [blocks[cid] for cid in cids] |
|
|
|
if minimal: |
|
return [Repo(storage=self, head=head, status=atp_repo.status) |
|
for atp_repo, head in zip(atp_repos, heads)] |
|
|
|
# MST.load doesn't read from storage |
|
msts = [MST.load(storage=self, cid=block.decoded['data']) for block in heads] |
|
return [Repo(storage=self, mst=mst, head=head, status=atp_repo.status, |
|
handle=atp_repo.handles[0] if atp_repo.handles else None, |
|
signing_key=atp_repo.signing_key, |
|
rotation_key=atp_repo.rotation_key) |
|
for atp_repo, head, mst in zip(atp_repos, heads, msts)] |
Note the minimal=True. I originally though the private key parsing and loading was the culprit, so I now skip that, but that didn't really help. 😕
I'm seeing it take 20+s in prod right now for limit=1000, which is way too slow.
Not sure why though. All it does is call
storage.load_reposand then construct the output, and all load_repos does is queryAtpRepos, load their headAtpBlocks, and then return.arroba/arroba/xrpc_sync.py
Lines 74 to 94 in 75cefb6
arroba/arroba/datastore_storage.py
Lines 718 to 740 in 75cefb6
Note the
minimal=True. I originally though the private key parsing and loading was the culprit, so I now skip that, but that didn't really help. 😕