chaind/chaind/filter.py

103 lines
3.3 KiB
Python
Raw Normal View History

2022-04-10 18:21:52 +02:00
# standard imports
import logging
2022-04-29 08:26:43 +02:00
import time
2022-04-10 18:21:52 +02:00
2022-03-14 22:17:31 +01:00
# external imports
from chainlib.status import Status as TxStatus
2022-04-10 18:21:52 +02:00
from chainsyncer.filter import SyncFilter
from chainqueue.error import NotLocalTxError
from chaind.adapters.fs import ChaindFsAdapter
2022-03-14 22:17:31 +01:00
2022-04-29 08:26:43 +02:00
# local imports
from .error import (
QueueLockError,
BackendIntegrityError,
)
2022-04-29 08:26:43 +02:00
2022-04-10 18:21:52 +02:00
logg = logging.getLogger(__name__)
2022-03-14 22:17:31 +01:00
2022-04-10 18:21:52 +02:00
class StateFilter(SyncFilter):
2022-03-14 22:17:31 +01:00
2022-04-29 08:26:43 +02:00
delay_limit = 3.0
race_delay = 0.1
2022-04-29 08:26:43 +02:00
def __init__(self, chain_spec, adapter_path, tx_adapter, throttler=None):
self.chain_spec = chain_spec
self.adapter_path = adapter_path
self.tx_adapter = tx_adapter
2022-03-14 22:17:31 +01:00
self.throttler = throttler
def filter(self, conn, block, tx, session=None):
cache_tx = None
for i in range(3):
queue_adapter = None
try:
queue_adapter = ChaindFsAdapter(
self.chain_spec,
self.adapter_path,
self.tx_adapter,
None,
)
except BackendIntegrityError as e:
logg.error('adapter instantiation failed: {}, one more try'.format(e))
time.sleep(self.race_delay)
continue
try:
cache_tx = queue_adapter.get(tx.hash)
except NotLocalTxError:
logg.debug('skipping not local transaction {}'.format(tx.hash))
return False
except BackendIntegrityError as e:
logg.error('adapter instantiation failed: {}, one more try'.format(e))
time.sleep(self.race_delay)
continue
break
if cache_tx == None:
raise NotLocalTxError(tx.hash)
2022-04-29 08:26:43 +02:00
delay = 0.01
race_attempts = 0
err = None
2022-04-29 08:26:43 +02:00
while True:
if delay > self.delay_limit:
raise QueueLockError('The queue lock for tx {} seems to be stuck. Human meddling needed.'.format(tx.hash))
elif race_attempts >= 3:
break
2022-04-29 08:26:43 +02:00
try:
if tx.status == TxStatus.SUCCESS:
queue_adapter.succeed(block, tx)
2022-04-29 08:26:43 +02:00
else:
queue_adapter.fail(block, tx)
2022-04-29 08:26:43 +02:00
break
err = None
2022-04-29 08:26:43 +02:00
except QueueLockError as e:
logg.debug('queue item {} is blocked, will retry: {}'.format(tx.hash, e))
time.sleep(delay)
delay *= 2
err = None
except FileNotFoundError as e:
err = e
logg.debug('queue item {} not found, possible race condition, will retry: {}'.format(tx.hash, e))
race_attempts += 1
continue
except NotLocalTxError as e:
err = e
logg.debug('queue item {} not found, possible race condition, will retry: {}'.format(tx.hash, e))
race_attempts += 1
continue
if err != None:
raise BackendIntegrityError('cannot find queue item {} in backend: {}'.format(tx.hash, err))
logg.info('filter registered {} for {} in {}'.format(tx.status.name, tx.hash, block))
2022-04-29 08:26:43 +02:00
2022-03-14 22:17:31 +01:00
if self.throttler != None:
self.throttler.dec(tx.hash)
2022-04-10 18:21:52 +02:00
return False