springbootAI 1.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. spring/__init__.py +66 -0
  2. spring/ai/__init__.py +78 -0
  3. spring/ai/advisors.py +139 -0
  4. spring/ai/annotations.py +74 -0
  5. spring/ai/autoconfig.py +481 -0
  6. spring/ai/core.py +391 -0
  7. spring/ai/etl.py +188 -0
  8. spring/ai/memory.py +109 -0
  9. spring/ai/observability.py +129 -0
  10. spring/ai/providers.py +789 -0
  11. spring/ai/resilience.py +258 -0
  12. spring/ai/tools.py +106 -0
  13. spring/ai/vectorstore.py +303 -0
  14. spring/annotations/__init__.py +188 -0
  15. spring/annotations/cache.py +126 -0
  16. spring/annotations/cloud.py +207 -0
  17. spring/annotations/conditional.py +272 -0
  18. spring/annotations/core.py +864 -0
  19. spring/annotations/messaging.py +107 -0
  20. spring/aop/__init__.py +4 -0
  21. spring/aop/cloud_aop.py +404 -0
  22. spring/aop/comprehensive_aop.py +1015 -0
  23. spring/aop/method_interceptor.py +19 -0
  24. spring/aop/proxy_factory.py +55 -0
  25. spring/cloud/__init__.py +76 -0
  26. spring/cloud/discovery.py +364 -0
  27. spring/cloud/feign.py +469 -0
  28. spring/cloud/gateway.py +452 -0
  29. spring/cloud/load_balancer.py +149 -0
  30. spring/cloud/seata.py +557 -0
  31. spring/cloud/sentinel.py +525 -0
  32. spring/cloud/tracer.py +337 -0
  33. spring/config/__init__.py +21 -0
  34. spring/config/binding.py +206 -0
  35. spring/config/config_loader.py +405 -0
  36. spring/context/__init__.py +13 -0
  37. spring/context/application_context.py +589 -0
  38. spring/context/bean_definition.py +70 -0
  39. spring/context/bean_factory.py +1052 -0
  40. spring/context/registry.py +58 -0
  41. spring/context/scanner.py +106 -0
  42. spring/core/__init__.py +3 -0
  43. spring/core/graceful_shutdown.py +196 -0
  44. spring/core/typing_utils.py +50 -0
  45. spring/csv/__init__.py +52 -0
  46. spring/csv/annotations.py +402 -0
  47. spring/csv/converters.py +69 -0
  48. spring/csv/easy_csv.py +95 -0
  49. spring/csv/exceptions.py +27 -0
  50. spring/csv/reader.py +195 -0
  51. spring/csv/writer.py +155 -0
  52. spring/data/__init__.py +54 -0
  53. spring/data/page.py +181 -0
  54. spring/data/repository.py +274 -0
  55. spring/data/specification.py +228 -0
  56. spring/datasource/__init__.py +66 -0
  57. spring/datasource/annotations.py +133 -0
  58. spring/datasource/context.py +69 -0
  59. spring/datasource/dynamic.py +148 -0
  60. spring/event/__init__.py +7 -0
  61. spring/event/publisher.py +69 -0
  62. spring/excel/__init__.py +51 -0
  63. spring/excel/annotations.py +405 -0
  64. spring/excel/converters.py +231 -0
  65. spring/excel/easy_excel.py +94 -0
  66. spring/excel/exceptions.py +31 -0
  67. spring/excel/reader.py +254 -0
  68. spring/excel/style.py +95 -0
  69. spring/excel/writer.py +197 -0
  70. spring/i18n/__init__.py +97 -0
  71. spring/i18n/accessor.py +94 -0
  72. spring/i18n/auto_config.py +177 -0
  73. spring/i18n/holder.py +106 -0
  74. spring/i18n/locale.py +152 -0
  75. spring/i18n/locale_resolver.py +367 -0
  76. spring/i18n/message_source.py +250 -0
  77. spring/i18n/middleware.py +79 -0
  78. spring/i18n/properties.py +168 -0
  79. spring/i18n/sources.py +255 -0
  80. spring/logging/__init__.py +1 -0
  81. spring/logging/loguru_logger.py +228 -0
  82. spring/main.py +378 -0
  83. spring/messaging/__init__.py +1 -0
  84. spring/messaging/rabbitmq.py +302 -0
  85. spring/monitoring/__init__.py +1 -0
  86. spring/monitoring/prometheus.py +199 -0
  87. spring/orm/__init__.py +258 -0
  88. spring/orm/database.py +222 -0
  89. spring/orm/ddl_auto.py +1217 -0
  90. spring/orm/migration.py +419 -0
  91. spring/orm/mybatis_integration.py +400 -0
  92. spring/orm/pymybatis/__init__.py +86 -0
  93. spring/orm/pymybatis/annotations/__init__.py +30 -0
  94. spring/orm/pymybatis/annotations/annotations.py +332 -0
  95. spring/orm/pymybatis/cache/__init__.py +47 -0
  96. spring/orm/pymybatis/cache/cache.py +371 -0
  97. spring/orm/pymybatis/cache/redis_cache.py +434 -0
  98. spring/orm/pymybatis/circuit_breaker/__init__.py +21 -0
  99. spring/orm/pymybatis/circuit_breaker/circuit_breaker.py +424 -0
  100. spring/orm/pymybatis/configuration.py +525 -0
  101. spring/orm/pymybatis/core/__init__.py +10 -0
  102. spring/orm/pymybatis/core/sql_session.py +1382 -0
  103. spring/orm/pymybatis/core/sql_session_factory.py +76 -0
  104. spring/orm/pymybatis/dialect/__init__.py +9 -0
  105. spring/orm/pymybatis/dialect/dialect.py +445 -0
  106. spring/orm/pymybatis/dynamic_sql/__init__.py +9 -0
  107. spring/orm/pymybatis/dynamic_sql/dynamic_sql.py +900 -0
  108. spring/orm/pymybatis/interceptor/__init__.py +31 -0
  109. spring/orm/pymybatis/interceptor/interceptor.py +427 -0
  110. spring/orm/pymybatis/mapper/__init__.py +9 -0
  111. spring/orm/pymybatis/mapper/mapper.py +540 -0
  112. spring/orm/pymybatis/metrics/__init__.py +41 -0
  113. spring/orm/pymybatis/metrics/metrics.py +595 -0
  114. spring/orm/pymybatis/pool/__init__.py +9 -0
  115. spring/orm/pymybatis/pool/connection_pool.py +711 -0
  116. spring/orm/pymybatis/security/__init__.py +19 -0
  117. spring/orm/pymybatis/security/access_control.py +415 -0
  118. spring/orm/pymybatis/security/password_encoder.py +293 -0
  119. spring/orm/pymybatis/security/sensitive_data_masker.py +326 -0
  120. spring/orm/pymybatis/security/sql_injection_detector.py +675 -0
  121. spring/orm/pymybatis/transaction/__init__.py +9 -0
  122. spring/orm/pymybatis/transaction/transaction.py +288 -0
  123. spring/orm/pymybatis/type_handler/__init__.py +37 -0
  124. spring/orm/pymybatis/type_handler/type_handler.py +473 -0
  125. spring/orm/pymybatis/version.py +9 -0
  126. spring/orm/pymybatis/xml_parser/__init__.py +9 -0
  127. spring/orm/pymybatis/xml_parser/xml_parser.py +761 -0
  128. spring/retry/__init__.py +12 -0
  129. spring/retry/retry_annotations.py +71 -0
  130. spring/retry/retry_decorator.py +155 -0
  131. spring/scheduling/__init__.py +3 -0
  132. spring/scheduling/scheduler.py +389 -0
  133. spring/security/__init__.py +39 -0
  134. spring/security/jwt_utils.py +281 -0
  135. spring/security/replay_protection.py +206 -0
  136. spring/security/secret_manager.py +226 -0
  137. spring/security/security_aop.py +248 -0
  138. spring/security/security_context.py +172 -0
  139. spring/test/__init__.py +45 -0
  140. spring/test/slicing.py +341 -0
  141. spring/tracing/__init__.py +11 -0
  142. spring/tracing/skywalking.py +229 -0
  143. spring/tx/__init__.py +52 -0
  144. spring/tx/events.py +172 -0
  145. spring/tx/synchronization.py +143 -0
  146. spring/utils/__init__.py +5 -0
  147. spring/utils/banner.py +32 -0
  148. spring/utils/logger.py +73 -0
  149. spring/utils/redis_client.py +526 -0
  150. spring/validation/__init__.py +55 -0
  151. spring/validation/aop.py +141 -0
  152. spring/validation/constraints.py +357 -0
  153. spring/validation/exceptions.py +55 -0
  154. spring/validation/validator.py +139 -0
  155. spring/web/__init__.py +12 -0
  156. spring/web/actuator.py +319 -0
  157. spring/web/exception_handler.py +61 -0
  158. spring/web/health.py +399 -0
  159. spring/web/interceptor.py +91 -0
  160. spring/web/result.py +44 -0
  161. spring/web/swagger.py +601 -0
  162. spring/web/web_context.py +755 -0
  163. spring/websocket/__init__.py +86 -0
  164. spring/websocket/annotations.py +169 -0
  165. spring/websocket/broker.py +238 -0
  166. spring/websocket/exceptions.py +26 -0
  167. spring/websocket/handler.py +243 -0
  168. spring/websocket/router.py +526 -0
  169. spring/websocket/session.py +216 -0
  170. springbootai-1.8.0.dist-info/METADATA +2796 -0
  171. springbootai-1.8.0.dist-info/RECORD +175 -0
  172. springbootai-1.8.0.dist-info/WHEEL +5 -0
  173. springbootai-1.8.0.dist-info/entry_points.txt +2 -0
  174. springbootai-1.8.0.dist-info/licenses/LICENSE +7 -0
  175. springbootai-1.8.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,424 @@
