chaind/chaind/filter.py

124 lines
4.1 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-05-02 11:59:13 +02:00
from shep.error import StateLockedKey
2022-03-14 22:17:31 +01:00
2022-04-29 08:26:43 +02:00
# local imports
from .error import (
QueueLockError,
2022-05-02 11:59:13 +02:00
BackendError,
)
2022-05-02 11:59:13 +02:00
from chaind.lock import StoreLock
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
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
2022-05-05 14:09:07 +02:00
self.last_block_height = 0
self.adapter = None
self.store_lock = None
def __get_adapter(self, block, force_reload=False):
if self.store_lock == None:
self.store_lock = StoreLock()
reload = False
if block.number != self.last_block_height:
reload = True
elif self.adapter == None:
reload = True
elif force_reload:
reload = True
self.last_block_height = block.number
if reload:
while True:
logg.info('reloading adapter')
try:
self.adapter = ChaindFsAdapter(
self.chain_spec,
self.adapter_path,
self.tx_adapter,
None,
)
break
except BackendError as e:
logg.error('adapter instantiation failed: {}, one more try'.format(e))
self.store_lock.again()
continue
return self.adapter
2022-03-14 22:17:31 +01:00
def filter(self, conn, block, tx, session=None):
cache_tx = None
2022-05-05 14:09:07 +02:00
queue_adapter = self.__get_adapter(block)
self.store_lock.reset()
2022-05-02 11:59:13 +02:00
while True:
try:
cache_tx = queue_adapter.get(tx.hash)
2022-05-02 11:59:13 +02:00
break
except NotLocalTxError:
logg.debug('skipping not local transaction {}'.format(tx.hash))
return False
2022-05-02 11:59:13 +02:00
except BackendError as e:
2022-05-04 20:22:29 +02:00
logg.error('adapter get failed: {}, one more try'.format(e))
2022-05-05 14:09:07 +02:00
self.store_lock.again()
queue_adapter = self.__get_adapter(block, force_reload=True)
continue
if cache_tx == None:
raise NotLocalTxError(tx.hash)
2022-05-05 14:09:07 +02:00
self.store_lock.reset()
2022-05-02 11:59:13 +02:00
queue_lock = StoreLock(error=QueueLockError)
2022-04-29 08:26:43 +02:00
while True:
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-05-01 09:55:51 +02:00
break
2022-04-29 08:26:43 +02:00
except QueueLockError as e:
logg.debug('queue item {} is blocked, will retry: {}'.format(tx.hash, e))
2022-05-02 11:59:13 +02:00
queue_lock.again()
except FileNotFoundError as e:
logg.debug('queue item {} not found, possible race condition, will retry: {}'.format(tx.hash, e))
2022-05-05 14:09:07 +02:00
self.store_lock.again()
queue_adapter = self.__get_adapter(block, force_reload=True)
continue
except NotLocalTxError as e:
logg.debug('queue item {} not found, possible race condition, will retry: {}'.format(tx.hash, e))
2022-05-05 14:09:07 +02:00
self.store_lock.again()
queue_adapter = self.__get_adapter(block, force_reload=True)
2022-05-02 11:59:13 +02:00
continue
except StateLockedKey as e:
logg.debug('queue item {} not found, possible race condition, will retry: {}'.format(tx.hash, e))
2022-05-05 14:09:07 +02:00
self.store_lock.again()
queue_adapter = self.__get_adapter(block, force_reload=True)
continue
2022-05-09 21:25:31 +02:00
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