|
11 | 11 | import dag_cbor
|
12 | 12 | import dag_json
|
13 | 13 | from google.cloud import ndb
|
14 |
| -from google.cloud.ndb.context import get_context |
| 14 | +from google.cloud.ndb import context |
15 | 15 | from google.cloud.ndb.exceptions import ContextError
|
16 | 16 | from lexrpc import ValidationError
|
17 | 17 | from multiformats import CID, multicodec, multihash
|
@@ -410,9 +410,9 @@ def __init__(self, *, ndb_client=None):
|
410 | 410 | def ndb_context(fn):
|
411 | 411 | @wraps(fn)
|
412 | 412 | def decorated(self, *args, **kwargs):
|
413 |
| - context = get_context(raise_context_error=False) |
| 413 | + ctx = context.get_context(raise_context_error=False) |
414 | 414 |
|
415 |
| - with context.use() if context else self.ndb_client.context(): |
| 415 | + with ctx.use() if ctx else self.ndb_client.context(): |
416 | 416 | ret = fn(self, *args, **kwargs)
|
417 | 417 |
|
418 | 418 | return ret
|
@@ -514,24 +514,41 @@ def read_many(self, cids):
|
514 | 514 | def read_blocks_by_seq(self, start=0, repo=None):
|
515 | 515 | assert start >= 0
|
516 | 516 |
|
517 |
| - context = get_context(raise_context_error=False) |
518 |
| - |
519 |
| - with context.use() if context else self.ndb_client.context() as cm: |
520 |
| - # lexrpc event subscription handlers like subscribeRepos call this |
521 |
| - # on a different thread, so if we're there, we need to create a new |
522 |
| - # ndb context |
523 |
| - try: |
524 |
| - query = AtpBlock.query(AtpBlock.seq >= start).order(AtpBlock.seq) |
525 |
| - if repo: |
526 |
| - query = query.filter(AtpBlock.repo == AtpRepo(id=repo).key) |
527 |
| - # unproven hypothesis: need strong consistency to make sure we |
528 |
| - # get all blocks for a given seq, including commit |
529 |
| - # https://console.cloud.google.com/errors/detail/CO2g4eLG_tOkZg;service=atproto-hub;time=P1D;refresh=true;locations=global?project=bridgy-federated |
530 |
| - for atp_block in query.iter(read_consistency=ndb.STRONG): |
531 |
| - yield atp_block.to_block() |
532 |
| - except ContextError as e: |
533 |
| - logging.warning(f'lost ndb context! client may have disconnected? "{e}"') |
534 |
| - return |
| 517 | + cur_seq = start |
| 518 | + cur_seq_cids = [] |
| 519 | + |
| 520 | + while True: |
| 521 | + ctx = context.get_context(raise_context_error=False) |
| 522 | + with ctx.use() if ctx else self.ndb_client.context(): |
| 523 | + # lexrpc event subscription handlers like subscribeRepos call this |
| 524 | + # on a different thread, so if we're there, we need to create a new |
| 525 | + # ndb context |
| 526 | + try: |
| 527 | + query = AtpBlock.query(AtpBlock.seq >= cur_seq).order(AtpBlock.seq) |
| 528 | + if repo: |
| 529 | + query = query.filter(AtpBlock.repo == AtpRepo(id=repo).key) |
| 530 | + # unproven hypothesis: need strong consistency to make sure we |
| 531 | + # get all blocks for a given seq, including commit |
| 532 | + # https://console.cloud.google.com/errors/detail/CO2g4eLG_tOkZg;service=atproto-hub;time=P1D;refresh=true;locations=global?project=bridgy-federated |
| 533 | + for atp_block in query.iter(read_consistency=ndb.STRONG): |
| 534 | + if atp_block.seq != cur_seq: |
| 535 | + cur_seq = atp_block.seq |
| 536 | + cur_seq_cids = [] |
| 537 | + if atp_block.key.id() not in cur_seq_cids: |
| 538 | + cur_seq_cids.append(atp_block.key.id()) |
| 539 | + yield atp_block.to_block() |
| 540 | + |
| 541 | + # finished cleanly |
| 542 | + break |
| 543 | + |
| 544 | + except ContextError as e: |
| 545 | + logging.warning(f'lost ndb context! re-querying at {cur_seq}. {e}') |
| 546 | + # continue loop, restart query |
| 547 | + |
| 548 | + # Context.use() resets this to the previous context when it exits, |
| 549 | + # but that context is bad now, so make sure we get a new one at the |
| 550 | + # top of the loop |
| 551 | + context._state.context = None |
535 | 552 |
|
536 | 553 | @ndb_context
|
537 | 554 | def has(self, cid):
|
|
0 commit comments