11import logging
22import os
3- from typing import Any , Callable , Iterable , Type
3+ from typing import Any , Callable , Iterable , Optional , Type
44
55import uvicorn
66from fastapi import APIRouter , FastAPI
2323 ApplicationContextConfig ,
2424)
2525from 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
2828from py_spring_core .core .entities .controllers .rest_controller import RestController
2929from 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
3132from py_spring_core .core .entities .middlewares .middleware_registry import (
3233 MiddlewareRegistry ,
3334)
3435from py_spring_core .core .entities .properties .properties import Properties
3536from py_spring_core .core .interfaces .application_context_required import (
3637 ApplicationContextRequired ,
3738)
39+ from py_spring_core .core .interfaces .graceful_shutdown_handler import GracefulShutdownHandler
40+ from py_spring_core .core .interfaces .single_inheritance_required import SingleInheritanceRequired
3841from py_spring_core .event .application_event_handler_registry import (
3942 ApplicationEventHandlerRegistry ,
4043)
4144from py_spring_core .event .application_event_publisher import ApplicationEventPublisher
4245
46+ import py_spring_core .core .utils as framework_utils
4347
4448class PySpringApplication :
4549 """
@@ -102,6 +106,7 @@ def __init__(
102106 self .type_checking_service = TypeCheckingService (
103107 self .app_config .app_src_target_dir
104108 )
109+ self .shutdown_handler : Optional [GracefulShutdownHandler ] = None
105110
106111 def __configure_logging (self ):
107112 """Applies the logging configuration using Loguru."""
@@ -232,31 +237,76 @@ def __init_controllers(self) -> None:
232237 self .fastapi .include_router (router )
233238 logger .debug (f"[CONTROLLER INIT] Controller { name } initialized" )
234239
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+
241265 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__ } "
243267 )
244268 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__ } "
246270 )
247271 self .app_context .inject_dependencies_for_external_object (
248- self_defined_registry_cls
272+ self_defined_handler_cls
249273 )
250- registry = self_defined_registry_cls ()
274+ return self_defined_handler_cls
251275
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 ()
253285 for middleware_class in middleware_classes :
254286 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__ } "
256288 )
257289 self .app_context .inject_dependencies_for_external_object (middleware_class )
258290 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" )
260310
261311 def __configure_uvicorn_logging (self ):
262312 """Configure Uvicorn to use Loguru instead of default logging."""
@@ -300,7 +350,14 @@ def run(self) -> None:
300350 self .__init_app ()
301351 self .__init_controllers ()
302352 self .__init_middlewares ()
353+ self .__init_graceful_shutdown ()
303354 if self .app_config .server_config .enabled :
304355 self .__run_server ()
305356 finally :
357+ # Handle component lifecycle destruction
306358 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