Cat Feeder  1.0.0
The Cat feeder project
Loading...
Searching...
No Matches
runtime_controls.py
Go to the documentation of this file.
1r"""
2# +==== BEGIN CatFeeder =================+
3# LOGO:
4# ..............(..../\
5# ...............)..(.')
6# ..............(../..)
7# ...............\‍(__)|
8# Inspired by Joan Stark
9# source https://www.asciiart.eu/
10# animals/cats
11# /STOP
12# PROJECT: CatFeeder
13# FILE: runtime_controls.py
14# CREATION DATE: 24-11-2025
15# LAST Modified: 14:43:8 19-12-2025
16# DESCRIPTION:
17# This is the backend server in charge of making the actual website work.
18# /STOP
19# COPYRIGHT: (c) Cat Feeder
20# PURPOSE: Class in charge of tracking variables and some functions that aim to control the state of the server (this includes being able to stop it)
21# // AR
22# +==== END CatFeeder =================+
23"""
24
25import signal
26from types import FrameType
27from typing import Optional, TYPE_CHECKING
28from display_tty import Disp, initialise_logger
29from .final_singleton_class import FinalSingleton
30
31if TYPE_CHECKING:
32 from fastapi import FastAPI
33 from uvicorn import Config as UConfig, Server as UServer
34
35
37 """Runtime control manager for server state and lifecycle.
38
39 This singleton class manages the server's runtime state, including the FastAPI application,
40 uvicorn server instance, and server lifecycle flags. It provides methods for graceful
41 shutdown and signal handling.
42
43 Attributes:
44 disp (Disp): Logger instance for this class.
45 app (Optional[FastAPI]): The FastAPI application instance.
46 config (Optional[uvicorn.Config]): The uvicorn server configuration.
47 server (Optional[uvicorn.Server]): The uvicorn server instance.
48 server_running (bool): Flag indicating if the server is currently running.
49 continue_running (bool): Flag indicating if the server should continue running.
50 """
51 disp: Disp = initialise_logger(__qualname__, False)
52
53 def __init__(self, debug: bool = False) -> None:
54 """Initialize the RuntimeControl singleton.
55
56 Args:
57 debug (bool, optional): Enable debug logging. Defaults to False.
58 """
59 super().__init__()
60 # ------------------------ The logging function ------------------------
61 self.disp.update_disp_debug(debug)
62 self.disp.log_debug("Initialising...")
63 # -------------------------- Inherited values --------------------------
64 self._debug = debug
65 # --------------------- The rest api boiling class ---------------------
66 self.app: Optional["FastAPI"] = None
67 # ------------------------- The uvicorn server classes -------------------------
68 self.config: Optional["UConfig"] = None
69 self.serverserver: Optional["UServer"] = None
70 # ------------------------- The server Status -------------------------
71 self.server_running: bool = True
72 self.continue_running: bool = True
73 # --------------------- The rest api boiling class ---------------------
74 self.disp.log_debug("Initialised")
75
76 def handle_exit(self, sig: int = signal.SIGTERM, frame: Optional[FrameType] = None) -> None:
77 """Handle system exit signals by delegating to uvicorn's signal handler.
78
79 This method captures signals (SIGTERM, SIGINT, etc.) and passes them to uvicorn's
80 built-in signal handler. Note that uvicorn will re-raise captured signals after
81 shutdown, which may prevent cleanup code from executing. For graceful shutdown
82 without signal handling, use graceful_shutdown() instead.
83
84 Args:
85 sig (int, optional): The signal number to handle. Defaults to signal.SIGTERM.
86 frame (Optional[FrameType], optional): The current stack frame. Defaults to None.
87 """
88 if self.serverserver:
89 self.serverserver.handle_exit(sig, frame)
90
91 def graceful_shutdown(self) -> None:
92 """Trigger a graceful server shutdown without signal handling.
93
94 This method triggers uvicorn's graceful shutdown by setting the should_exit flag
95 directly, avoiding signal capture and re-raising that would kill the process.
96 This allows cleanup code in finally blocks to execute properly. Preferred over
97 handle_exit() when shutdown is initiated programmatically (e.g., from an API endpoint).
98
99 The method:
100 1. Sets server_running and continue_running flags to False
101 2. Sets uvicorn's should_exit flag to trigger graceful shutdown
102 3. Logs debug messages for tracking shutdown progress
103
104 Note:
105 If no server instance exists, logs a warning and only updates the flags.
106 """
107 self.disp.log_debug("Triggering graceful shutdown...")
108 self.server_running = False
109 self.continue_running = False
111 self.serverserver.should_exit = True
112 self.disp.log_debug("Uvicorn shutdown flag set")
113 else:
114 self.disp.log_warning("No server instance to shutdown")
None handle_exit(self, int sig=signal.SIGTERM, Optional[FrameType] frame=None)