Add state log, tx cache test, add final setter on tx cache
This commit is contained in:
@@ -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.
|
||||
|
||||
|
||||
@@ -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),
|
||||
)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user