def make_broadcast_futures(session: aiohttp.ClientSession, block_id: str, level: int, chain_ids: set) -> Optional[Set[asyncio.Task]]: """Initiate broadcasts for a block id to certain higher level nodes Args: session: aiohttp session to use for making http requests block_id: the block id to broadcast level: higher level of the chain_ids to broadcast to chain_ids: set of (level) chains to broadcast to Returns: Set of asyncio futures for the http requests initialized (None if it was not possible to get broadcast dto) """ path = "/v1/enqueue" broadcasts = set() try: broadcast_dto = block_dao.get_broadcast_dto(level, block_id) except exceptions.NotEnoughVerifications as e: _log.warning(f"[BROADCAST PROCESSOR] {str(e)}") _log.info(f"[BROADCAST PROCESSOR] Will attempt to broadcast block {block_id} next run") broadcast_functions.increment_storage_error_sync(block_id, level) return None _log.debug(f"[BROADCAST PROCESSOR] Sending broadcast(s) for {block_id} level {level}:\n{broadcast_dto}") for chain in chain_ids: try: headers, data = authorization.generate_authenticated_request("POST", chain, path, broadcast_dto) if level != 5: headers["deadline"] = str(BROADCAST_RECEIPT_WAIT_TIME) else: headers["deadline"] = str(get_l5_wait_time(chain)) url = f"{matchmaking.get_dragonchain_address(chain)}{path}" _log.info(f"[BROADCAST PROCESSOR] Firing transaction for {chain} (level {level}) at {url}") broadcasts.add(asyncio.create_task(session.post(url=url, data=data, headers=headers, timeout=HTTP_REQUEST_TIMEOUT))) except Exception: _log.exception(f"[BROADCAST PROCESSOR] Exception trying to broadcast to {chain}") return broadcasts
def test_storage_error_rolls_back_state_correctly_when_needed( self, list_objects, smembers_sync, get_sync, state_key, verifications_key, error_key, mock_pipeline ): fake_pipeline = MagicMock() mock_pipeline.return_value = fake_pipeline broadcast_functions.increment_storage_error_sync("blah", 3) mock_pipeline.assert_called_once() fake_pipeline.srem.assert_called_once_with("verifications_key", "def") fake_pipeline.delete.assert_called_once_with("error_key") fake_pipeline.set.assert_called_once_with("state_key", "2") fake_pipeline.execute.assert_called_once()
def test_storage_error_increments_redis_value_correctly( self, set_sync, get_sync, patch_error_key): broadcast_functions.increment_storage_error_sync("blah", 3) get_sync.assert_called_once_with("key", decode=False) set_sync.assert_called_once_with("key", "3")
def test_storage_error_no_op_when_low_level(self, patch_error_key): broadcast_functions.increment_storage_error_sync("blah", 2) broadcast_functions.increment_storage_error_sync("blah", 1) patch_error_key.assert_not_called()