# standard imports import datetime # third-party imports from sqlalchemy import Column, String, Integer, DateTime, Text, Boolean from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method # local imports from .base import SessionBase class BlockchainSync(SessionBase): """Syncer control backend. :param chain: Chain spec string representation :type chain: str :param block_start: Block number to start sync from :type block_start: number :param tx_start: Block transaction number to start sync from :type tx_start: number :param block_target: Block number to sync until, inclusive :type block_target: number """ __tablename__ = 'chain_sync' blockchain = Column(String) block_start = Column(Integer) tx_start = Column(Integer) block_cursor = Column(Integer) tx_cursor = Column(Integer) block_target = Column(Integer) date_created = Column(DateTime, default=datetime.datetime.utcnow) date_updated = Column(DateTime) @staticmethod def first(chain, session=None): """Check if a sync session for the specified chain already exists. :param chain: Chain spec string representation :type chain: str :param session: Session to use. If not specified, a separate session will be created for this method only. :type session: SqlAlchemy Session :returns: True if sync record found :rtype: bool """ local_session = False if session == None: session = SessionBase.create_session() local_session = True q = session.query(BlockchainSync.id) q = q.filter(BlockchainSync.blockchain==chain) o = q.first() if local_session: session.close() return o == None @staticmethod def get_last_live_height(current, session=None): """Get the most recent open-ended ("live") syncer record. :param current: Current block number :type current: number :param session: Session to use. If not specified, a separate session will be created for this method only. :type session: SqlAlchemy Session :returns: Block and transaction number, respectively :rtype: tuple """ local_session = False if session == None: session = SessionBase.create_session() local_session = True q = session.query(BlockchainSync) q = q.filter(BlockchainSync.block_target==None) q = q.order_by(BlockchainSync.date_created.desc()) o = q.first() if local_session: session.close() if o == None: return (0, 0) return (o.block_cursor, o.tx_cursor) @staticmethod def get_unsynced(session=None): """Get previous bounded sync sessions that did not complete. :param session: Session to use. If not specified, a separate session will be created for this method only. :type session: SqlAlchemy Session :returns: Syncer database ids :rtype: tuple, where first element is id """ unsynced = [] local_session = False if session == None: session = SessionBase.create_session() local_session = True q = session.query(BlockchainSync.id) q = q.filter(BlockchainSync.block_target!=None) q = q.filter(BlockchainSync.block_cursor