chainsyncer/chainsyncer/filter.py

97 lines
3.1 KiB
Python
Raw Normal View History

2021-02-17 12:44:35 +01:00
# standard imports
import logging
# local imports
from .error import BackendError
2021-02-17 12:44:35 +01:00
logg = logging.getLogger(__name__)
2021-04-04 15:03:58 +02:00
2021-02-17 12:44:35 +01:00
class SyncFilter:
2021-08-27 12:43:12 +02:00
"""Manages the collection of filters on behalf of a specific backend.
A filter is a pluggable piece of code to execute for every transaction retrieved by the syncer. Filters are executed in the sequence they were added to the instance.
:param backend: Syncer backend to apply filter state changes to
:type backend: chainsyncer.backend.base.Backend implementation
"""
2021-02-17 12:44:35 +01:00
def __init__(self, backend):
2021-02-17 12:44:35 +01:00
self.filters = []
self.backend = backend
2021-02-17 12:44:35 +01:00
def add(self, fltr):
2021-08-27 12:43:12 +02:00
"""Add a filter instance.
:param fltr: Filter instance.
:type fltr: Object instance implementing signature as in chainsyncer.filter.NoopFilter.filter
:raises ValueError: Object instance is incorrect implementation
"""
2021-02-17 12:44:35 +01:00
if getattr(fltr, 'filter') == None:
raise ValueError('filter object must implement have method filter')
2021-04-04 15:03:58 +02:00
logg.debug('added filter "{}"'.format(str(fltr)))
2021-02-17 12:44:35 +01:00
self.filters.append(fltr)
2021-08-26 10:09:47 +02:00
2021-08-27 12:43:12 +02:00
def __apply_one(self, fltr, idx, conn, block, tx, session):
2021-09-26 19:32:08 +02:00
self.backend.begin_filter(idx)
2021-08-26 10:09:47 +02:00
fltr.filter(conn, block, tx, session)
self.backend.complete_filter(idx)
2021-02-17 12:44:35 +01:00
def apply(self, conn, block, tx):
2021-08-27 12:43:12 +02:00
"""Apply all registered filters on the given transaction.
:param conn: RPC Connection, will be passed to the filter method
:type conn: chainlib.connection.RPCConnection
:param block: Block object
:type block: chainlib.block.Block
:param tx: Transaction object
:type tx: chainlib.tx.Tx
:raises BackendError: Backend connection failed
"""
session = None
try:
session = self.backend.connect()
except TimeoutError as e:
self.backend.disconnect()
raise BackendError('database connection fail: {}'.format(e))
2021-04-04 15:03:58 +02:00
i = 0
2021-04-15 14:11:06 +02:00
(pair, flags) = self.backend.get()
2021-02-17 12:44:35 +01:00
for f in self.filters:
2021-04-15 17:16:31 +02:00
if not self.backend.check_filter(i, flags):
logg.debug('applying filter {} {}'.format(str(f), flags))
2021-08-27 12:43:12 +02:00
self.__apply_one(f, i, conn, block, tx, session)
else:
logg.debug('skipping previously applied filter {} {}'.format(str(f), flags))
2021-04-04 15:03:58 +02:00
i += 1
self.backend.disconnect()
2021-02-17 12:44:35 +01:00
2021-08-26 10:09:47 +02:00
class NoopFilter:
2021-08-27 12:43:12 +02:00
"""A noop implemenation of a sync filter.
Logs the filter inputs at debug log level.
"""
2021-02-17 12:44:35 +01:00
def filter(self, conn, block, tx, db_session=None):
2021-08-27 12:43:12 +02:00
"""Filter method implementation:
:param conn: RPC Connection, will be passed to the filter method
:type conn: chainlib.connection.RPCConnection
:param block: Block object
:type block: chainlib.block.Block
:param tx: Transaction object
:type tx: chainlib.tx.Tx
2021-08-27 13:41:03 +02:00
:param db_session: Backend session object
2021-08-27 12:43:12 +02:00
:type db_session: varies
"""
logg.debug('noop filter :received\n{} {} {}'.format(block, tx, id(db_session)))
2021-02-17 12:44:35 +01:00
def __str__(self):
return 'noopfilter'