Handle duplicate tx attempts

This commit is contained in:
lash 2022-04-12 13:44:29 +00:00
parent c22fafad53
commit 95930ef7de
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
5 changed files with 33 additions and 3 deletions

View File

@ -42,7 +42,6 @@ class StatusEnum(enum.IntEnum):
""" """
PENDING = 0 PENDING = 0
"""Transaction has been added but no processing has been performed""" """Transaction has been added but no processing has been performed"""
SENDFAIL = StatusBits.DEFERRED | StatusBits.LOCAL_ERROR SENDFAIL = StatusBits.DEFERRED | StatusBits.LOCAL_ERROR
"""Temporary error occurred when sending transaction to node""" """Temporary error occurred when sending transaction to node"""
RETRY = StatusBits.QUEUED | StatusBits.DEFERRED RETRY = StatusBits.QUEUED | StatusBits.DEFERRED

View File

@ -29,3 +29,8 @@ class BackendIntegrityError(ChainQueueException):
""" """
pass pass
class DuplicateTxError(ChainQueueException):
"""Backend already knows transaction
"""
pass

View File

@ -6,7 +6,9 @@ import logging
# local imports # local imports
from chainqueue.cache import CacheTx from chainqueue.cache import CacheTx
from chainqueue.entry import QueueEntry from chainqueue.entry import QueueEntry
from chainqueue.error import NotLocalTxError from chainqueue.error import (
NotLocalTxError,
)
logg = logging.getLogger(__name__) logg = logging.getLogger(__name__)
@ -53,8 +55,8 @@ class Store:
n = self.counter.next() n = self.counter.next()
t = datetime.datetime.now().timestamp() t = datetime.datetime.now().timestamp()
s = to_key(t, n, k) s = to_key(t, n, k)
self.state_store.put(s, v)
self.index_store.put(k, s) self.index_store.put(k, s)
self.state_store.put(s, v)
if self.cache != None: if self.cache != None:
self.cache.put(self.chain_spec, tx) self.cache.put(self.chain_spec, tx)
return (s, k,) return (s, k,)

View File

@ -5,6 +5,9 @@ import logging
# external imports # external imports
from leveldir.hex import HexDir from leveldir.hex import HexDir
# local imports
from chainqueue.error import DuplicateTxError
logg = logging.getLogger(__name__) logg = logging.getLogger(__name__)
@ -14,10 +17,21 @@ class IndexStore(HexDir):
os.path.join(root_path, 'contents') os.path.join(root_path, 'contents')
self.store = HexDir(root_path, digest_bytes) self.store = HexDir(root_path, digest_bytes)
def __exists(self, k):
existing = None
try:
existing = self.get(k)
except FileNotFoundError:
pass
return existing != None
def put(self, k, v): def put(self, k, v):
kb = bytes.fromhex(k) kb = bytes.fromhex(k)
vb = v.encode('utf-8') vb = v.encode('utf-8')
if self.__exists(k):
raise DuplicateTxError(k)
self.store.add(kb, vb) self.store.add(kb, vb)

View File

@ -12,6 +12,7 @@ from chainqueue.store.fs import (
IndexStore, IndexStore,
CounterStore, CounterStore,
) )
from chainqueue.error import DuplicateTxError
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
@ -48,5 +49,14 @@ class TestStoreImplementations(unittest.TestCase):
self.assertEqual(v, 2) self.assertEqual(v, 2)
def test_duplicate(self):
store = IndexStore(self.path)
hx = os.urandom(32).hex()
data = 'foo_bar_baz'
store.put(hx, data)
with self.assertRaises(DuplicateTxError):
store.put(hx, data)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()