Add state log, tx cache test, add final setter on tx cache

This commit is contained in:
nolash
2021-04-02 14:02:22 +02:00
parent a219f3272e
commit 5ea1b15c53
11 changed files with 226 additions and 43 deletions

View File

@@ -51,6 +51,7 @@ class StatusEnum(enum.IntEnum):
SENDFAIL = StatusBits.DEFERRED | StatusBits.LOCAL_ERROR
RETRY = StatusBits.QUEUED | StatusBits.DEFERRED
READYSEND = StatusBits.QUEUED
RESERVED = StatusBits.RESERVED
OBSOLETED = StatusBits.OBSOLETE | StatusBits.IN_NETWORK
@@ -124,6 +125,15 @@ def is_error_status(v):
return bool(v & all_errors())
__ignore_manual_value = ~StatusBits.MANUAL
def ignore_manual(v):
return v & __ignore_manual_value
def is_nascent(v):
return ignore_manual(v) == StatusEnum.PENDING
def dead():
"""Bit mask defining whether a transaction is still likely to be processed on the network.

View File

@@ -30,7 +30,7 @@ def upgrade():
sa.Column('recipient', sa.String(42), nullable=False),
sa.Column('from_value', sa.NUMERIC(), nullable=False),
sa.Column('to_value', sa.NUMERIC(), nullable=True),
sa.Column('block_number', sa.BIGINT(), nullable=True),
# sa.Column('block_number', sa.BIGINT(), nullable=True),
sa.Column('tx_index', sa.Integer, nullable=True),
)

View File

@@ -519,23 +519,7 @@ class Otx(SessionBase):
return q.first()
@staticmethod
def account(account_address):
"""Retrieves all transaction hashes for which the given Ethereum address is sender or recipient.
:param account_address: Ethereum address to use in query.
:type account_address: str, 0x-hex
:returns: Outgoing transactions
:rtype: tuple, where first element is transaction hash
"""
session = Otx.create_session()
q = session.query(Otx.tx_hash)
q = q.join(TxCache)
q = q.filter(or_(TxCache.sender==account_address, TxCache.recipient==account_address))
txs = q.all()
session.close()
return list(txs)
def __state_log(self, session):
l = OtxStateLog(self)

View File

@@ -59,7 +59,7 @@ class TxCache(SessionBase):
recipient = Column(String(42))
from_value = Column(NUMERIC())
to_value = Column(NUMERIC())
block_number = Column(Integer())
#block_number = Column(Integer())
tx_index = Column(Integer())
date_created = Column(DateTime, default=datetime.datetime.utcnow)
date_updated = Column(DateTime, default=datetime.datetime.utcnow)
@@ -126,6 +126,65 @@ class TxCache(SessionBase):
SessionBase.release_session(session)
# TODO: possible dead code
@staticmethod
def account(account_address, session=None):
"""Retrieves all transaction hashes for which the given Ethereum address is sender or recipient.
:param account_address: Ethereum address to use in query.
:type account_address: str, 0x-hex
:returns: Outgoing transactions
:rtype: tuple, where first element is transaction hash
"""
session = SessionBase.bind_session(session)
q = session.query(Otx.tx_hash)
q = q.join(TxCache)
q = q.filter(or_(TxCache.sender==account_address, TxCache.recipient==account_address))
txs = q.all()
SessionBase.release_session(session)
return list(txs)
@staticmethod
def set_final(tx_hash, block_number, tx_index, session=None):
session = SessionBase.bind_session(session)
q = session.query(TxCache)
q = q.join(Otx)
q = q.filter(Otx.tx_hash==strip_0x(tx_hash))
q = q.filter(Otx.block==block_number)
o = q.first()
if o == None:
raise NotLocalTxError(tx_hash, block_number)
o.tx_index = tx_index
session.add(o)
session.flush()
SessionBase.release_session(session)
@staticmethod
def load(tx_hash, session=None):
"""Retrieves the outgoing transaction record by transaction hash.
:param tx_hash: Transaction hash
:type tx_hash: str, 0x-hex
"""
session = SessionBase.bind_session(session)
q = session.query(TxCache)
q = q.join(Otx)
q = q.filter(Otx.tx_hash==strip_0x(tx_hash))
SessionBase.release_session(session)
return q.first()
def __init__(self, tx_hash, sender, recipient, source_token_address, destination_token_address, from_value, to_value, block_number=None, tx_index=None, session=None):
session = SessionBase.bind_session(session)
q = session.query(Otx)

View File

@@ -5,7 +5,9 @@ class ChainQueueException(Exception):
class NotLocalTxError(ChainQueueException):
"""Exception raised when trying to access a tx not originated from a local task
"""
pass
def __init__(self, tx_hash, block=None):
super(NotLocalTxError, self).__init__(tx_hash, block)
class TxStateChangeError(ChainQueueException):

View File

@@ -11,6 +11,7 @@ from chainqueue.db.models.base import SessionBase
from chainqueue.db.enum import (
StatusEnum,
StatusBits,
is_nascent,
)
from chainqueue.db.models.otx import OtxStateLog
from chainqueue.error import (
@@ -95,6 +96,14 @@ def set_final(tx_hash, block=None, fail=False):
session.close()
raise(e)
q = session.query(TxCache)
q = q.join(Otx)
q = q.filter(Otx.tx_hash==strip_0x(tx_hash))
o = q.first()
if o != None:
session.close()
return tx_hash
@@ -224,7 +233,7 @@ def set_ready(tx_hash):
raise NotLocalTxError('queue does not contain tx hash {}'.format(tx_hash))
session.flush()
if o.status & StatusBits.GAS_ISSUES or o.status == StatusEnum.PENDING:
if o.status & StatusBits.GAS_ISSUES or is_nascent(o.status):
o.readysend(session=session)
else:
o.retry(session=session)
@@ -285,7 +294,7 @@ def get_state_log(tx_hash):
q = session.query(OtxStateLog)
q = q.join(Otx)
q = q.filter(Otx.tx_hash==tx_hash)
q = q.filter(Otx.tx_hash==strip_0x(tx_hash))
q = q.order_by(OtxStateLog.date.asc())
for l in q.all():
logs.append((l.date, l.status,))
@@ -332,4 +341,3 @@ def cancel_obsoletes_by_cache(tx_hash):
session.close()
return tx_hash

View File

@@ -39,6 +39,7 @@ def create(nonce, holder_address, tx_hash, signed_tx, chain_spec, obsolete_prede
)
session.flush()
# TODO: No magic, please, should be separate step
if obsolete_predecessors:
q = session.query(Otx)
q = q.join(TxCache)
@@ -60,7 +61,6 @@ def create(nonce, holder_address, tx_hash, signed_tx, chain_spec, obsolete_prede
session.close()
raise(e)
session.commit()
SessionBase.release_session(session)
logg.debug('queue created nonce {} from {} hash {}'.format(nonce, holder_address, tx_hash))