Skip to content

Conversation

NFUChen
Copy link
Contributor

@NFUChen NFUChen commented Jul 21, 2025

Implement Graceful Shutdown Handler with Configurable Timeout

🚀 Overview

This PR introduces a comprehensive graceful shutdown handling system for PySpring applications, along with important structural improvements to the codebase. The implementation provides configurable timeout-based shutdown management with proper signal handling and cleanup procedures.

✨ Key Features

🛡️ Graceful Shutdown Handler

  • Signal Handling: Automatic handling of SIGINT (Ctrl+C) and SIGTERM signals
  • Configurable Timeout: Customizable shutdown timeout with automatic force-exit fallback
  • Shutdown Types: Support for different shutdown scenarios (Manual, SIGTERM, Timeout, Error)
  • Thread-Safe: Proper thread synchronization and duplicate signal prevention
  • Elapsed Time Tracking: Built-in monitoring of shutdown duration

⚙️ Configuration Management

  • ShutdownConfig: New configuration class for shutdown behavior
  • Application Integration: Seamless integration with existing application configuration
  • Template Updates: Updated configuration templates with default shutdown settings

🏗️ Code Structure Improvements

  • Module Organization: Reorganized core entities into proper directory structures
  • Import Cleanup: Updated all import statements to reflect new file organization
  • Framework Utils: New utility functions for abstract method validation

📁 Structural Changes

File Reorganization

py_spring_core/core/entities/
├── bean_collection/
│   └── bean_collection.py      # Previously: bean_collection.py
├── component/
│   └── component.py            # Previously: component.py
└── entity_provider/
    └── entity_provider.py      # Previously: entity_provider.py

New Files

  • py_spring_core/core/interfaces/graceful_shutdown_handler.py - Core shutdown handler interface
  • py_spring_core/core/utils.py - Framework utility functions
  • tests/test_application_config.py - Configuration testing
  • tests/test_graceful_shutdown_handler.py - Shutdown handler testing
  • tests/test_framework_utils.py - Utility function testing

🔧 Implementation Details

Graceful Shutdown Handler Interface

class GracefulShutdownHandler(SingleInheritanceRequired, ABC):
    def __init__(self, timeout_seconds: float, timeout_enabled: bool):
        # Signal registration and timer setup
    
    @abstractmethod
    def on_shutdown(self, shutdown_type: ShutdownType) -> None:
        """Handle shutdown initiation"""
    
    @abstractmethod
    def on_timeout(self) -> None:
        """Handle shutdown timeout"""
    
    @abstractmethod
    def on_error(self, error: Exception) -> None:
        """Handle shutdown errors"""

Configuration Schema

class ShutdownConfig(BaseModel):
    timeout_seconds: float = Field(default=30.0)
    enabled: bool = Field(default=True)

Application Integration

The shutdown handler is automatically:

  1. Discovered using the existing subclass registry pattern
  2. Validated for proper abstract method implementation
  3. Configured with application shutdown settings
  4. Initialized during application startup
  5. Cleaned up during application termination

🧪 Testing

Comprehensive test coverage includes:

  • Unit Tests: Individual component functionality
  • Integration Tests: End-to-end shutdown scenarios
  • Configuration Tests: Validation and serialization
  • Error Handling: Exception scenarios and edge cases
  • Signal Handling: Mock-based signal testing

🔄 Migration Guide

For Existing Applications

  1. Configuration: Add optional shutdown_config to application configuration
  2. Imports: Update any direct imports of reorganized modules
  3. Custom Handlers: Implement GracefulShutdownHandler if custom shutdown logic is needed

Example Usage

class MyShutdownHandler(GracefulShutdownHandler):
    def on_shutdown(self, shutdown_type: ShutdownType) -> None:
        logger.info(f"Graceful shutdown initiated: {shutdown_type}")
        # Custom cleanup logic here
    
    def on_timeout(self) -> None:
        logger.warning("Shutdown timeout reached")
    
    def on_error(self, error: Exception) -> None:
        logger.error(f"Shutdown error: {error}")

📊 Configuration Example

{
  "shutdown_config": {
    "timeout_seconds": 30.0,
    "enabled": true
  }
}

🛡️ Backward Compatibility

  • Full Compatibility: All existing functionality remains unchanged
  • Optional Feature: Graceful shutdown is optional and doesn't affect apps without custom handlers
  • Default Behavior: Sensible defaults ensure smooth operation without configuration changes
  • Import Updates: Automatic fallback for import compatibility

🚦 Testing Instructions

  1. Run Test Suite: python -m pytest tests/
  2. Manual Testing:
    • Start application and send SIGINT/SIGTERM
    • Verify timeout behavior with long-running operations
    • Test configuration changes and validation

📝 Related Issues

This implementation addresses requirements for:

  • Production-ready application lifecycle management
  • Container orchestration compatibility (Docker, Kubernetes)
  • Graceful resource cleanup and connection handling
  • Configurable shutdown behavior for different deployment scenarios

…component classes; add BeanCollection and Component classes with lifecycle management and error handling features.
- Introduced `GracefulShutdownHandler` interface for managing application shutdowns with support for manual, SIGTERM, timeout, and error scenarios.
- Updated `PySpringApplication` to initialize graceful shutdown handling during application startup.
- Refactored middleware initialization to utilize a common external handler initialization method for better code organization and error handling.
- Added unit tests for the `GracefulShutdownHandler` to ensure proper functionality across various shutdown scenarios.
- Updated the initialization of the handler in `PySpringApplication` to specify the type.
- Removed the `wait` method from `GracefulShutdownHandler` to streamline shutdown handling.
- Deleted the `test_graceful_shutdown.py` file as part of the cleanup process.
- Wrapped shutdown signal handling methods in try-except blocks to catch and handle exceptions gracefully.
- Ensured that errors during shutdown processing are reported via the on_error method.
…ndler to streamline the interface and improve code clarity.
- Introduced `ShutdownConfig` class to encapsulate graceful shutdown settings, including timeout and enabled status.
- Updated `ApplicationConfig` to include `shutdown_config` for managing shutdown behavior.
- Enhanced `GracefulShutdownHandler` to accept timeout parameters and manage shutdown timing.
- Modified `PySpringApplication` to utilize the new shutdown configuration during initialization and shutdown processes.
…int statements for SIGINT and SIGTERM signals
- Added checks in `_handle_sigint` and `_handle_sigterm` methods to ignore signals if a shutdown is already in progress, improving robustness and logging clarity.
- Introduced comprehensive test suites for `ApplicationConfig` and `ShutdownConfig` to validate default values, custom configurations, serialization, and type validation.
- Added tests for graceful shutdown handler functionality, including signal handling, timeout behavior, and error management.
- Ensured coverage for various scenarios to enhance reliability and maintainability of the shutdown handling logic.
@NFUChen NFUChen changed the title Refactor imports to use new module structure for bean collection and … Implement Graceful Shutdown Handler with Configurable Timeout Jul 21, 2025
@NFUChen NFUChen merged commit 070d556 into main Jul 21, 2025
1 check passed
@NFUChen NFUChen deleted the feat/graceful-shutdown-handler branch July 21, 2025 07:56
@NFUChen NFUChen restored the feat/graceful-shutdown-handler branch July 21, 2025 07:56
@NFUChen NFUChen deleted the feat/graceful-shutdown-handler branch July 21, 2025 07:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants