Core Module
Overview
The core module provides the foundational design patterns for the Cat Feeder backend architecture. It implements a Service Locator Pattern combined with a Protected Singleton Pattern to enable centralized, thread-safe service management.
Location: backend/src/libs/core/
Key Files:
Purpose
- Centralized Service Management: Single point of access for all backend services
- Lazy Initialization: Services created only when first requested
- Thread Safety: Synchronized access across multiple request handlers
- Lifecycle Control: Coordinated startup, access, and shutdown
- Singleton Enforcement: Prevent accidental multiple instantiations
Architecture
RuntimeManager: Service Locator
Overview
RuntimeManager acts as a service container providing:
- Named service registration
- Lazy instantiation with caching
- Constructor argument forwarding
- Thread-safe access
API
from core import RuntimeManager
from sql import SQL
RuntimeManager.set(SQL, database_url="postgresql://...")
sql = RuntimeManager.get(SQL)
if RuntimeManager.exists(SQL):
sql = RuntimeManager.get(SQL)
services = RuntimeManager.get_all_instances()
RuntimeManager.clear()
Initialization Sequence
Thread Safety
The RuntimeManager uses a lock-per-service strategy:
_thread_locks: Dict[str, threading.Lock] = {}
- Read operations (
exists, cached get): Lock-free, O(1)
- Write operations (
set, first get): Synchronized with lock
- No global lock: Multiple services can initialize concurrently
Error Handling
try:
sql = RuntimeManager.get(SQL, url="invalid://")
except ConnectionError:
pass
sql = RuntimeManager.get(SQL, url="valid://")
FinalSingleton: Protected Construction
Overview
FinalSingleton is a base class that prevents direct instantiation:
class MyService(FinalSingleton):
def __init__(self, config: str):
self.config = config
async def async_init(self):
await self.connect()
service = MyService("config")
RuntimeManager.set(MyService, "config")
service = RuntimeManager.get(MyService)
Mechanism
class FinalSingleton:
_instances: Dict[type, Self] = {}
_lock: threading.RLock = threading.RLock()
def __new__(cls, *args, **kwargs):
frame = inspect.currentframe()
caller = frame.f_back.f_code.co_name
if caller not in {"set", "get", "_create_instance"}:
raise RuntimeError(
f"{cls.__name__} must be created through RuntimeManager"
)
with cls._lock:
if cls not in cls._instances:
instance = super().__new__(cls)
cls._instances[cls] = instance
return cls._instances[cls]
Async Initialization
Services requiring async setup implement async_init():
class SQL(FinalSingleton):
def __init__(self, database_url: str):
self.url = database_url
self.engine = None
async def async_init(self):
"""Called automatically by RuntimeManager after construction."""
self.engine = create_async_engine(self.url)
await self.engine.connect()
RuntimeManager.get() automatically calls async_init() if defined:
instance = cls(*args, **kwargs)
if hasattr(instance, "async_init"):
await instance.async_init()
RuntimeControl: Shutdown Coordination
Overview
RuntimeControl provides a global shutdown signal that all services can observe:
from core import RuntimeControl
RuntimeControl.signal_shutdown()
if RuntimeControl.is_shutting_down():
return
RuntimeControl.wait_for_shutdown(timeout=30)
Shutdown Sequence
Implementation
class RuntimeControl:
_shutdown_event: threading.Event = threading.Event()
_lock: threading.Lock = threading.Lock()
@classmethod
def signal_shutdown(cls) -> None:
"""Signal all services to shut down."""
with cls._lock:
cls._shutdown_event.set()
@classmethod
def is_shutting_down(cls) -> bool:
"""Check if shutdown has been signaled."""
return cls._shutdown_event.is_set()
@classmethod
def wait_for_shutdown(cls, timeout: Optional[float] = None) -> bool:
"""Block until shutdown signaled or timeout."""
return cls._shutdown_event.wait(timeout)
Usage in Services
class BackgroundWorker(FinalSingleton):
async def run_loop(self):
while not RuntimeControl.is_shutting_down():
await self.process_task()
await asyncio.sleep(1)
await self.cleanup()
FinalClass: Inheritance Prevention
Overview
FinalClass is a metaclass that prevents inheritance from classes using it:
from core import FinalClass
class CannotInherit(metaclass=FinalClass):
pass
class Derived(CannotInherit):
pass
Use Cases
Applied to classes that should never be subclassed:
- Configuration containers
- Utility classes with static methods
- Classes with security-critical behavior
Design Patterns
1. Service Locator Pattern
Intent: Centralize service creation and access
Implementation: RuntimeManager
Benefits:
- Decouples service consumers from construction
- Enables lazy initialization
- Simplifies dependency management
- Facilitates testing (mock services)
Example:
RuntimeManager.set(SQL, database_url)
RuntimeManager.set(Redis, redis_url)
RuntimeManager.set(Bucket, s3_config)
sql = RuntimeManager.get(SQL)
users = await sql.query("SELECT * FROM users")
2. Protected Singleton Pattern
Intent: Enforce single instance through controlled creation
Implementation: FinalSingleton
Benefits:
- Prevents accidental multiple instances
- Centralizes lifecycle management
- Thread-safe by design
- Clear intent (cannot be instantiated directly)
Example:
class DatabaseConnection(FinalSingleton):
def __init__(self, url: str):
self.url = url
def query(self, sql: str):
return self.engine.execute(sql)
db = RuntimeManager.get(DatabaseConnection, "postgresql://...")
3. Observer Pattern (Shutdown)
Intent: Notify all services of shutdown
Implementation: RuntimeControl
Benefits:
- Coordinated shutdown
- No tight coupling
- Services can cleanup resources
- Background tasks can terminate gracefully
Performance Characteristics
| Operation | Time Complexity | Thread Safety |
RuntimeManager.set() | O(1) | ✅ Locked |
RuntimeManager.get() (cached) | O(1) | ✅ Lock-free |
RuntimeManager.get() (first) | O(1) + init | ✅ Locked |
RuntimeManager.exists() | O(1) | ✅ Lock-free |
RuntimeControl.signal_shutdown() | O(1) | ✅ Locked |
RuntimeControl.is_shutting_down() | O(1) | ✅ Lock-free |
Memory: O(n) where n = number of registered services
Testing Strategies
Mocking Services
import unittest
from core import RuntimeManager
class MockSQL(FinalSingleton):
def __init__(self):
self.data = {"users": []}
def query(self, sql: str):
return self.data["users"]
class TestEndpoint(unittest.TestCase):
def setUp(self):
RuntimeManager.set(SQL, MockSQL())
def tearDown(self):
RuntimeManager.clear()
def test_get_users(self):
sql = RuntimeManager.get(SQL)
users = sql.query("SELECT * FROM users")
self.assertEqual(users, [])
Testing Lazy Initialization
def test_lazy_creation():
assert not RuntimeManager.exists(MyService)
svc1 = RuntimeManager.get(MyService, arg="value")
assert RuntimeManager.exists(MyService)
svc2 = RuntimeManager.get(MyService)
assert svc1 is svc2
Testing Shutdown
async def test_graceful_shutdown():
worker = RuntimeManager.get(BackgroundWorker)
task = asyncio.create_task(worker.run_loop())
RuntimeControl.signal_shutdown()
await asyncio.wait_for(task, timeout=5)
assert worker.is_cleaned_up
Common Patterns
Conditional Initialization
if not RuntimeManager.exists(CacheService):
RuntimeManager.set(CacheService, cache_url)
Service Dependencies
class EndpointManager(FinalSingleton):
def __init__(self, app: FastAPI):
self.app = app
async def async_init(self):
self.path_manager = RuntimeManager.get(PathManager)
await self.register_routes()
Cleanup on Shutdown
class DatabasePool(FinalSingleton):
async def async_init(self):
self.pool = await create_pool()
def shutdown(self):
"""Called during server shutdown."""
if RuntimeControl.is_shutting_down():
self.pool.close()
Best Practices
✅ DO
- Register all services during server initialization
- Use
RuntimeManager.get() for lazy retrieval
- Implement
async_init() for async setup
- Implement
shutdown() for cleanup
- Use
RuntimeControl.is_shutting_down() in loops
❌ DON'T
- Don't instantiate
FinalSingleton subclasses directly
- Don't call
RuntimeManager.set() after server starts
- Don't store service references globally (use RuntimeManager)
- Don't forget to implement
shutdown() for resource cleanup
- Don't create circular dependencies between services
Dependencies
This module depends on:
display_tty (logging)
threading (standard library)
asyncio (standard library)
inspect (standard library)
Used by:
Related Documentation