1
1
import logging
2
2
import os
3
- from typing import Any , Callable , Iterable , Type
3
+ from typing import Any , Callable , Iterable , Optional , Type
4
4
5
5
import uvicorn
6
6
from fastapi import APIRouter , FastAPI
23
23
ApplicationContextConfig ,
24
24
)
25
25
from py_spring_core .core .application .loguru_config import LogFormat
26
- from py_spring_core .core .entities .bean_collection import BeanCollection
27
- from py_spring_core .core .entities .component import Component , ComponentLifeCycle
26
+ from py_spring_core .core .entities .bean_collection . bean_collection import BeanCollection
27
+ from py_spring_core .core .entities .component . component import Component , ComponentLifeCycle
28
28
from py_spring_core .core .entities .controllers .rest_controller import RestController
29
29
from py_spring_core .core .entities .controllers .route_mapping import RouteMapping
30
- from py_spring_core .core .entities .entity_provider import EntityProvider
30
+ from py_spring_core .core .entities .entity_provider .entity_provider import EntityProvider
31
+ from py_spring_core .core .entities .middlewares .middleware import Middleware
31
32
from py_spring_core .core .entities .middlewares .middleware_registry import (
32
33
MiddlewareRegistry ,
33
34
)
34
35
from py_spring_core .core .entities .properties .properties import Properties
35
36
from py_spring_core .core .interfaces .application_context_required import (
36
37
ApplicationContextRequired ,
37
38
)
39
+ from py_spring_core .core .interfaces .graceful_shutdown_handler import GracefulShutdownHandler
40
+ from py_spring_core .core .interfaces .single_inheritance_required import SingleInheritanceRequired
38
41
from py_spring_core .event .application_event_handler_registry import (
39
42
ApplicationEventHandlerRegistry ,
40
43
)
41
44
from py_spring_core .event .application_event_publisher import ApplicationEventPublisher
42
45
46
+ import py_spring_core .core .utils as framework_utils
43
47
44
48
class PySpringApplication :
45
49
"""
@@ -102,6 +106,7 @@ def __init__(
102
106
self .type_checking_service = TypeCheckingService (
103
107
self .app_config .app_src_target_dir
104
108
)
109
+ self .shutdown_handler : Optional [GracefulShutdownHandler ] = None
105
110
106
111
def __configure_logging (self ):
107
112
"""Applies the logging configuration using Loguru."""
@@ -232,31 +237,76 @@ def __init_controllers(self) -> None:
232
237
self .fastapi .include_router (router )
233
238
logger .debug (f"[CONTROLLER INIT] Controller { name } initialized" )
234
239
235
- def __init_middlewares (self ) -> None :
236
- logger .debug ("[MIDDLEWARE INIT] Initialize middlewares..." )
237
- self_defined_registry_cls = MiddlewareRegistry .get_subclass ()
238
- if self_defined_registry_cls is None :
239
- logger .debug ("[MIDDLEWARE INIT] No self defined registry class found" )
240
- return
240
+ def _init_external_handler (self , base_class : Type [SingleInheritanceRequired ]) -> Type [Any ] | None :
241
+ """Initialize an external handler (middleware registry or graceful shutdown handler).
242
+
243
+ Args:
244
+ base_class: The base class to get subclass from
245
+ handler_type: The type of handler for logging purposes
246
+
247
+ Returns:
248
+ The initialized handler class or None if no handler is found
249
+
250
+ Raises:
251
+ RuntimeError: If the handler has unimplemented abstract methods
252
+ """
253
+ handler_type = base_class .__name__
254
+ self_defined_handler_cls = base_class .get_subclass ()
255
+ if self_defined_handler_cls is None :
256
+ logger .debug (f"[{ handler_type } INIT] No self defined { handler_type .lower ()} class found" )
257
+ return None
258
+
259
+ unimplemented_abstract_methods = framework_utils .get_unimplemented_abstract_methods (self_defined_handler_cls )
260
+ if len (unimplemented_abstract_methods ) > 0 :
261
+ error_message = f"[{ handler_type } INIT] Self defined { handler_type .lower ()} class: { self_defined_handler_cls .__name__ } has unimplemented abstract methods: { unimplemented_abstract_methods } "
262
+ logger .error (error_message )
263
+ raise RuntimeError (error_message )
264
+
241
265
logger .debug (
242
- f"[MIDDLEWARE INIT] Self defined registry class: { self_defined_registry_cls .__name__ } "
266
+ f"[{ handler_type } INIT] Self defined { handler_type . lower () } class: { self_defined_handler_cls .__name__ } "
243
267
)
244
268
logger .debug (
245
- f"[MIDDLEWARE INIT] Inject dependencies for external object: { self_defined_registry_cls .__name__ } "
269
+ f"[{ handler_type } INIT] Inject dependencies for external object: { self_defined_handler_cls .__name__ } "
246
270
)
247
271
self .app_context .inject_dependencies_for_external_object (
248
- self_defined_registry_cls
272
+ self_defined_handler_cls
249
273
)
250
- registry = self_defined_registry_cls ()
274
+ return self_defined_handler_cls
251
275
252
- middleware_classes = registry .get_middleware_classes ()
276
+ def __init_middlewares (self ) -> None :
277
+ handler_type = MiddlewareRegistry .__name__
278
+ logger .debug (f"[{ handler_type } INIT] Initialize middlewares..." )
279
+ registry_cls = self ._init_external_handler (MiddlewareRegistry )
280
+ if registry_cls is None :
281
+ return
282
+
283
+ registry : MiddlewareRegistry = registry_cls ()
284
+ middleware_classes : list [Type [Middleware ]] = registry .get_middleware_classes ()
253
285
for middleware_class in middleware_classes :
254
286
logger .debug (
255
- f"[MIDDLEWARE INIT] Inject dependencies for middleware: { middleware_class .__name__ } "
287
+ f"[{ handler_type } INIT] Inject dependencies for middleware: { middleware_class .__name__ } "
256
288
)
257
289
self .app_context .inject_dependencies_for_external_object (middleware_class )
258
290
registry .apply_middlewares (self .fastapi )
259
- logger .debug ("[MIDDLEWARE INIT] Middlewares initialized" )
291
+ logger .debug (f"[{ handler_type } INIT] Middlewares initialized" )
292
+
293
+ def __init_graceful_shutdown (self ) -> None :
294
+ handler_type = GracefulShutdownHandler .__name__
295
+ logger .debug (f"[{ handler_type } INIT] Initialize graceful shutdown..." )
296
+ handler_cls : Optional [Type [GracefulShutdownHandler ]] = self ._init_external_handler (GracefulShutdownHandler )
297
+ if handler_cls is None :
298
+ return
299
+
300
+ # Get shutdown configuration
301
+ shutdown_config = self .app_config .shutdown_config
302
+ logger .debug (f"[{ handler_type } INIT] Shutdown timeout: { shutdown_config .timeout_seconds } s, enabled: { shutdown_config .enabled } " )
303
+
304
+ # Initialize handler with timeout configuration
305
+ self .shutdown_handler = handler_cls (
306
+ timeout_seconds = shutdown_config .timeout_seconds ,
307
+ timeout_enabled = shutdown_config .enabled
308
+ )
309
+ logger .debug (f"[{ handler_type } INIT] Graceful shutdown initialized" )
260
310
261
311
def __configure_uvicorn_logging (self ):
262
312
"""Configure Uvicorn to use Loguru instead of default logging."""
@@ -300,7 +350,14 @@ def run(self) -> None:
300
350
self .__init_app ()
301
351
self .__init_controllers ()
302
352
self .__init_middlewares ()
353
+ self .__init_graceful_shutdown ()
303
354
if self .app_config .server_config .enabled :
304
355
self .__run_server ()
305
356
finally :
357
+ # Handle component lifecycle destruction
306
358
self ._handle_singleton_components_life_cycle (ComponentLifeCycle .Destruction )
359
+ # Handle graceful shutdown completion
360
+ if self .shutdown_handler :
361
+ self .shutdown_handler .complete_shutdown ()
362
+
363
+
0 commit comments