1
+ """
2
+ PyMyBatis熔断降级模块
3
+
4
+ 实现数据库连接熔断机制,防止数据库故障导致的级联失败
5
+
6
+ 核心特性:
7
+ - 三种状态:闭合(Closed)、打开(Open)、半开(Half-Open)
8
+ - 基于失败率的熔断触发
9
+ - 自动恢复机制
10
+ - 支持自定义降级策略
11
+ """
12
+
13
+ import time
14
+ import threading
15
+ import logging
16
+ from enum import Enum
17
+ from typing import Callable, Optional, Any, Dict
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ class CircuitBreakerState(Enum):
23
+ """
24
+ 熔断器状态
25
+
26
+ CLOSED: 闭合状态,正常运行,所有请求都被允许通过
27
+ OPEN: 打开状态,熔断器触发,所有请求都被拒绝,直接返回降级结果
28
+ HALF_OPEN: 半开状态,尝试恢复,允许部分请求通过进行试探
29
+ """
30
+ CLOSED = 'closed'
31
+ OPEN = 'open'
32
+ HALF_OPEN = 'half_open'
33
+
34
+
35
+ class CircuitBreakerError(Exception):
36
+ """
37
+ 熔断器异常
38
+
39
+ 当熔断器处于打开状态时,请求被拒绝时抛出此异常
40
+ """
41
+
42
+ def __init__(self, message: str, fallback_result: Any = None):
43
+ super().__init__(message)
44
+ self.fallback_result = fallback_result
45
+
46
+
47
+ class CircuitBreaker:
48
+ """
49
+ 熔断器实现
50
+
51
+ 实现经典的熔断器模式:
52
+ 1. 闭合状态:正常处理请求,记录失败次数
53
+ 2. 打开状态:拒绝所有请求,返回降级结果
54
+ 3. 半开状态:允许部分请求通过,检测服务是否恢复
55
+
56
+ 配置参数:
57
+ - failure_threshold: 失败阈值,当失败次数达到此值时触发熔断
58
+ - recovery_timeout: 恢复超时时间,熔断器打开后经过此时间进入半开状态
59
+ - success_threshold: 成功阈值,半开状态下成功次数达到此值时恢复闭合状态
60
+ - max_concurrent_requests: 最大并发请求数
61
+ - fallback: 降级函数,熔断器打开时调用
62
+ """
63
+
64
+ def __init__(self,
65
+ failure_threshold: int = 5,
66
+ recovery_timeout: int = 30,
67
+ success_threshold: int = 3,
68
+ max_concurrent_requests: int = 100,
69
+ fallback: Optional[Callable[..., Any]] = None,
70
+ name: str = 'default'):
71
+ """
72
+ 初始化熔断器
73
+
74
+ Args:
75
+ failure_threshold: 失败阈值,当失败次数达到此值时触发熔断
76
+ recovery_timeout: 恢复超时时间(秒),熔断器打开后经过此时间进入半开状态
77
+ success_threshold: 成功阈值,半开状态下成功次数达到此值时恢复闭合状态
78
+ max_concurrent_requests: 最大并发请求数
79
+ fallback: 降级函数,熔断器打开时调用
80
+ name: 熔断器名称,用于日志和监控
81
+ """
82
+ self.failure_threshold = failure_threshold
83
+ self.recovery_timeout = recovery_timeout
84
+ self.success_threshold = success_threshold
85
+ self.max_concurrent_requests = max_concurrent_requests
86
+ self.fallback = fallback
87
+ self.name = name
88
+
89
+ # 状态管理
90
+ self._state = CircuitBreakerState.CLOSED
91
+ self._failure_count = 0
92
+ self._success_count = 0
93
+ self._concurrent_requests = 0
94
+ self._last_failure_time = 0
95
+ self._last_state_change_time = 0
96
+
97
+ # 锁
98
+ self._lock = threading.RLock()
99
+ self._state_lock = threading.RLock()
100
+
101
+ # 统计信息
102
+ self._total_requests = 0
103
+ self._total_failures = 0
104
+ self._total_successes = 0
105
+ self._total_circuit_open = 0
106
+
107
+ def _get_state(self) -> CircuitBreakerState:
108
+ """
109
+ 获取当前状态(考虑状态自动转换)
110
+
111
+ Returns:
112
+ 当前状态
113
+ """
114
+ with self._state_lock:
115
+ # 如果是打开状态,检查是否应该进入半开状态
116
+ if self._state == CircuitBreakerState.OPEN:
117
+ elapsed = time.time() - self._last_state_change_time
118
+ if elapsed >= self.recovery_timeout:
119
+ logger.info(f"熔断器[{self.name}]从OPEN状态转换为HALF_OPEN状态")
120
+ self._state = CircuitBreakerState.HALF_OPEN
121
+ self._success_count = 0
122
+ self._last_state_change_time = time.time()
123
+
124
+ return self._state
125
+
126
+ def _transition_to_open(self):
127
+ """转换到打开状态"""
128
+ with self._state_lock:
129
+ if self._state != CircuitBreakerState.OPEN:
130
+ logger.warning(f"熔断器[{self.name}]触发熔断,转换为OPEN状态")
131
+ self._state = CircuitBreakerState.OPEN
132
+ self._last_state_change_time = time.time()
133
+ self._total_circuit_open += 1
134
+
135
+ def _transition_to_closed(self):
136
+ """转换到闭合状态"""
137
+ with self._state_lock:
138
+ if self._state != CircuitBreakerState.CLOSED:
139
+ logger.info(f"熔断器[{self.name}]恢复正常,转换为CLOSED状态")
140
+ self._state = CircuitBreakerState.CLOSED
141
+ self._failure_count = 0
142
+ self._success_count = 0
143
+ self._last_state_change_time = time.time()
144
+
145
+ def _acquire_concurrent_slot(self) -> bool:
146
+ """
147
+ 获取并发请求槽位
148
+
149
+ Returns:
150
+ 是否成功获取
151
+ """
152
+ with self._lock:
153
+ if self._concurrent_requests >= self.max_concurrent_requests:
154
+ logger.warning(f"熔断器[{self.name}]并发请求数已达上限: {self.max_concurrent_requests}")
155
+ return False
156
+ self._concurrent_requests += 1
157
+ return True
158
+
159
+ def _release_concurrent_slot(self):
160
+ """释放并发请求槽位"""
161
+ with self._lock:
162
+ self._concurrent_requests = max(0, self._concurrent_requests - 1)
163
+
164
+ def call(self, func: Callable[..., Any], *args, **kwargs) -> Any:
165
+ """
166
+ 执行受保护的函数调用
167
+
168
+ Args:
169
+ func: 受保护的函数
170
+ *args: 函数参数
171
+ **kwargs: 函数关键字参数
172
+
173
+ Returns:
174
+ 函数执行结果
175
+
176
+ Raises:
177
+ CircuitBreakerError: 熔断器打开时抛出
178
+ Exception: 函数执行异常
179
+ """
180
+ state = self._get_state()
181
+
182
+ # 检查并发限制
183
+ if not self._acquire_concurrent_slot():
184
+ if self.fallback:
185
+ return self.fallback(*args, **kwargs)
186
+ raise CircuitBreakerError(f"熔断器[{self.name}]并发请求数已达上限")
187
+
188
+ try:
189
+ # 根据状态处理请求
190
+ if state == CircuitBreakerState.OPEN:
191
+ # 熔断器打开,直接返回降级结果
192
+ self._total_requests += 1
193
+ if self.fallback:
194
+ result = self.fallback(*args, **kwargs)
195
+ logger.debug(f"熔断器[{self.name}]OPEN状态,使用降级结果")
196
+ return result
197
+ raise CircuitBreakerError(f"熔断器[{self.name}]处于OPEN状态,请求被拒绝")
198
+
199
+ elif state == CircuitBreakerState.HALF_OPEN:
200
+ # 熔断器半开,允许试探请求
201
+ logger.debug(f"熔断器[{self.name}]HALF_OPEN状态,允许试探请求")
202
+ result = self._execute_with_half_open(func, *args, **kwargs)
203
+
204
+ else:
205
+ # 熔断器闭合,正常执行
206
+ result = self._execute_with_closed(func, *args, **kwargs)
207
+
208
+ return result
209
+
210
+ finally:
211
+ self._release_concurrent_slot()
212
+
213
+ def _execute_with_closed(self, func: Callable[..., Any], *args, **kwargs) -> Any:
214
+ """
215
+ 闭合状态下执行函数
216
+
217
+ Args:
218
+ func: 函数
219
+ *args: 参数
220
+ **kwargs: 关键字参数
221
+
222
+ Returns:
223
+ 函数执行结果
224
+ """
225
+ try:
226
+ result = func(*args, **kwargs)
227
+ self._on_success()
228
+ return result
229
+ except Exception as e:
230
+ self._on_failure()
231
+ raise
232
+
233
+ def _execute_with_half_open(self, func: Callable[..., Any], *args, **kwargs) -> Any:
234
+ """
235
+ 半开状态下执行函数
236
+
237
+ Args:
238
+ func: 函数
239
+ *args: 参数
240
+ **kwargs: 关键字参数
241
+
242
+ Returns:
243
+ 函数执行结果
244
+ """
245
+ # 获取状态锁,确保在执行过程中状态不会被其他线程改变
246
+ with self._state_lock:
247
+ # 再次检查状态,因为可能在等待锁的过程中状态已经改变
248
+ current_state = self._state
249
+ if current_state != CircuitBreakerState.HALF_OPEN:
250
+ # 状态已改变,重新执行
251
+ return self.call(func, *args, **kwargs)
252
+
253
+ try:
254
+ result = func(*args, **kwargs)
255
+ self._success_count += 1
256
+ self._total_successes += 1
257
+ self._total_requests += 1
258
+
259
+ # 检查是否达到成功阈值
260
+ if self._success_count >= self.success_threshold:
261
+ self._state = CircuitBreakerState.CLOSED
262
+ self._failure_count = 0
263
+ self._success_count = 0
264
+ self._last_state_change_time = time.time()
265
+ logger.info(f"熔断器[{self.name}]恢复正常,转换为CLOSED状态")
266
+
267
+ return result
268
+ except Exception as e:
269
+ self._total_failures += 1
270
+ self._total_requests += 1
271
+
272
+ # 半开状态下任何失败都会立即打开熔断器
273
+ logger.warning(f"熔断器[{self.name}]HALF_OPEN状态下请求失败,立即打开")
274
+ self._state = CircuitBreakerState.OPEN
275
+ self._last_state_change_time = time.time()
276
+ raise
277
+
278
+ def _on_success(self):
279
+ """处理成功请求"""
280
+ with self._lock:
281
+ self._failure_count = 0
282
+ self._total_successes += 1
283
+ self._total_requests += 1
284
+
285
+ def _on_failure(self):
286
+ """处理失败请求"""
287
+ with self._lock:
288
+ self._failure_count += 1
289
+ self._total_failures += 1
290
+ self._total_requests += 1
291
+ self._last_failure_time = time.time()
292
+
293
+ # 检查是否达到失败阈值
294
+ if self._failure_count >= self.failure_threshold:
295
+ self._transition_to_open()
296
+
297
+ def reset(self):
298
+ """重置熔断器状态"""
299
+ with self._state_lock:
300
+ logger.info(f"熔断器[{self.name}]被重置")
301
+ self._state = CircuitBreakerState.CLOSED
302
+ self._failure_count = 0
303
+ self._success_count = 0
304
+ self._last_state_change_time = time.time()
305
+
306
+ def force_open(self):
307
+ """强制打开熔断器"""
308
+ with self._state_lock:
309
+ logger.warning(f"熔断器[{self.name}]被强制打开")
310
+ self._state = CircuitBreakerState.OPEN
311
+ self._last_state_change_time = time.time()
312
+
313
+ def force_close(self):
314
+ """强制关闭熔断器"""
315
+ with self._state_lock:
316
+ logger.info(f"熔断器[{self.name}]被强制关闭")
317
+ self._state = CircuitBreakerState.CLOSED
318
+ self._failure_count = 0
319
+ self._success_count = 0
320
+ self._last_state_change_time = time.time()
321
+
322
+ def get_state(self) -> str:
323
+ """获取当前状态字符串"""
324
+ return self._get_state().value
325
+
326
+ def get_stats(self) -> Dict[str, Any]:
327
+ """
328
+ 获取熔断器统计信息
329
+
330
+ Returns:
331
+ 统计信息字典
332
+ """
333
+ with self._lock:
334
+ return {
335
+ 'name': self.name,
336
+ 'state': self._get_state().value,
337
+ 'failure_threshold': self.failure_threshold,
338
+ 'recovery_timeout': self.recovery_timeout,
339
+ 'success_threshold': self.success_threshold,
340
+ 'max_concurrent_requests': self.max_concurrent_requests,
341
+ 'current_concurrent_requests': self._concurrent_requests,
342
+ 'failure_count': self._failure_count,
343
+ 'success_count': self._success_count,
344
+ 'total_requests': self._total_requests,
345
+ 'total_successes': self._total_successes,
346
+ 'total_failures': self._total_failures,
347
+ 'total_circuit_open': self._total_circuit_open,
348
+ 'last_failure_time': self._last_failure_time,
349
+ 'last_state_change_time': self._last_state_change_time,
350
+ 'failure_rate': round(self._total_failures / self._total_requests * 100, 2) if self._total_requests > 0 else 0.0
351
+ }
352
+
353
+ def __enter__(self):
354
+ """上下文管理器进入"""
355
+ return self
356
+
357
+ def __exit__(self, exc_type, exc_val, exc_tb):
358
+ """上下文管理器退出"""
359
+ pass
360
+
361
+
362
+ class DatabaseCircuitBreaker(CircuitBreaker):
363
+ """
364
+ 数据库连接专用熔断器
365
+
366
+ 针对数据库连接场景优化:
367
+ - 默认配置适合数据库连接场景
368
+ - 支持连接池集成
369
+ """
370
+
371
+ def __init__(self,
372
+ failure_threshold: int = 3,
373
+ recovery_timeout: int = 60,
374
+ success_threshold: int = 3,
375
+ max_concurrent_requests: int = 50,
376
+ fallback: Optional[Callable[..., Any]] = None,
377
+ name: str = 'database'):
378
+ """
379
+ 初始化数据库熔断器
380
+
381
+ Args:
382
+ failure_threshold: 失败阈值,默认3次
383
+ recovery_timeout: 恢复超时时间,默认60秒
384
+ success_threshold: 成功阈值,默认3次
385
+ max_concurrent_requests: 最大并发请求数,默认50
386
+ fallback: 降级函数
387
+ name: 熔断器名称
388
+ """
389
+ super().__init__(
390
+ failure_threshold=failure_threshold,
391
+ recovery_timeout=recovery_timeout,
392
+ success_threshold=success_threshold,
393
+ max_concurrent_requests=max_concurrent_requests,
394
+ fallback=fallback,
395
+ name=name
396
+ )
397
+
398
+
399
+ # 全局默认数据库熔断器
400
+ DEFAULT_DB_CIRCUIT_BREAKER = DatabaseCircuitBreaker()
401
+
402
+
403
+ def with_circuit_breaker(circuit_breaker: CircuitBreaker = None):
404
+ """
405
+ 装饰器:使用熔断器保护函数
406
+
407
+ Args:
408
+ circuit_breaker: 熔断器实例,默认使用全局数据库熔断器
409
+
410
+ Returns:
411
+ 装饰器函数
412
+ """
413
+ cb = circuit_breaker or DEFAULT_DB_CIRCUIT_BREAKER
414
+
415
+ def decorator(func: Callable[..., Any]):
416
+ import functools
417
+
418
+ @functools.wraps(func)
419
+ def wrapper(*args, **kwargs):
420
+ return cb.call(func, *args, **kwargs)
421
+
422
+ return wrapper
423
+
424
+ return decorator