Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add application states #1974

Merged
merged 2 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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