async def __settle_bounty(self, bounty_guid, chain): """ Callback registered in `__init__` to handle a settled bounty. Args: bounty_guid (str): GUID of the bounty being asserted on chain (str): Chain to operate on Returns: Response JSON parsed from polyswarmd containing emitted events """ async with self.bounties_pending_locks[chain]: bounties_pending = self.bounties_pending.get(chain, set()) if bounty_guid not in bounties_pending: logger.debug('Bounty %s already settled', bounty_guid) return [] self.bounties_pending[chain] = bounties_pending - {bounty_guid} self.settles_posted += 1 if self.testing > 0: if self.settles_posted > self.testing: logger.warning( 'Scheduled settle, but finished with testing mode') return [] logger.info('Testing mode, %s settles remaining', self.testing - self.settles_posted) ret = await self.client.bounties.settle_bounty(bounty_guid, chain) if 0 < self.testing <= self.settles_posted: logger.info('All testing bounties complete, exiting') asyncio_stop() return ret
async def __handle_settle_bounty(self, bounty_guid, chain): """ Settle the given bounty on the given chain. Args: bounty_guid (str): The bounty which we are settling. chain (str): Which chain to operate on. Returns: Response JSON parsed from polyswarmd containing emitted events. """ async with self.bounties_pending_locks[chain]: bounties_pending = self.bounties_pending.get(chain, set()) if bounty_guid not in bounties_pending: logger.debug('Bounty %s already settled', bounty_guid) return [] self.bounties_pending[chain] = bounties_pending - {bounty_guid} self.settles_posted += 1 if self.testing > 0: if self.settles_posted > self.testing: logger.warning( 'Scheduled settle, but finished with testing mode') return [] logger.info('Testing mode, %s settles remaining', self.testing - self.settles_posted) ret = await self.client.bounties.settle_bounty(bounty_guid, chain) if 0 < self.testing <= self.settles_posted: logger.info('All testing bounties complete, exiting') asyncio_stop() return ret
def run(self, chains=None): """Run the main event loop Args: chains (set(str)): Set of chains to operate on. Defaults to {'home', 'side'} """ if chains is None: chains = {'home', 'side'} configure_event_loop() while True: try: asyncio.get_event_loop().run_until_complete( self.run_task(chains=chains)) except asyncio.CancelledError: logger.info('Clean exit requested, exiting') asyncio_join() exit(0) except Exception: logger.exception('Unhandled exception at top level') asyncio_stop() asyncio_join() self.tries += 1 wait = min(MAX_WAIT, self.tries * self.tries) logger.critical( 'Detected unhandled exception, sleeping for %s seconds then resetting task', wait) time.sleep(wait) continue
def mock_client(event_loop): asyncio.set_event_loop(event_loop) client = MockClient() client.start() yield client client.stop() asyncio_stop() asyncio_join()
async def watch_balance(self, block, chain): """ Stores the latest block and then kicks off some balance checks. If the balance is outside the given range, it deposits, or withdraws as needed. """ # Do nothing when talking to polyswarmd-fast if isinstance(self.client.bounties, polyswarmclient.fast.bountiesclient.BountiesClient): return if chain == 'side': return # Keep block up to date, so we can use that value when figuring out what block the transaction may have gone in if chain == 'home': async with self.block_lock: if block > self.latest_block: self.latest_block = block else: return async with self.deposit_lock: side_balance = await self.client.balances.get_nct_balance( chain='side') if 0 < self.testing <= self.transfers: logger.info('Finished text runs') asyncio_stop() if self.last_relay is not None and (self.last_relay + self.confirmations) >= block: more_blocks = self.last_relay + self.confirmations - block logger.info('Waiting for %d more blocks', more_blocks) return elif self.last_relay is not None: logger.info('Checking NCT balance') # We can handle up to half refill_amount changes in either direction for any given block. # Greater than that, and the client will have to restart. if self.last_balance + (self.refill_amount / 2) >= side_balance: # Update balance, so each check against refill amount is from the latest changes self.last_balance = side_balance logger.error( 'Transfer does not appear to have completed. ' 'Initial Balance: %s nct-wei. Current Balance: %s nct-wei.', self.initial_balance, side_balance) return else: logger.info('Balance increased to %s nct-wei', side_balance) self.last_relay = None self.last_balance = 0 self.initial_balance = 0 if self.maximum is not None and self.withdraw_target is not None and side_balance > self.maximum: await self.try_withdrawal(side_balance) elif side_balance < self.minimum: await self.try_deposit(side_balance)
def run(self): configure_event_loop() loop = asyncio.get_event_loop() try: self.start(loop) # This stops any leftover tasks after out main task finishes asyncio_stop() except asyncio.CancelledError: logger.info('Clean exit requested, exiting') asyncio_join() except Exception: logger.exception('Unhandled exception at top level') asyncio_stop() asyncio_join()
def run(self, chains=None): """Run the main event loop Args: chains (set(str)): Set of chains to operate on. Defaults to {'home', 'side'} """ if chains is None: chains = {'home', 'side'} # noinspection PyBroadException try: asyncio.get_event_loop().run_until_complete(self.run_task(chains=chains)) except asyncio.CancelledError: logger.info('Clean exit requested') utils.asyncio_join() except Exception: logger.exception('Unhandled exception at top level') utils.asyncio_stop() utils.asyncio_join()
async def __do_handle_settle_bounty(self, bounty_guid, chain): """ When a bounty is scheduled to be settled, actually settle the bounty to the given chain. Args: bounty_guid (str): GUID of the bounty to be submitted. chain (str): Name of the chain where the bounty is to be posted. Returns: Response JSON parsed from polyswarmd containing emitted events. """ async with self.bounties_pending_locks[chain]: bounties_pending = self.bounties_pending.get(chain, set()) if bounty_guid not in bounties_pending: logger.debug(f'Bounty {bounty_guid} already settled') return [] self.bounties_pending[chain] = bounties_pending - {bounty_guid} last_settle = False async with self.settles_posted_locks[chain]: settles_posted = self.settles_posted.get(chain, 0) self.settles_posted[chain] = settles_posted + 1 if self.testing > 0: if self.settles_posted[chain] > self.testing: logger.warning( 'Scheduled settle, but finished with testing mode') return [] elif self.settles_posted[chain] == self.testing: last_settle = True logger.info( f'Testing mode, {self.testing - self.settles_posted[chain]} settles remaining' ) ret = await self.client.bounties.settle_bounty(bounty_guid, chain) if last_settle: logger.info("All testing bounties complete, exiting") asyncio_stop() return ret
def run(self): while not self.finished: configure_event_loop() loop = asyncio.get_event_loop() try: self.start(loop) # This stops any leftover tasks after out main task finishes asyncio_stop() except asyncio.CancelledError: logger.info('Clean exit requested, exiting') asyncio_join() exit(0) except Exception: logger.exception('Unhandled exception at top level') asyncio_stop() asyncio_join() self.tries += 1 wait = min(MAX_WAIT, self.tries * self.tries) logger.critical( f'Detected unhandled exception, sleeping for {wait} seconds then resetting task' ) time.sleep(wait) continue
def run(self): while not self.finished: loop = asyncio.SelectorEventLoop() # Default event loop does not support pipes on Windows if sys.platform == 'win32': loop = asyncio.ProactorEventLoop() asyncio.set_event_loop(loop) # K8 uses SIGTERM on linux and SIGINT and windows exit_signal = signal.SIGINT if platform.system() == "Windows" else signal.SIGTERM try: loop.add_signal_handler(exit_signal, self.handle_signal) except NotImplementedError: # Disable graceful exit, but run anyway logger.exception(f'{platform.system()} does not support graceful shutdown') try: asyncio.get_event_loop().run_until_complete(self.setup()) gather_task = asyncio.gather(*[self.run_task(i) for i in range(self.task_count)]) asyncio.get_event_loop().run_until_complete(gather_task) except asyncio.CancelledError: logger.info('Clean exit requested, exiting') asyncio_join() exit(0) except Exception: logger.exception('Unhandled exception at top level') asyncio_stop() asyncio_join() self.tries += 1 wait = min(MAX_WAIT, self.tries * self.tries) logger.critical(f'Detected unhandled exception, sleeping for {wait} seconds then resetting task') time.sleep(wait) continue
def stop(self): self.http_mock.stop() self.__ws_mock_manager.stop() asyncio_stop()