Skip to content

Commit

Permalink
feat: add application states (#1974)
Browse files Browse the repository at this point in the history
* feat: add application state

* docs: generate API References

---------

Co-authored-by: Artem-Safronov <[email protected]>
  • Loading branch information
Artem-Safronov and Artem-Safronov authored Dec 12, 2024
1 parent 7025d86 commit b84c032
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 9 deletions.
32 changes: 23 additions & 9 deletions faststream/_internal/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@
from faststream._internal.constants import EMPTY
from faststream._internal.context import ContextRepo
from faststream._internal.log import logger
from faststream._internal.state import DIState
from faststream._internal.state import (
BasicApplicationState,
DIState,
RunningApplicationState,
)
from faststream._internal.state.broker import OuterBrokerState
from faststream._internal.utils import apply_types
from faststream._internal.utils.functions import (
Expand Down Expand Up @@ -99,21 +103,23 @@ def _init_setupable_( # noqa: PLW3201

serializer = PydanticSerializer()

self._state = DIState(
use_fastdepends=True,
get_dependent=None,
call_decorators=(),
serializer=serializer,
provider=self.provider,
context=self.context,
self._state = BasicApplicationState(
di_state=DIState(
use_fastdepends=True,
get_dependent=None,
call_decorators=(),
serializer=serializer,
provider=self.provider,
context=self.context,
)
)

self.broker = broker

self._setup()

def _setup(self) -> None:
self.broker._setup(OuterBrokerState(di_state=self._state))
self.broker._setup(OuterBrokerState(di_state=self._state.di_state))

async def _start_broker(self) -> None:
await self.broker.start()
Expand Down Expand Up @@ -188,6 +194,8 @@ async def _startup(
async with self._startup_logging(log_level=log_level):
await self.start(**(run_extra_options or {}))

self._state = RunningApplicationState(di_state=self._state.di_state)

async def start(
self,
**run_extra_options: "SettingField",
Expand Down Expand Up @@ -235,6 +243,8 @@ async def _shutdown(self, log_level: int = logging.INFO) -> None:
async with self._shutdown_logging(log_level=log_level):
await self.stop()

self._state = BasicApplicationState(di_state=self._state.di_state)

async def stop(self) -> None:
"""Executes shutdown hooks and stop broker."""
async with self._shutdown_hooks_context():
Expand Down Expand Up @@ -318,3 +328,7 @@ def after_shutdown(
apply_types(to_async(func), context__=self.context)
)
return func

@property
def running(self) -> bool:
return self._state.running
3 changes: 3 additions & 0 deletions faststream/_internal/state/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .application import BasicApplicationState, RunningApplicationState
from .broker import BrokerState, EmptyBrokerState
from .fast_depends import DIState
from .logger import LoggerParamsStorage, LoggerState
Expand All @@ -6,6 +7,7 @@

__all__ = (
# state
"BasicApplicationState",
"BrokerState",
# FastDepend
"DIState",
Expand All @@ -14,6 +16,7 @@
# logging
"LoggerState",
"Pointer",
"RunningApplicationState",
# proto
"SetupAble",
)
28 changes: 28 additions & 0 deletions faststream/_internal/state/application.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from abc import ABC, abstractmethod

from faststream._internal.state.fast_depends import DIState


class ApplicationState(ABC):
def __init__(self, di_state: DIState) -> None:
self._di_state = di_state

@property
@abstractmethod
def running(self) -> bool: ...

@property
def di_state(self) -> DIState:
return self._di_state


class BasicApplicationState(ApplicationState):
@property
def running(self) -> bool:
return False


class RunningApplicationState(ApplicationState):
@property
def running(self) -> bool:
return True
31 changes: 31 additions & 0 deletions tests/cli/test_app_state.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from unittest.mock import AsyncMock, patch

import pytest

from faststream import FastStream


@pytest.mark.asyncio()
async def test_state_running(app: FastStream) -> None:
with patch(
"faststream._internal.application.Application.start", new_callable=AsyncMock
):
await app._startup()

assert app.running


@pytest.mark.asyncio()
async def test_state_stopped(app: FastStream) -> None:
with (
patch(
"faststream._internal.application.Application.start", new_callable=AsyncMock
),
patch(
"faststream._internal.application.Application.stop", new_callable=AsyncMock
),
):
await app._startup()
await app._shutdown()

assert not app.running

0 comments on commit b84c032

Please sign in to comment.