async def on_assign(self, assign: BouncedForwardedAssignMessage): assign_handler = AssignHandler(message=assign, connection=self.connector) self.assign_handler_map[assign.meta.reference] = assign_handler await assign_handler.log(f"Assignment received", level=DebugLevel.INFO) try: try: args, kwargs = await expandInputs( node=self.template.node, args=assign.data.args, kwargs=assign.data.kwargs) if self.expandInputs else ( assign.data.args, assign.data.kwargs) await self._assign( assign_handler, args, kwargs ) # We dont do all of the handling here, as we really want to have a generic class for Generators and Normal Functions except Exception as e: # As broad as possible to send further await assign_handler.log( "Captured an Exception on the Broadest Level of Assignment. Please make sure to capure this exception before.", level=LogLevel.WARN) console.print_exception() await assign_handler.pass_exception(e) except asyncio.CancelledError as e: await assign_handler.log(f"Cancellation of Assignment suceeded", level=DebugLevel.INFO) await assign_handler.pass_cancelled() raise e
async def pass_async(self, the_query: TypedGQL, variables: dict = {}, **kwargs): query_node = the_query.query try: async with self.async_session.post(self._graphql_endpoint, json={"query": query_node, "variables": variables}) as resp: if resp.status == 200: result = await resp.json() logger.debug(f"Received Reply {result}") if "errors" in result: raise GraphQLException(f"Ward {self._graphql_endpoint}:" + str(result["errors"])) return the_query.extract(result["data"]) if resp.status == 400: raise WardException(await resp.json()) if resp.status == 403: console.log("Auth token is expired trying to refresh") raise TokenExpired("Token Expired Error") raise WardException(f"Unexpected statuscode {resp.status} {resp}") except: console.print_exception(show_locals=True) raise
async def connectBergen(self): try: self._bergen = ProviderBergen(**self.default_kwargs) print("Here") await self._bergen.negotiate_async() except: console.print_exception()
async def configure(self): try: await self.connect() if self.needs_negotiation: return await self.negotiate() return except: console.print_exception() raise ConnectionError(f"Ward {self.distinct}: Connection to {self.host}:{self.port} on {self.port} Failed")
async def startup(self): try: await self.connect_websocket() except Exception as e: console.print("[blue] Connection attempt as Provider failed") self.current_retries += 1 if self.auto_reconnect: sleeping_time = (self.current_retries + 1) console.print(f"[blue] Trying to Reconnect as Provider in {sleeping_time} seconds") await asyncio.sleep(sleeping_time) await self.startup() else: console.print("[blue]Provider: No reconnecting attempt envisioned. Shutting Down!") console.print_exception() console.print("[blue] Sucessfully Established A Connection to Provider Endpoint") self.consumer_task = create_task( self.consumer() ) self.producer_task = create_task( self.producer() ) self.worker_task = create_task( self.workers() ) done, self.pending = await asyncio.wait( [self.consumer_task, self.worker_task, self.producer_task], return_when=asyncio.FIRST_EXCEPTION ) try: for task in done: if task.exception(): raise task.exception() except ConnectionClosedError: console.print("[blue] Provider Connection was closed. Trying Reconnect") except: console.print_exception() logger.error(f"Provider: Lost connection inbetween everything :( {[ task.exception() for task in done]}") logger.error(f'Provider: Reconnecting') if self.connection: await self.connection.close() for task in self.pending: task.cancel() console.log("Trying to Reconnect") self.current_retries = 0 # reset retries after one successfull connection await self.startup() # Attempt to ronnect again
async def pass_critical(self, exception): critical_message = UnprovideCriticalMessage(data={ "message": str(exception), "type": exception.__class__.__name__ }, meta=self.meta) console.print_exception() return await self.connection.forward(critical_message)
async def change_state(self, seconds: int): try: while True: await asyncio.sleep(seconds) print("Changing State to INactive") await self.provide_handler.set_state(ProvideState.INACTIVE) await asyncio.sleep(seconds) print("Changing State to Active") await self.provide_handler.set_state(ProvideState.ACTIVE) except: console.print_exception()
async def startup(self): try: await self.connect_websocket() except Exception as e: console.print("[green] Connection attempt as Postman failed") self.current_retries += 1 self.current_retries += 1 if self.auto_reconnect: sleeping_time = (self.current_retries + 1) console.print( f"[green] Trying to Reconnect as Postman in {sleeping_time} seconds" ) await asyncio.sleep(sleeping_time) await self.startup() else: return console.print("[green] Successfully established Postman Connection") self.receiving_task = create_task(self.receiving()) self.sending_task = create_task(self.sending()) self.callback_task = create_task(self.callbacks()) done, self.pending = await asyncio.wait( [self.callback_task, self.receiving_task, self.sending_task], return_when=asyncio.FIRST_EXCEPTION) try: for task in done: if task.exception(): raise task.exception() except ConnectionClosedError: console.print( "[green] Postman Connection was closed. Trying Reconnect") except: console.print_exception() logger.debug( f"Postman: Lost connection inbetween everything :( {[ task.exception() for task in done]}" ) logger.error(f'Postman: Trying to reconnect Postman') if self.connection: await self.connection.close() for task in self.pending: task.cancel() self.current_retries = 0 # reset retries after one successfull connection await self.startup()
async def stream_worker(self, queue: asyncio.Queue): try: self.reference = await self._postman.stream_reserve_to_queue( queue, node_id=self.node.id, provision=self.provision, params_dict=self.params.dict(), with_log=self.with_log, context=self.context) print(self.reference) while True: message = await queue.get() if isinstance(message, ReserveCriticalMessage): if self.enter_future.done(): self.log( f"We have transitioned to a critical State {message.data.message}" ) self.current_state = ReserveState.CRITICAL else: self.enter_future.set_exception( Exception(message.data.message)) elif isinstance(message, ReserveTransitionMessage): # Once we acquire a reserved resource our contract (the inner part of the context can start) self.current_state = message.data.state if self.transition_hook: await self.transition_hook(self, message.data.state) if self.current_state in self.exit_states: if not self.is_closing: self.log( f"Received Exitstate: {message.data.state}. Closing reservation at next assignment", level=LogLevel.CRITICAL) return # This means we do no longer need to here about stuff if self.current_state in self.enter_states: if self.enter_future.done(): self.log("We are already entered.") else: self.enter_future.set_result( message.meta.reference) else: console.log(message) queue.task_done() except Exception as e: console.print_exception() if not self.enter_future.done(): self.enter_future.set_exception(e) raise e
async def run(self, gql: TypedGQL, variables: dict = {}): try: return await self.pass_async(gql, variables=variables) except TokenExpired: console.print_exception() self.auth.refetch() self._headers = {"Authorization": f"Bearer {self.auth.access_token}"} await self.disconnect() await self.connect() return await self.pass_async(gql, variables=variables) except: console.print_exception(show_locals=True) raise
async def _on_provide_message(self, message: BouncedProvideMessage): self.provide_handler = ProvideHandler(message, self.connector) try: await self.provide_handler.log("Providing ssss", level=LogLevel.INFO) self.template = await self.provide_handler.get_template() provision_context = await self.on_provide(self.provide_handler) if provision_context is not None: self.provide_handler.set_context(provision_context) await self.provide_handler.log("Provision Done", level=LogLevel.INFO) self._provided = True await self.provide_handler.pass_done() except Exception as e: console.print_exception() await self.provide_handler.pass_exception(e)
async def unentertain(self, bounced_unprovide: BouncedUnprovideMessage): unprovide_handler = UnprovideHandler(bounced_unprovide, self.connector) try: provision_reference = bounced_unprovide.data.provision assert provision_reference in self.provision_actor_run_map, "We dont entertain this provision" task = self.provision_actor_run_map[provision_reference] if not task.done(): await unprovide_handler.pass_log("Cancelling", level=LogLevel.INFO) task.cancel() await unprovide_handler.pass_done() else: raise TaskAlreadyDoneError("Task was already done") except ProtocolException as e: console.print_exception() await unprovide_handler.pass_error(e) except Exception as e: console.print_exception() await unprovide_handler.pass_critical(e)
async def pass_async(self, the_query: TypedGQL, variables: dict = {}, **kwargs): query_node = gql(the_query.query) try: try: response = await self.async_transport.execute( query_node, variable_values=variables) except Exception as e: console.print_exception(show_locals=True) raise TokenExpired(f"Token Expired {e}") if response.errors: raise GraphQLException(f"Ward {self._graphql_endpoint}:" + str(response.errors)) return the_query.extract(response.data) except: console.print_exception(show_locals=True) raise
async def show(rep: Representation) -> Representation: try: await interface.helper.openRepresentationAsLayer(rep=rep) except: console.print_exception() return rep
async def on_except(self, exception): console.print_exception()
async def configure(self): try: await self.connect() except: console.print_exception() raise ConnectionError(f"BaseWard: Connection to {self.host}:{self.port} on {self.port} Failed")
async def run(self, bounced_provide: BouncedProvideMessage): ''' An infinitie loop assigning to itself''' try: await self._on_provide_message(bounced_provide) try: assert self._provided, "We didnt provide this actor before running" while True: message = await self.queue.get() if isinstance(message, BouncedForwardedAssignMessage): task = create_task(self.on_assign(message)) task.add_done_callback( self.check_if_assignation_cancelled) self.assignments[message.meta.reference] = task elif isinstance(message, BouncedUnassignMessage): if message.data.assignation in self.assignments: await self.log( f"Cancellation of assignment {message.data.assignation}", level=DebugLevel.INFO) task = self.assignments[message.data.assignation] if not task.done(): task.cancel() unassign_done = UnassignDoneMessage( data={ "assignation": message.data.assignation }, meta={ "reference": message.meta.reference, "extensions": message.meta.extensions }) await self.connector.forward(unassign_done) await self.log( f"Cancellation of assignment suceeded", level=DebugLevel.INFO) else: unassign_critical = UnassignCriticalMessage( data={ "message": "Task was already done", "type": "Exception" }, meta={ "reference": message.meta.reference, "extensions": message.meta.extensions }) await self.connector.forward(unassign_critical) await self.log( f"Cancellation of assignment failed. Task was already Done", level=DebugLevel.INFO) #TODO: Maybe send this to arkitekt as well? else: unassign_done = UnassignDoneMessage( data={"assignation": message.data.assignation}, meta={ "reference": message.meta.reference, "extensions": message.meta.extensions }) await self.connector.forward(unassign_done) await self.log( f"There was nether an assignment on this Worker... Sending Done", level=DebugLevel.INFO) else: raise Exception(f"Type not known {message}") self.queue.task_done() except Exception as e: console.print_exception() except asyncio.CancelledError: await self.on_unprovide(self.provide_handler) await self.log("Actor was beeing cancelled") raise