async def send(self, message: Message) -> None: """ Awaited by the application to send ASGI `lifespan` events. """ message_type = message["type"] self.logger.info("%s: '%s' event received from application.", self.state, message_type) if self.state is LifespanCycleState.CONNECTING: if self.lifespan == "on": raise LifespanFailure( "Lifespan connection failed during startup and lifespan is 'on'." ) # If a message is sent before the startup event is received by the # application, then assume that lifespan is unsupported. self.state = LifespanCycleState.UNSUPPORTED raise LifespanUnsupported("Lifespan protocol appears unsupported.") if message_type not in ( "lifespan.startup.complete", "lifespan.shutdown.complete", "lifespan.startup.failed", "lifespan.shutdown.failed", ): self.state = LifespanCycleState.FAILED raise UnexpectedMessage( f"Unexpected '{message_type}' event received.") if self.state is LifespanCycleState.STARTUP: if message_type == "lifespan.startup.complete": self.startup_event.set() elif message_type == "lifespan.startup.failed": self.state = LifespanCycleState.FAILED self.startup_event.set() message = message.get("message", "") raise LifespanFailure(f"Lifespan startup failure. {message}") elif self.state is LifespanCycleState.SHUTDOWN: if message_type == "lifespan.shutdown.complete": self.shutdown_event.set() elif message_type == "lifespan.shutdown.failed": self.state = LifespanCycleState.FAILED self.shutdown_event.set() message = message.get("message", "") raise LifespanFailure(f"Lifespan shutdown failure. {message}")
async def shutdown(self) -> None: """ Pushes the `lifespan` shutdown event to application queue and handles errors. """ self.logger.info("Waiting for application shutdown.") await self.app_queue.put({"type": "lifespan.shutdown"}) await self.shutdown_event.wait() if self.state is LifespanCycleState.FAILED: raise LifespanFailure(self.exception)
async def send(self, message: Message) -> None: if not self.is_supported: raise LifespanFailure("Lifespan unsupported.") message_type = message["type"] if message_type == "lifespan.startup.complete": self.startup_event.set() elif message_type == "lifespan.shutdown.complete": self.shutdown_event.set() else: raise RuntimeError( f"Expected lifespan message type, received: {message_type}")
async def startup(self) -> None: """ Pushes the `lifespan` startup event to application queue and handles errors. """ self.logger.info("Waiting for application startup.") await self.app_queue.put({"type": "lifespan.startup"}) await self.startup_event.wait() if self.state is LifespanCycleState.FAILED: raise LifespanFailure(self.exception) if not self.exception: self.logger.info("Application startup complete.") else: self.logger.info("Application startup failed.")