7
7
from asgi_lifespan import LifespanManager
8
8
from celery import Celery # type: ignore[import-untyped]
9
9
from fastapi import FastAPI
10
- from servicelib .async_utils import cancel_wait_task
10
+ from servicelib .logging_utils import log_context
11
11
12
12
from ...core .application import create_app
13
13
from ...core .settings import ApplicationSettings
14
- from ...modules .celery import get_event_loop , set_event_loop
14
+ from ...modules .celery import set_event_loop
15
15
from ...modules .celery .utils import (
16
16
get_fastapi_app ,
17
17
set_celery_worker ,
21
21
22
22
_logger = logging .getLogger (__name__ )
23
23
24
- _LIFESPAN_TIMEOUT : Final [int ] = 10
25
- _FASTAPI_STARTUP_TIMEOUT : Final [float ] = datetime .timedelta (minutes = 1 ).total_seconds ()
24
+ _SHUTDOWN_TIMEOUT : Final [float ] = datetime . timedelta ( seconds = 10 ). total_seconds ()
25
+ _STARTUP_TIMEOUT : Final [float ] = datetime .timedelta (minutes = 1 ).total_seconds ()
26
26
27
27
28
28
def on_worker_init (sender , ** _kwargs ) -> None :
@@ -35,11 +35,13 @@ def _init_fastapi(startup_complete_event: threading.Event) -> None:
35
35
36
36
fastapi_app = create_app (ApplicationSettings .create_from_envs ())
37
37
38
- async def lifespan (startup_complete_event : threading .Event ) -> None :
38
+ async def lifespan (
39
+ startup_complete_event : threading .Event , shutdown_event : asyncio .Event
40
+ ) -> None :
39
41
async with LifespanManager (
40
42
fastapi_app ,
41
- startup_timeout = _LIFESPAN_TIMEOUT ,
42
- shutdown_timeout = _LIFESPAN_TIMEOUT ,
43
+ startup_timeout = _STARTUP_TIMEOUT ,
44
+ shutdown_timeout = _SHUTDOWN_TIMEOUT ,
43
45
):
44
46
try :
45
47
_logger .info ("fastapi APP started!" )
@@ -48,37 +50,27 @@ async def lifespan(startup_complete_event: threading.Event) -> None:
48
50
except asyncio .CancelledError :
49
51
_logger .warning ("Lifespan task cancelled" )
50
52
51
- lifespan_task = loop .create_task (lifespan (startup_complete_event ))
52
- fastapi_app .state .lifespan_task = lifespan_task
53
53
fastapi_app .state .shutdown_event = shutdown_event
54
54
set_event_loop (fastapi_app , loop )
55
55
56
56
set_fastapi_app (sender .app , fastapi_app )
57
57
set_celery_worker (sender .app , CeleryTaskQueueWorker (sender .app ))
58
-
59
- loop .run_forever ()
58
+ loop .run_until_complete (lifespan (startup_complete_event , shutdown_event ))
60
59
61
60
thread = threading .Thread (
61
+ group = None ,
62
62
target = _init_fastapi ,
63
63
name = "fastapi_app" ,
64
64
args = (startup_complete_event ,),
65
- daemon = True ,
66
65
)
67
66
thread .start ()
68
67
# ensure the fastapi app is ready before going on
69
- startup_complete_event .wait (_FASTAPI_STARTUP_TIMEOUT )
70
-
71
-
72
- def on_worker_shutdown (sender , ** _kwargs ):
73
- assert isinstance (sender .app , Celery )
68
+ startup_complete_event .wait (_STARTUP_TIMEOUT * 1.1 )
74
69
75
- fastapi_app = get_fastapi_app (sender .app )
76
- assert isinstance (fastapi_app , FastAPI )
77
- event_loop = get_event_loop (fastapi_app )
78
70
79
- async def shutdown ():
71
+ def on_worker_shutdown (sender , ** _kwargs ) -> None :
72
+ with log_context (_logger , logging .INFO , "Worker Shuts-down" ):
73
+ assert isinstance (sender .app , Celery )
74
+ fastapi_app = get_fastapi_app (sender .app )
75
+ assert isinstance (fastapi_app , FastAPI )
80
76
fastapi_app .state .shutdown_event .set ()
81
-
82
- await cancel_wait_task (fastapi_app .state .lifespan_task , max_delay = 5 )
83
-
84
- asyncio .run_coroutine_threadsafe (shutdown (), event_loop )
0 commit comments