Coverage for src / lexigram / contracts / core / lifecycle.py: 0%

21 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-15 18:57 +0800

1"""Lifecycle protocols for Lexigram Framework. 

2 

3These protocols allow providers and services to hook into framework 

4lifecycle events such as initialization and shutdown. 

5""" 

6 

7from __future__ import annotations 

8 

9from typing import Any, Protocol, runtime_checkable 

10 

11 

12@runtime_checkable 

13class OnModuleInitProtocol(Protocol): 

14 """Provider implements this to run initialization logic. 

15 

16 Called once when the provider is first booted, BEFORE other providers 

17 that depend on it. 

18 

19 Behavioral Contract: 

20 - Implementers MUST be idempotent — calling ``on_module_init()`` 

21 twice MUST NOT produce side effects or raise. 

22 - Implementers SHOULD complete quickly — blocking here delays 

23 the entire boot sequence. 

24 - Implementers MUST NOT resolve services from other providers 

25 that have not yet been booted. 

26 """ 

27 

28 async def on_module_init(self) -> None: 

29 """Initialize provider after registration but before other providers boot.""" 

30 ... 

31 

32 

33@runtime_checkable 

34class OnApplicationBootstrapProtocol(Protocol): 

35 """Provider implements this to run after application bootstrap. 

36 

37 Called after ALL providers have been booted successfully. 

38 At this point every service is fully resolved and available. 

39 

40 Behavioral Contract: 

41 - Implementers MUST NOT throw exceptions — doing so indicates 

42 a fatal application startup failure. 

43 - Implementers CAN resolve any service from the container. 

44 - Implementers SHOULD start background tasks, schedulers, or 

45 listeners here rather than in ``on_module_init()``. 

46 """ 

47 

48 async def on_application_bootstrap(self) -> None: 

49 """Run after all providers are booted.""" 

50 ... 

51 

52 

53@runtime_checkable 

54class OnBeforeShutdownProtocol(Protocol): 

55 """Provider implements this to run before shutdown begins. 

56 

57 Called before any provider's ``shutdown()`` method is invoked. 

58 Use this to drain queues, finish in-flight requests, or save state. 

59 

60 Behavioral Contract: 

61 - Implementers MUST complete within a reasonable timeout. 

62 - Implementers SHOULD NOT start new work — only finish existing work. 

63 - Implementers MUST NOT throw exceptions. 

64 """ 

65 

66 async def on_before_shutdown(self, signal: str | None = None) -> None: 

67 """Run before shutdown begins.""" 

68 ... 

69 

70 

71@runtime_checkable 

72class OnApplicationShutdownProtocol(Protocol): 

73 """Provider implements this to run after shutdown completes. 

74 

75 Called after ALL providers have been shut down. 

76 Use this for final cleanup like closing log files or flushing metrics. 

77 

78 Behavioral Contract: 

79 - Implementers MUST NOT resolve services — the container is 

80 already disposed at this point. 

81 - Implementers MUST NOT throw exceptions. 

82 - Implementers SHOULD release any remaining OS resources. 

83 """ 

84 

85 async def on_application_shutdown(self, signal: str | None = None) -> None: 

86 """Run after all providers are shut down.""" 

87 ... 

88 

89 

90@runtime_checkable 

91class GracefulShutdownProtocol(Protocol): 

92 """Standard protocol for services that support graceful shutdown. 

93 

94 Any service that holds background tasks, open connections, or in-flight 

95 work SHOULD implement this protocol. The framework will call 

96 ``shutdown()`` on all registered services during teardown. 

97 

98 Behavioral Contract: 

99 - ``shutdown()`` MUST be idempotent — calling it twice is safe. 

100 - ``shutdown()`` SHOULD complete within a reasonable timeout. 

101 - ``shutdown()`` MUST NOT raise exceptions. 

102 - ``shutdown()`` SHOULD release all held resources (tasks, connections, 

103 file handles) before returning. 

104 """ 

105 

106 async def shutdown(self) -> None: 

107 """Request graceful shutdown and wait for completion.""" 

108 ... 

109 

110 

111@runtime_checkable 

112class OnConfigReloadProtocol(Protocol): 

113 """Lifecycle hook called when application configuration is reloaded at runtime. 

114 

115 Services that hold configuration-derived state (e.g., connection pools, 

116 caches, rate-limiters) SHOULD implement this protocol to react to live 

117 config changes without requiring a full restart. 

118 

119 Behavioral Contract: 

120 - ``on_config_reload`` MUST be idempotent. 

121 - ``on_config_reload`` SHOULD complete quickly; defer heavy work to a background task. 

122 - ``on_config_reload`` MUST NOT raise exceptions; log and absorb errors. 

123 

124 Example:: 

125 

126 class RedisCache(OnConfigReloadProtocol): 

127 async def on_config_reload(self, new_config: Any) -> None: 

128 self._ttl = new_config.cache.default_ttl 

129 """ 

130 

131 async def on_config_reload(self, new_config: Any) -> None: 

132 """React to a live configuration change. 

133 

134 Args: 

135 new_config: The new application configuration object. 

136 """ 

137 ... 

138 

139 

140__all__ = [ 

141 "GracefulShutdownProtocol", 

142 "OnApplicationBootstrapProtocol", 

143 "OnApplicationShutdownProtocol", 

144 "OnBeforeShutdownProtocol", 

145 "OnConfigReloadProtocol", 

146 "OnModuleInitProtocol", 

147]