A from-scratch atproto PDS implementation in Python (mirrors https://github.com/DavidBuchanan314/millipds)

treat empty-string cursors the same as nonexistent

Changed files
+10 -6
src
tests
+3 -1
src/millipds/atproto_repo.py
··· 220 220 if limit < 1 or limit > 100: 221 221 raise web.HTTPBadRequest(text="limit out of range") 222 222 reverse = request.query.get("reverse") == "true" 223 - cursor = request.query.get("cursor", "" if reverse else "\xff") 223 + cursor = request.query.get("cursor", "") 224 + if not reverse and not cursor: 225 + cursor = "\xff" # compares greater than all valid rkeys 224 226 did_or_handle = request.query["repo"] 225 227 collection = request.query["collection"] 226 228 records = []
+3 -3
src/millipds/atproto_sync.py
··· 190 190 limit = int(request.query.get("limit", 500)) 191 191 if limit < 1 or limit > 1000: 192 192 raise web.HTTPBadRequest(text="limit out of range") 193 - cursor = int(request.query.get("cursor", 0)) 193 + cursor = int(request.query.get("cursor") or 0) 194 194 195 195 cids = [] 196 196 for id_, cid in get_db(request).con.execute( ··· 246 246 await ws.prepare(request) # TODO: should this be outside of try? 247 247 248 248 last_sent_seq = None 249 - if "cursor" in request.query: 249 + if cursor_str := request.query.get("cursor"): 250 250 # TODO: try to limit number of concurrent backfillers? (it's more expensive than livetailing) 251 - cursor = int(request.query["cursor"]) 251 + cursor = int(cursor_str) 252 252 db = get_db(request) 253 253 while True: 254 254 # we read one at a time to force gaps between reads - could be a perf win to read in small batches
+1
src/millipds/database.py
··· 150 150 ) STRICT 151 151 """ 152 152 ) 153 + # TODO: index on timestamp for efficient purging of old events. 153 154 154 155 # repo storage stuff 155 156 self.con.execute(
+3 -2
tests/integration_test.py
··· 494 494 ) as r: 495 495 assert r.status != 200 496 496 497 + 497 498 async def test_updateHandle(s, pds_host, auth_headers): 498 499 async with s.post( 499 500 pds_host + "/xrpc/com.atproto.identity.updateHandle", 500 501 headers=auth_headers, 501 - json={ "handle": "juliet.test" }, 502 + json={"handle": "juliet.test"}, 502 503 ) as r: 503 504 assert r.status == 200 504 505 505 506 async with s.get( 506 507 pds_host + "/xrpc/com.atproto.repo.describeRepo", 507 - params={ "repo": TEST_DID }, 508 + params={"repo": TEST_DID}, 508 509 ) as r: 509 510 assert r.status == 200 510 511 r = await r.json()