WIP docstrings
This commit is contained in:
parent
88098e356b
commit
1dd403b4a2
@ -38,15 +38,50 @@ logg = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class SQLBackend:
|
class SQLBackend:
|
||||||
|
"""SQL flavor of the chainqueue backend implementation.
|
||||||
|
|
||||||
def __init__(self, conn_spec, error_parser=None, *args, **kwargs):
|
:param conn_spec: Backend-dependent connection specification string. See chainqueue.db.models.base.SessionBase.connect
|
||||||
SessionBase.connect(conn_spec, pool_size=kwargs.get('poolsize', 0), debug=kwargs.get('debug', False))
|
:type conn_spec: str
|
||||||
|
:param error_parser: Error parser to use for RPC calls within the backend component
|
||||||
|
:type error_parser: Object implementing chainlib.error.DefaultErrorParser
|
||||||
|
:param pool_size: Connection pool size for pool-capable sql engines. See chainqueue.db.models.base.SessionBase.connect
|
||||||
|
:type pool_size: int
|
||||||
|
:param debug: Activate SQL engine level debug. See chainqueue.db.models.base.SessionBase.connect
|
||||||
|
:type debug: bool
|
||||||
|
:todo: define a backend abstract interface class
|
||||||
|
"""
|
||||||
|
|
||||||
|
#def __init__(self, conn_spec, error_parser=None, *args, **kwargs):
|
||||||
|
def __init__(self, conn_spec, error_parser=None, pool_size=0, debug=False, *args, **kwargs):
|
||||||
|
#SessionBase.connect(conn_spec, pool_size=kwargs.get('poolsize', 0), debug=kwargs.get('debug', False))
|
||||||
|
SessionBase.connect(conn_spec, pool_size=pool_size, debug=debug)
|
||||||
if error_parser == None:
|
if error_parser == None:
|
||||||
error_parser = DefaultErrorParser()
|
error_parser = DefaultErrorParser()
|
||||||
self.error_parser = error_parser
|
self.error_parser = error_parser
|
||||||
|
|
||||||
|
|
||||||
def create(self, chain_spec, nonce, holder_address, tx_hash, signed_tx, obsolete_predecessors=True, session=None):
|
def create(self, chain_spec, nonce, holder_address, tx_hash, signed_tx, obsolete_predecessors=True, session=None):
|
||||||
|
"""Create a new transaction record in backend.
|
||||||
|
|
||||||
|
The nonce field is provided as a convenience to avoid needless resources spent on decoding the transaction data to retrieve it. However, this means that no check will be performed to verify that nonce matches the nonce encoded in the transaction, and thus it is the caller's responsibility to ensure that it is correct.
|
||||||
|
|
||||||
|
:param chain_spec: Chain spec to add record for
|
||||||
|
:type chain_spec: chainlib.chain.ChainSpec
|
||||||
|
:param nonce: Transaction nonce
|
||||||
|
:type nonce: int
|
||||||
|
:param holder_address: Address of transaction sender
|
||||||
|
:type holder_address: str
|
||||||
|
:param tx_hash: Transaction hash
|
||||||
|
:type tx_hash: str
|
||||||
|
:param signed_tx: Signed transaction data
|
||||||
|
:type signed_tx: str
|
||||||
|
:param obsolete_predecessors: If set, will mark older transactions with same nonce from holder_address as obsolete
|
||||||
|
:type obsolete_predecessors: bool
|
||||||
|
:param session: Sqlalchemy database session
|
||||||
|
:type session: sqlalchemy.orm.Session
|
||||||
|
:rtype: int
|
||||||
|
:returns: 0 if successfully added
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
queue_create(chain_spec, nonce, holder_address, tx_hash, signed_tx, obsolete_predecessors=True, session=session)
|
queue_create(chain_spec, nonce, holder_address, tx_hash, signed_tx, obsolete_predecessors=True, session=session)
|
||||||
except IntegrityError as e:
|
except IntegrityError as e:
|
||||||
@ -57,16 +92,61 @@ class SQLBackend:
|
|||||||
|
|
||||||
|
|
||||||
def cache(self, tx, session=None):
|
def cache(self, tx, session=None):
|
||||||
|
"""Create a new cache record for existing outgoing transaction in backend.
|
||||||
|
|
||||||
|
:param tx: Transaction dict representation
|
||||||
|
:type tx: dict
|
||||||
|
:param session: Sqlalchemy database session
|
||||||
|
:type session: sqlalchemy.orm.Session
|
||||||
|
:rtype: int
|
||||||
|
:returns: 0 if successful
|
||||||
|
"""
|
||||||
(tx, txc_id) = cache_tx_dict(tx, session=session)
|
(tx, txc_id) = cache_tx_dict(tx, session=session)
|
||||||
logg.debug('cached {} db insert id {}'.format(tx, txc_id))
|
logg.debug('cached {} db insert id {}'.format(tx, txc_id))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def get_tx(self, chain_spec, tx_hash, session=None):
|
def get_otx(self, chain_spec, tx_hash, session=None):
|
||||||
|
"""Retrieve a single otx summary dictionary by transaction hash.
|
||||||
|
|
||||||
|
Alias of chainqueue.sql.query.get_tx
|
||||||
|
|
||||||
|
:param chain_spec: Chain spec context to look up transaction with
|
||||||
|
:type chain_spec: chainlib.chain.ChainSpec
|
||||||
|
:param tx_hash: Transaction hash
|
||||||
|
:type tx_hash: str
|
||||||
|
:param session: Sqlalchemy database session
|
||||||
|
:type session: sqlalchemy.orm.Session
|
||||||
|
:rtype: dict
|
||||||
|
:returns: otx record summary
|
||||||
|
"""
|
||||||
return backend_get_tx(chain_spec, tx_hash, session=session)
|
return backend_get_tx(chain_spec, tx_hash, session=session)
|
||||||
|
|
||||||
|
|
||||||
def get(self, chain_spec, decoder, session=None, requeue=False, *args, **kwargs):
|
def get(self, chain_spec, decoder, session=None, requeue=False, *args, **kwargs):
|
||||||
|
"""Gets transaction lists based on given criteria.
|
||||||
|
|
||||||
|
Calls chainqueue.sql.query.get_upcoming_tx. If requeue is True, the QUEUED status bit will be set on all matched transactions.
|
||||||
|
|
||||||
|
:param chain_spec: Chain spec context to look up transactions for
|
||||||
|
:type chain_spec: chainlib.chain.ChainSpec
|
||||||
|
:param decoder: Decoder instance to parse values from serialized transaction data in record
|
||||||
|
:type decoder: Function taking serialized tx as parameter
|
||||||
|
:param session: Sqlalchemy database session
|
||||||
|
:type session: sqlalchemy.orm.Session
|
||||||
|
:param status: Only match transaction that have the given bits set
|
||||||
|
:type status: int
|
||||||
|
:param not_status: Only match transactions that have none of the given bits set
|
||||||
|
:type not_status: int
|
||||||
|
:param recipient: Only match transactions that has the given address as recipient
|
||||||
|
:type recipient: str
|
||||||
|
:param before: Only match tranaactions that were last checked before the given time
|
||||||
|
:type before: datetime.datetime
|
||||||
|
:param limit: Return at most given number of transaction. If 0, will return all matched transactions.
|
||||||
|
:type limit: int
|
||||||
|
:rtype: dict
|
||||||
|
:returns: key value pairs of transaction hash and signed transaction data for all matching transactions
|
||||||
|
"""
|
||||||
txs = get_upcoming_tx(chain_spec, status=kwargs.get('status'), decoder=decoder, not_status=kwargs.get('not_status', 0), recipient=kwargs.get('recipient'), before=kwargs.get('before'), limit=kwargs.get('limit', 0))
|
txs = get_upcoming_tx(chain_spec, status=kwargs.get('status'), decoder=decoder, not_status=kwargs.get('not_status', 0), recipient=kwargs.get('recipient'), before=kwargs.get('before'), limit=kwargs.get('limit', 0))
|
||||||
if requeue:
|
if requeue:
|
||||||
for tx_hash in txs.keys():
|
for tx_hash in txs.keys():
|
||||||
@ -75,6 +155,21 @@ class SQLBackend:
|
|||||||
|
|
||||||
|
|
||||||
def dispatch(self, chain_spec, rpc, tx_hash, payload, session=None):
|
def dispatch(self, chain_spec, rpc, tx_hash, payload, session=None):
|
||||||
|
"""Send a single queued transaction.
|
||||||
|
|
||||||
|
:param chain_spec: Chain spec context for network send
|
||||||
|
:type chain_spec: chainlib.chain.ChainSpec
|
||||||
|
:param rpc: RPC connection to use for send
|
||||||
|
:type rpc: chainlib.connection.RPCConnection
|
||||||
|
:param tx_hash: Transaction hash of transaction to send
|
||||||
|
:type tx_hash: str
|
||||||
|
:param payload: Prepared RPC query to send
|
||||||
|
:type payload: any
|
||||||
|
:param session: Sqlalchemy database session
|
||||||
|
:type session: sqlalchemy.orm.Session
|
||||||
|
:rtype: int
|
||||||
|
:returns: 0 if no error
|
||||||
|
"""
|
||||||
set_reserved(chain_spec, tx_hash, session=session)
|
set_reserved(chain_spec, tx_hash, session=session)
|
||||||
fail = False
|
fail = False
|
||||||
r = 1
|
r = 1
|
||||||
@ -102,8 +197,12 @@ class SQLBackend:
|
|||||||
|
|
||||||
|
|
||||||
def create_session(self, session=None):
|
def create_session(self, session=None):
|
||||||
|
"""Alias for chainqueue.db.models.base.SessionBase.bind_session
|
||||||
|
"""
|
||||||
return SessionBase.bind_session(session=session)
|
return SessionBase.bind_session(session=session)
|
||||||
|
|
||||||
|
|
||||||
def release_session(self, session):
|
def release_session(self, session):
|
||||||
|
"""Alias for chainqueue.db.models.base.SessionBase.release_session
|
||||||
|
"""
|
||||||
return SessionBase.release_session(session=session)
|
return SessionBase.release_session(session=session)
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# TODO: this module could require better naming to discern what type of data the different methods return. Currently it's a mix of otx summary, otx objects, tx cache objects, tx representation dicts and hash/signedtx kv pairs
|
||||||
|
|
||||||
# standard imports
|
# standard imports
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
@ -127,6 +129,7 @@ def get_nonce_tx_cache(chain_spec, nonce, sender, decoder=None, session=None):
|
|||||||
:type decoder: TODO - define transaction decoder
|
:type decoder: TODO - define transaction decoder
|
||||||
:param session: Backend state integrity session
|
:param session: Backend state integrity session
|
||||||
:type session: varies
|
:type session: varies
|
||||||
|
:raises CacheIntegrityError: Cached data does not match intepreted data.
|
||||||
:returns: Transactions
|
:returns: Transactions
|
||||||
:rtype: dict, with transaction hash as key, signed raw transaction as value
|
:rtype: dict, with transaction hash as key, signed raw transaction as value
|
||||||
"""
|
"""
|
||||||
@ -160,17 +163,15 @@ def get_paused_tx_cache(chain_spec, status=None, sender=None, session=None, deco
|
|||||||
:type chain_spec: chainlib.chain.ChainSpec
|
:type chain_spec: chainlib.chain.ChainSpec
|
||||||
:param status: If set, will return transactions with this local queue status only
|
:param status: If set, will return transactions with this local queue status only
|
||||||
:type status: cic_eth.db.enum.StatusEnum
|
:type status: cic_eth.db.enum.StatusEnum
|
||||||
:param recipient: Recipient address to return transactions for
|
:param sender: Sender address to return transactions for
|
||||||
:type recipient: str, 0x-hex
|
:type sender: str
|
||||||
:param chain_id: Numeric chain id to use to parse signed transaction data
|
|
||||||
:type chain_id: number
|
|
||||||
:param decoder: Transaction decoder
|
|
||||||
:type decoder: TODO - define transaction decoder
|
|
||||||
:param session: Backend state integrity session
|
:param session: Backend state integrity session
|
||||||
:type session: varies
|
:type session: varies
|
||||||
|
:param decoder: Transaction decoder
|
||||||
|
:type decoder: Function accepting signed transaction data as input
|
||||||
:raises ValueError: Status is finalized, sent or never attempted sent
|
:raises ValueError: Status is finalized, sent or never attempted sent
|
||||||
:returns: Transactions
|
:returns: Key value pairs with transaction hash and signed raw transaction
|
||||||
:rtype: dict, with transaction hash as key, signed raw transaction as value
|
:rtype: dict
|
||||||
"""
|
"""
|
||||||
session = SessionBase.bind_session(session)
|
session = SessionBase.bind_session(session)
|
||||||
q = session.query(Otx)
|
q = session.query(Otx)
|
||||||
@ -465,13 +466,13 @@ def get_account_tx(chain_spec, address, as_sender=True, as_recipient=True, count
|
|||||||
return txs
|
return txs
|
||||||
|
|
||||||
|
|
||||||
def count_tx(chain_spec, address=None, status=None, status_target=None, session=None):
|
def count_tx(chain_spec, sender=None, status=None, status_target=None, session=None):
|
||||||
"""
|
"""Count transaction records matching the given criteria.
|
||||||
|
|
||||||
:param chain_spec: Chain spec for transaction network
|
:param chain_spec: Chain spec for transaction network
|
||||||
:type chain_spec: chainlib.chain.ChainSpec
|
:type chain_spec: chainlib.chain.ChainSpec
|
||||||
:param address: Address to count transactions for
|
:param sender: Sender address to count transactions for
|
||||||
:type address: str
|
:type sender: str
|
||||||
:param status: Status to count transactions for
|
:param status: Status to count transactions for
|
||||||
:type status: chainqueue.enum.StatusEnum
|
:type status: chainqueue.enum.StatusEnum
|
||||||
:param status_target: If set, will match status argument exactly against the given value
|
:param status_target: If set, will match status argument exactly against the given value
|
||||||
|
@ -379,7 +379,7 @@ def obsolete_by_cache(chain_spec, tx_hash, final, session=None):
|
|||||||
:param tx_hash: Transaction hash of record to modify, in hex
|
:param tx_hash: Transaction hash of record to modify, in hex
|
||||||
:type tx_hash: str
|
:type tx_hash: str
|
||||||
:param final: Transaction hash superseding record, in hex
|
:param final: Transaction hash superseding record, in hex
|
||||||
:type tx_hash: str
|
:type final: str
|
||||||
:param session: Backend state integrity session
|
:param session: Backend state integrity session
|
||||||
:type session: varies
|
:type session: varies
|
||||||
:raises TxStateChangeError: Transaction is not obsoletable
|
:raises TxStateChangeError: Transaction is not obsoletable
|
||||||
|
@ -38,6 +38,7 @@ def create(chain_spec, nonce, holder_address, tx_hash, signed_tx, obsolete_prede
|
|||||||
:type obsolete_predecessors: bool
|
:type obsolete_predecessors: bool
|
||||||
:param session: Backend state integrity session
|
:param session: Backend state integrity session
|
||||||
:type session: varies
|
:type session: varies
|
||||||
|
:raises TxStateChangeError: Transaction obsoletion failed
|
||||||
:returns: transaction hash, in hex
|
:returns: transaction hash, in hex
|
||||||
:rtype: str
|
:rtype: str
|
||||||
"""
|
"""
|
||||||
|
@ -21,6 +21,11 @@ db_config = {
|
|||||||
|
|
||||||
|
|
||||||
class ChainQueueDb:
|
class ChainQueueDb:
|
||||||
|
"""SQLITE database setup for unit tests
|
||||||
|
|
||||||
|
:param debug: Activate sql level debug (outputs sql statements)
|
||||||
|
:type debug: bool
|
||||||
|
"""
|
||||||
|
|
||||||
base = SessionBase
|
base = SessionBase
|
||||||
|
|
||||||
@ -48,8 +53,12 @@ class ChainQueueDb:
|
|||||||
|
|
||||||
|
|
||||||
def bind_session(self, session=None):
|
def bind_session(self, session=None):
|
||||||
|
"""Create session using underlying session base
|
||||||
|
"""
|
||||||
return self.base.bind_session(session)
|
return self.base.bind_session(session)
|
||||||
|
|
||||||
|
|
||||||
def release_session(self, session=None):
|
def release_session(self, session=None):
|
||||||
|
"""Release session using underlying session base
|
||||||
|
"""
|
||||||
return self.base.release_session(session)
|
return self.base.release_session(session)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = chainqueue
|
name = chainqueue
|
||||||
version = 0.0.4a6
|
version = 0.0.4a7
|
||||||
description = Generic blockchain transaction queue control
|
description = Generic blockchain transaction queue control
|
||||||
author = Louis Holbrook
|
author = Louis Holbrook
|
||||||
author_email = dev@holbrook.no
|
author_email = dev@holbrook.no
|
||||||
|
@ -39,6 +39,7 @@ class TestBasic(TestBase):
|
|||||||
tx = add_0x(os.urandom(128).hex())
|
tx = add_0x(os.urandom(128).hex())
|
||||||
nonce = 42
|
nonce = 42
|
||||||
otx = Otx(nonce, tx_hash, tx)
|
otx = Otx(nonce, tx_hash, tx)
|
||||||
|
otx.block = 1024
|
||||||
self.session.add(otx)
|
self.session.add(otx)
|
||||||
|
|
||||||
alice = add_0x(os.urandom(20).hex())
|
alice = add_0x(os.urandom(20).hex())
|
||||||
|
Loading…
Reference in New Issue
Block a user