lmcache-cli 0.4.5.dev0__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 (399) hide show
  1. lmcache/__init__.py +84 -0
  2. lmcache/_version.py +24 -0
  3. lmcache/cli/__init__.py +1 -0
  4. lmcache/cli/commands/__init__.py +34 -0
  5. lmcache/cli/commands/base.py +157 -0
  6. lmcache/cli/commands/bench/__init__.py +557 -0
  7. lmcache/cli/commands/bench/engine_bench/__init__.py +1 -0
  8. lmcache/cli/commands/bench/engine_bench/config.py +245 -0
  9. lmcache/cli/commands/bench/engine_bench/interactive/__init__.py +274 -0
  10. lmcache/cli/commands/bench/engine_bench/interactive/config.json +10 -0
  11. lmcache/cli/commands/bench/engine_bench/interactive/schema.py +352 -0
  12. lmcache/cli/commands/bench/engine_bench/interactive/state.py +327 -0
  13. lmcache/cli/commands/bench/engine_bench/interactive/terminal.py +291 -0
  14. lmcache/cli/commands/bench/engine_bench/progress.py +145 -0
  15. lmcache/cli/commands/bench/engine_bench/request_sender.py +232 -0
  16. lmcache/cli/commands/bench/engine_bench/stats.py +275 -0
  17. lmcache/cli/commands/bench/engine_bench/workloads/__init__.py +153 -0
  18. lmcache/cli/commands/bench/engine_bench/workloads/base.py +122 -0
  19. lmcache/cli/commands/bench/engine_bench/workloads/long_doc_permutator.py +435 -0
  20. lmcache/cli/commands/bench/engine_bench/workloads/long_doc_qa.py +281 -0
  21. lmcache/cli/commands/bench/engine_bench/workloads/multi_round_chat.py +337 -0
  22. lmcache/cli/commands/bench/engine_bench/workloads/random_prefill.py +178 -0
  23. lmcache/cli/commands/describe.py +310 -0
  24. lmcache/cli/commands/kvcache.py +133 -0
  25. lmcache/cli/commands/mock.py +75 -0
  26. lmcache/cli/commands/ping.py +113 -0
  27. lmcache/cli/commands/query/__init__.py +155 -0
  28. lmcache/cli/commands/query/prompt.py +134 -0
  29. lmcache/cli/commands/query/request.py +357 -0
  30. lmcache/cli/commands/server.py +99 -0
  31. lmcache/cli/commands/tool/__init__.py +63 -0
  32. lmcache/cli/commands/tool/cache_simulator.py +113 -0
  33. lmcache/cli/commands/trace/__init__.py +505 -0
  34. lmcache/cli/commands/trace/dispatch.py +249 -0
  35. lmcache/cli/commands/trace/driver.py +372 -0
  36. lmcache/cli/commands/trace/stats.py +289 -0
  37. lmcache/cli/documents/lmcache.txt +11 -0
  38. lmcache/cli/main.py +42 -0
  39. lmcache/cli/metrics/__init__.py +29 -0
  40. lmcache/cli/metrics/formatter.py +171 -0
  41. lmcache/cli/metrics/handler.py +94 -0
  42. lmcache/cli/metrics/metrics.py +161 -0
  43. lmcache/cli/metrics/section.py +77 -0
  44. lmcache/connections.py +173 -0
  45. lmcache/integration/__init__.py +2 -0
  46. lmcache/integration/base_service_factory.py +165 -0
  47. lmcache/integration/request_telemetry/__init__.py +1 -0
  48. lmcache/integration/request_telemetry/base.py +51 -0
  49. lmcache/integration/request_telemetry/factory.py +113 -0
  50. lmcache/integration/request_telemetry/fastapi.py +109 -0
  51. lmcache/integration/request_telemetry/noop.py +35 -0
  52. lmcache/integration/sglang/__init__.py +2 -0
  53. lmcache/integration/sglang/sglang_adapter.py +326 -0
  54. lmcache/integration/sglang/utils.py +39 -0
  55. lmcache/integration/vllm/__init__.py +1 -0
  56. lmcache/integration/vllm/lmcache_connector_v1.py +213 -0
  57. lmcache/integration/vllm/lmcache_connector_v1_085.py +150 -0
  58. lmcache/integration/vllm/lmcache_mp_connector_0180.py +1072 -0
  59. lmcache/integration/vllm/tests/test_mm_hash_utils.py +112 -0
  60. lmcache/integration/vllm/utils.py +433 -0
  61. lmcache/integration/vllm/vllm_multi_process_adapter.py +1090 -0
  62. lmcache/integration/vllm/vllm_service_factory.py +339 -0
  63. lmcache/integration/vllm/vllm_v1_adapter.py +1713 -0
  64. lmcache/logging.py +107 -0
  65. lmcache/native_storage_ops.pyi +230 -0
  66. lmcache/non_cuda_equivalents.py +1424 -0
  67. lmcache/observability.py +1958 -0
  68. lmcache/storage_backend/serde/__init__.py +1 -0
  69. lmcache/storage_backend/serde/cachegen_basics.py +210 -0
  70. lmcache/storage_backend/serde/cachegen_decoder.py +207 -0
  71. lmcache/storage_backend/serde/cachegen_encoder.py +394 -0
  72. lmcache/storage_backend/serde/serde.py +75 -0
  73. lmcache/tools/__init__.py +1 -0
  74. lmcache/tools/cache_simulator/README.md +392 -0
  75. lmcache/tools/cache_simulator/__init__.py +1 -0
  76. lmcache/tools/cache_simulator/docs/simulate_example.png +0 -0
  77. lmcache/tools/cache_simulator/docs/sweep_example.png +0 -0
  78. lmcache/tools/cache_simulator/gen_bench_dataset.py +360 -0
  79. lmcache/tools/cache_simulator/lru_cache.py +124 -0
  80. lmcache/tools/cache_simulator/plot_hit_rate.py +231 -0
  81. lmcache/tools/cache_simulator/simulator.py +795 -0
  82. lmcache/tools/controller_benchmark/README.md +161 -0
  83. lmcache/tools/controller_benchmark/__init__.py +1 -0
  84. lmcache/tools/controller_benchmark/__main__.py +331 -0
  85. lmcache/tools/controller_benchmark/benchmark.py +660 -0
  86. lmcache/tools/controller_benchmark/config.py +44 -0
  87. lmcache/tools/controller_benchmark/constants.py +10 -0
  88. lmcache/tools/controller_benchmark/handlers/__init__.py +46 -0
  89. lmcache/tools/controller_benchmark/handlers/admit.py +52 -0
  90. lmcache/tools/controller_benchmark/handlers/base.py +47 -0
  91. lmcache/tools/controller_benchmark/handlers/deregister.py +49 -0
  92. lmcache/tools/controller_benchmark/handlers/evict.py +52 -0
  93. lmcache/tools/controller_benchmark/handlers/heartbeat.py +56 -0
  94. lmcache/tools/controller_benchmark/handlers/p2p_lookup.py +47 -0
  95. lmcache/tools/controller_benchmark/handlers/register.py +56 -0
  96. lmcache/tools/mp_status_viewer/__init__.py +1 -0
  97. lmcache/tools/mp_status_viewer/__main__.py +95 -0
  98. lmcache/usage_context.py +417 -0
  99. lmcache/utils.py +665 -0
  100. lmcache/v1/__init__.py +2 -0
  101. lmcache/v1/api_server/__init__.py +2 -0
  102. lmcache/v1/api_server/__main__.py +537 -0
  103. lmcache/v1/basic_check.py +112 -0
  104. lmcache/v1/cache_controller/__init__.py +9 -0
  105. lmcache/v1/cache_controller/commands/__init__.py +15 -0
  106. lmcache/v1/cache_controller/commands/base.py +35 -0
  107. lmcache/v1/cache_controller/commands/full_sync.py +49 -0
  108. lmcache/v1/cache_controller/config.py +176 -0
  109. lmcache/v1/cache_controller/controller_manager.py +535 -0
  110. lmcache/v1/cache_controller/controllers/__init__.py +11 -0
  111. lmcache/v1/cache_controller/controllers/full_sync_tracker.py +473 -0
  112. lmcache/v1/cache_controller/controllers/kv_controller.py +439 -0
  113. lmcache/v1/cache_controller/controllers/registration_controller.py +282 -0
  114. lmcache/v1/cache_controller/executor.py +463 -0
  115. lmcache/v1/cache_controller/frontend/static/css/style.css +201 -0
  116. lmcache/v1/cache_controller/frontend/static/img/logo.png +0 -0
  117. lmcache/v1/cache_controller/frontend/static/index.html +234 -0
  118. lmcache/v1/cache_controller/frontend/static/js/controller_app.js +660 -0
  119. lmcache/v1/cache_controller/full_sync_sender.py +475 -0
  120. lmcache/v1/cache_controller/locks.py +149 -0
  121. lmcache/v1/cache_controller/message.py +828 -0
  122. lmcache/v1/cache_controller/observability.py +208 -0
  123. lmcache/v1/cache_controller/utils.py +679 -0
  124. lmcache/v1/cache_controller/worker.py +665 -0
  125. lmcache/v1/cache_engine.py +2058 -0
  126. lmcache/v1/cache_interface.py +19 -0
  127. lmcache/v1/check/__init__.py +74 -0
  128. lmcache/v1/check/check_mode_gen.py +86 -0
  129. lmcache/v1/check/check_mode_test_l2_adapter.py +284 -0
  130. lmcache/v1/check/check_mode_test_remote.py +155 -0
  131. lmcache/v1/check/check_mode_test_storage_manager.py +142 -0
  132. lmcache/v1/check/utils.py +571 -0
  133. lmcache/v1/compute/__init__.py +2 -0
  134. lmcache/v1/compute/attention/__init__.py +0 -0
  135. lmcache/v1/compute/attention/abstract.py +39 -0
  136. lmcache/v1/compute/attention/flash_attn.py +129 -0
  137. lmcache/v1/compute/attention/flash_infer_sparse.py +284 -0
  138. lmcache/v1/compute/attention/metadata.py +85 -0
  139. lmcache/v1/compute/attention/utils.py +14 -0
  140. lmcache/v1/compute/blend/__init__.py +7 -0
  141. lmcache/v1/compute/blend/blender.py +168 -0
  142. lmcache/v1/compute/blend/metadata.py +34 -0
  143. lmcache/v1/compute/blend/utils.py +63 -0
  144. lmcache/v1/compute/models/__init__.py +0 -0
  145. lmcache/v1/compute/models/base.py +141 -0
  146. lmcache/v1/compute/models/llama.py +9 -0
  147. lmcache/v1/compute/models/qwen3.py +24 -0
  148. lmcache/v1/compute/models/utils.py +68 -0
  149. lmcache/v1/compute/positional_encoding.py +199 -0
  150. lmcache/v1/config.py +848 -0
  151. lmcache/v1/config_base.py +848 -0
  152. lmcache/v1/distributed/api.py +248 -0
  153. lmcache/v1/distributed/config.py +321 -0
  154. lmcache/v1/distributed/error.py +64 -0
  155. lmcache/v1/distributed/eviction.py +192 -0
  156. lmcache/v1/distributed/eviction_policy/__init__.py +21 -0
  157. lmcache/v1/distributed/eviction_policy/factory.py +27 -0
  158. lmcache/v1/distributed/eviction_policy/lru.py +244 -0
  159. lmcache/v1/distributed/eviction_policy/noop.py +50 -0
  160. lmcache/v1/distributed/internal_api.py +170 -0
  161. lmcache/v1/distributed/l1_manager.py +835 -0
  162. lmcache/v1/distributed/l2_adapters/__init__.py +67 -0
  163. lmcache/v1/distributed/l2_adapters/base.py +360 -0
  164. lmcache/v1/distributed/l2_adapters/config.py +385 -0
  165. lmcache/v1/distributed/l2_adapters/factory.py +205 -0
  166. lmcache/v1/distributed/l2_adapters/fs_l2_adapter.py +747 -0
  167. lmcache/v1/distributed/l2_adapters/fs_native_l2_adapter.py +167 -0
  168. lmcache/v1/distributed/l2_adapters/mock_l2_adapter.py +516 -0
  169. lmcache/v1/distributed/l2_adapters/mooncake_store_l2_adapter.py +135 -0
  170. lmcache/v1/distributed/l2_adapters/native_connector_l2_adapter.py +468 -0
  171. lmcache/v1/distributed/l2_adapters/native_plugin_l2_adapter.py +199 -0
  172. lmcache/v1/distributed/l2_adapters/nixl_store_dynamic_l2_adapter.py +831 -0
  173. lmcache/v1/distributed/l2_adapters/nixl_store_l2_adapter.py +983 -0
  174. lmcache/v1/distributed/l2_adapters/plugin_l2_adapter.py +210 -0
  175. lmcache/v1/distributed/l2_adapters/resp_l2_adapter.py +176 -0
  176. lmcache/v1/distributed/memory_manager.py +179 -0
  177. lmcache/v1/distributed/storage_controller.py +39 -0
  178. lmcache/v1/distributed/storage_controllers/__init__.py +43 -0
  179. lmcache/v1/distributed/storage_controllers/eviction_controller.py +242 -0
  180. lmcache/v1/distributed/storage_controllers/prefetch_controller.py +830 -0
  181. lmcache/v1/distributed/storage_controllers/prefetch_policy.py +193 -0
  182. lmcache/v1/distributed/storage_controllers/store_controller.py +452 -0
  183. lmcache/v1/distributed/storage_controllers/store_policy.py +213 -0
  184. lmcache/v1/distributed/storage_manager.py +532 -0
  185. lmcache/v1/event_manager.py +145 -0
  186. lmcache/v1/exceptions/__init__.py +16 -0
  187. lmcache/v1/gpu_connector/__init__.py +126 -0
  188. lmcache/v1/gpu_connector/gpu_connectors.py +1906 -0
  189. lmcache/v1/gpu_connector/gpu_ops.py +85 -0
  190. lmcache/v1/gpu_connector/hpu_connector.py +326 -0
  191. lmcache/v1/gpu_connector/mock_gpu_connector.py +67 -0
  192. lmcache/v1/gpu_connector/utils.py +890 -0
  193. lmcache/v1/gpu_connector/xpu_connectors.py +916 -0
  194. lmcache/v1/health_monitor/__init__.py +1 -0
  195. lmcache/v1/health_monitor/base.py +587 -0
  196. lmcache/v1/health_monitor/checks/__init__.py +1 -0
  197. lmcache/v1/health_monitor/checks/remote_backend_check.py +304 -0
  198. lmcache/v1/health_monitor/constants.py +36 -0
  199. lmcache/v1/internal_api_server/__init__.py +0 -0
  200. lmcache/v1/internal_api_server/api_registry.py +59 -0
  201. lmcache/v1/internal_api_server/api_server.py +120 -0
  202. lmcache/v1/internal_api_server/common/__init__.py +1 -0
  203. lmcache/v1/internal_api_server/common/env_api.py +22 -0
  204. lmcache/v1/internal_api_server/common/loglevel_api.py +57 -0
  205. lmcache/v1/internal_api_server/common/metrics_api.py +29 -0
  206. lmcache/v1/internal_api_server/common/periodic_thread_api.py +138 -0
  207. lmcache/v1/internal_api_server/common/run_script_api.py +73 -0
  208. lmcache/v1/internal_api_server/common/thread_api.py +63 -0
  209. lmcache/v1/internal_api_server/controller/__init__.py +1 -0
  210. lmcache/v1/internal_api_server/controller/key_stats_api.py +81 -0
  211. lmcache/v1/internal_api_server/controller/worker_info_api.py +136 -0
  212. lmcache/v1/internal_api_server/utils.py +43 -0
  213. lmcache/v1/internal_api_server/vllm/__init__.py +1 -0
  214. lmcache/v1/internal_api_server/vllm/backend_api.py +221 -0
  215. lmcache/v1/internal_api_server/vllm/bypass_api.py +204 -0
  216. lmcache/v1/internal_api_server/vllm/cache_api.py +895 -0
  217. lmcache/v1/internal_api_server/vllm/chunk_statistics_api.py +141 -0
  218. lmcache/v1/internal_api_server/vllm/conf_api.py +147 -0
  219. lmcache/v1/internal_api_server/vllm/freeze_api.py +172 -0
  220. lmcache/v1/internal_api_server/vllm/hot_cache_api.py +184 -0
  221. lmcache/v1/internal_api_server/vllm/inference_api.py +65 -0
  222. lmcache/v1/internal_api_server/vllm/load_fs_chunks_api.py +320 -0
  223. lmcache/v1/internal_api_server/vllm/lookup_api.py +145 -0
  224. lmcache/v1/internal_api_server/vllm/version_api.py +25 -0
  225. lmcache/v1/kv_layer_groups.py +267 -0
  226. lmcache/v1/lazy_memory_allocator.py +284 -0
  227. lmcache/v1/lookup_client/__init__.py +25 -0
  228. lmcache/v1/lookup_client/abstract_client.py +77 -0
  229. lmcache/v1/lookup_client/async_lookup_message.py +50 -0
  230. lmcache/v1/lookup_client/chunk_statistics_lookup_client.py +200 -0
  231. lmcache/v1/lookup_client/factory.py +251 -0
  232. lmcache/v1/lookup_client/hit_limit_lookup_client.py +86 -0
  233. lmcache/v1/lookup_client/lmcache_async_lookup_client.py +407 -0
  234. lmcache/v1/lookup_client/lmcache_lookup_client.py +285 -0
  235. lmcache/v1/lookup_client/lmcache_lookup_client_bypass.py +99 -0
  236. lmcache/v1/lookup_client/mooncake_lookup_client.py +87 -0
  237. lmcache/v1/lookup_client/record_strategies/__init__.py +77 -0
  238. lmcache/v1/lookup_client/record_strategies/base.py +327 -0
  239. lmcache/v1/lookup_client/record_strategies/file_hash.py +130 -0
  240. lmcache/v1/lookup_client/record_strategies/memory_bloom_filter.py +81 -0
  241. lmcache/v1/manager.py +539 -0
  242. lmcache/v1/memory_management.py +2619 -0
  243. lmcache/v1/metadata.py +114 -0
  244. lmcache/v1/mp_observability/AGENTS.override.md +21 -0
  245. lmcache/v1/mp_observability/README.md +204 -0
  246. lmcache/v1/mp_observability/config.py +340 -0
  247. lmcache/v1/mp_observability/event.py +100 -0
  248. lmcache/v1/mp_observability/event_bus.py +313 -0
  249. lmcache/v1/mp_observability/otel_init.py +145 -0
  250. lmcache/v1/mp_observability/subscribers/__init__.py +28 -0
  251. lmcache/v1/mp_observability/subscribers/logging/__init__.py +19 -0
  252. lmcache/v1/mp_observability/subscribers/logging/l1.py +56 -0
  253. lmcache/v1/mp_observability/subscribers/logging/l2.py +73 -0
  254. lmcache/v1/mp_observability/subscribers/logging/lookup_hash.py +209 -0
  255. lmcache/v1/mp_observability/subscribers/logging/mp_server.py +90 -0
  256. lmcache/v1/mp_observability/subscribers/logging/sm.py +59 -0
  257. lmcache/v1/mp_observability/subscribers/metrics/__init__.py +20 -0
  258. lmcache/v1/mp_observability/subscribers/metrics/l0_lifecycle.py +290 -0
  259. lmcache/v1/mp_observability/subscribers/metrics/l1.py +55 -0
  260. lmcache/v1/mp_observability/subscribers/metrics/l1_lifecycle.py +166 -0
  261. lmcache/v1/mp_observability/subscribers/metrics/l2.py +121 -0
  262. lmcache/v1/mp_observability/subscribers/metrics/sm.py +69 -0
  263. lmcache/v1/mp_observability/subscribers/tracing/__init__.py +12 -0
  264. lmcache/v1/mp_observability/subscribers/tracing/mp_server.py +333 -0
  265. lmcache/v1/mp_observability/subscribers/tracing/span_registry.py +148 -0
  266. lmcache/v1/mp_observability/trace/__init__.py +50 -0
  267. lmcache/v1/mp_observability/trace/codecs.py +255 -0
  268. lmcache/v1/mp_observability/trace/decorator.py +147 -0
  269. lmcache/v1/mp_observability/trace/format.py +132 -0
  270. lmcache/v1/mp_observability/trace/lifecycle.py +83 -0
  271. lmcache/v1/mp_observability/trace/reader.py +167 -0
  272. lmcache/v1/mp_observability/trace/recorder.py +300 -0
  273. lmcache/v1/multiprocess/__init__.py +0 -0
  274. lmcache/v1/multiprocess/affinity_pool.py +102 -0
  275. lmcache/v1/multiprocess/blend_server_v2.py +891 -0
  276. lmcache/v1/multiprocess/config.py +253 -0
  277. lmcache/v1/multiprocess/custom_types.py +281 -0
  278. lmcache/v1/multiprocess/futures.py +194 -0
  279. lmcache/v1/multiprocess/gpu_context.py +511 -0
  280. lmcache/v1/multiprocess/http_server.py +235 -0
  281. lmcache/v1/multiprocess/mp_runtime_plugin_launcher.py +130 -0
  282. lmcache/v1/multiprocess/mq.py +732 -0
  283. lmcache/v1/multiprocess/protocol.py +86 -0
  284. lmcache/v1/multiprocess/protocols/README.md +213 -0
  285. lmcache/v1/multiprocess/protocols/__init__.py +127 -0
  286. lmcache/v1/multiprocess/protocols/base.py +89 -0
  287. lmcache/v1/multiprocess/protocols/blend.py +109 -0
  288. lmcache/v1/multiprocess/protocols/blend_v2.py +57 -0
  289. lmcache/v1/multiprocess/protocols/controller.py +53 -0
  290. lmcache/v1/multiprocess/protocols/debug.py +34 -0
  291. lmcache/v1/multiprocess/protocols/engine.py +146 -0
  292. lmcache/v1/multiprocess/protocols/observability.py +39 -0
  293. lmcache/v1/multiprocess/server.py +1134 -0
  294. lmcache/v1/multiprocess/session.py +190 -0
  295. lmcache/v1/multiprocess/token_hasher.py +441 -0
  296. lmcache/v1/offload_server/__init__.py +17 -0
  297. lmcache/v1/offload_server/abstract_server.py +37 -0
  298. lmcache/v1/offload_server/message.py +30 -0
  299. lmcache/v1/offload_server/zmq_server.py +122 -0
  300. lmcache/v1/periodic_thread.py +579 -0
  301. lmcache/v1/pin_monitor.py +246 -0
  302. lmcache/v1/plugin/__init__.py +0 -0
  303. lmcache/v1/plugin/runtime_plugin_launcher.py +211 -0
  304. lmcache/v1/protocol.py +317 -0
  305. lmcache/v1/rpc/__init__.py +17 -0
  306. lmcache/v1/rpc/transport.py +105 -0
  307. lmcache/v1/rpc/zmq_transport.py +213 -0
  308. lmcache/v1/rpc_utils.py +165 -0
  309. lmcache/v1/server/__init__.py +2 -0
  310. lmcache/v1/server/__main__.py +170 -0
  311. lmcache/v1/server/storage_backend/__init__.py +21 -0
  312. lmcache/v1/server/storage_backend/abstract_backend.py +80 -0
  313. lmcache/v1/server/storage_backend/local_backend.py +75 -0
  314. lmcache/v1/server/utils.py +21 -0
  315. lmcache/v1/standalone/__init__.py +1 -0
  316. lmcache/v1/standalone/__main__.py +583 -0
  317. lmcache/v1/standalone/manager.py +80 -0
  318. lmcache/v1/standalone/standalone_service_factory.py +86 -0
  319. lmcache/v1/storage_backend/__init__.py +313 -0
  320. lmcache/v1/storage_backend/abstract_backend.py +445 -0
  321. lmcache/v1/storage_backend/audit_backend.py +233 -0
  322. lmcache/v1/storage_backend/batched_message_sender.py +222 -0
  323. lmcache/v1/storage_backend/cache_policy/__init__.py +45 -0
  324. lmcache/v1/storage_backend/cache_policy/base_policy.py +87 -0
  325. lmcache/v1/storage_backend/cache_policy/fifo.py +58 -0
  326. lmcache/v1/storage_backend/cache_policy/lfu.py +105 -0
  327. lmcache/v1/storage_backend/cache_policy/lru.py +81 -0
  328. lmcache/v1/storage_backend/cache_policy/mru.py +61 -0
  329. lmcache/v1/storage_backend/connector/__init__.py +443 -0
  330. lmcache/v1/storage_backend/connector/audit_adapter.py +77 -0
  331. lmcache/v1/storage_backend/connector/audit_connector.py +320 -0
  332. lmcache/v1/storage_backend/connector/base_connector.py +379 -0
  333. lmcache/v1/storage_backend/connector/blackhole_adapter.py +21 -0
  334. lmcache/v1/storage_backend/connector/blackhole_connector.py +37 -0
  335. lmcache/v1/storage_backend/connector/eic_adapter.py +31 -0
  336. lmcache/v1/storage_backend/connector/eic_connector.py +757 -0
  337. lmcache/v1/storage_backend/connector/external_adapter.py +79 -0
  338. lmcache/v1/storage_backend/connector/fs_adapter.py +51 -0
  339. lmcache/v1/storage_backend/connector/fs_connector.py +403 -0
  340. lmcache/v1/storage_backend/connector/infinistore_adapter.py +56 -0
  341. lmcache/v1/storage_backend/connector/infinistore_connector.py +177 -0
  342. lmcache/v1/storage_backend/connector/instrumented_connector.py +219 -0
  343. lmcache/v1/storage_backend/connector/lm_adapter.py +31 -0
  344. lmcache/v1/storage_backend/connector/lm_connector.py +176 -0
  345. lmcache/v1/storage_backend/connector/mock_adapter.py +57 -0
  346. lmcache/v1/storage_backend/connector/mock_connector.py +349 -0
  347. lmcache/v1/storage_backend/connector/mooncakestore_adapter.py +43 -0
  348. lmcache/v1/storage_backend/connector/mooncakestore_connector.py +614 -0
  349. lmcache/v1/storage_backend/connector/redis_adapter.py +181 -0
  350. lmcache/v1/storage_backend/connector/redis_connector.py +828 -0
  351. lmcache/v1/storage_backend/connector/s3_adapter.py +59 -0
  352. lmcache/v1/storage_backend/connector/s3_connector.py +699 -0
  353. lmcache/v1/storage_backend/connector/sagemaker_hyperpod_adapter.py +233 -0
  354. lmcache/v1/storage_backend/connector/sagemaker_hyperpod_connector.py +987 -0
  355. lmcache/v1/storage_backend/connector/valkey_adapter.py +114 -0
  356. lmcache/v1/storage_backend/connector/valkey_connector.py +627 -0
  357. lmcache/v1/storage_backend/gds_backend.py +1199 -0
  358. lmcache/v1/storage_backend/job_executor/__init__.py +0 -0
  359. lmcache/v1/storage_backend/job_executor/base_executor.py +34 -0
  360. lmcache/v1/storage_backend/job_executor/pq_executor.py +235 -0
  361. lmcache/v1/storage_backend/local_cpu_backend.py +810 -0
  362. lmcache/v1/storage_backend/local_disk_backend.py +656 -0
  363. lmcache/v1/storage_backend/maru_backend.py +734 -0
  364. lmcache/v1/storage_backend/naive_serde/__init__.py +50 -0
  365. lmcache/v1/storage_backend/naive_serde/cachegen_basics.py +133 -0
  366. lmcache/v1/storage_backend/naive_serde/cachegen_decoder.py +135 -0
  367. lmcache/v1/storage_backend/naive_serde/cachegen_encoder.py +83 -0
  368. lmcache/v1/storage_backend/naive_serde/kivi_serde.py +22 -0
  369. lmcache/v1/storage_backend/naive_serde/naive_serde.py +18 -0
  370. lmcache/v1/storage_backend/naive_serde/serde.py +37 -0
  371. lmcache/v1/storage_backend/native_clients/connector_client_base.py +165 -0
  372. lmcache/v1/storage_backend/native_clients/resp_client.py +35 -0
  373. lmcache/v1/storage_backend/nixl_storage_backend.py +1400 -0
  374. lmcache/v1/storage_backend/p2p_backend.py +788 -0
  375. lmcache/v1/storage_backend/path_sharder.py +117 -0
  376. lmcache/v1/storage_backend/pd_backend.py +646 -0
  377. lmcache/v1/storage_backend/plugins/dax_backend.py +1443 -0
  378. lmcache/v1/storage_backend/plugins/rust_raw_block_backend.py +1361 -0
  379. lmcache/v1/storage_backend/remote_backend.py +624 -0
  380. lmcache/v1/storage_backend/resp_client.py +227 -0
  381. lmcache/v1/storage_backend/storage_backend_listener.py +19 -0
  382. lmcache/v1/storage_backend/storage_manager.py +1352 -0
  383. lmcache/v1/system_detection.py +110 -0
  384. lmcache/v1/token_database.py +551 -0
  385. lmcache/v1/transfer_channel/__init__.py +83 -0
  386. lmcache/v1/transfer_channel/abstract.py +285 -0
  387. lmcache/v1/transfer_channel/mock_memory_channel.py +156 -0
  388. lmcache/v1/transfer_channel/nixl_channel.py +639 -0
  389. lmcache/v1/transfer_channel/py_socket_channel.py +260 -0
  390. lmcache/v1/transfer_channel/transfer_utils.py +63 -0
  391. lmcache/v1/utils/__init__.py +1 -0
  392. lmcache/v1/utils/bloom_filter.py +109 -0
  393. lmcache/v1/utils/cache_utils.py +125 -0
  394. lmcache_cli-0.4.5.dev0.dist-info/METADATA +185 -0
  395. lmcache_cli-0.4.5.dev0.dist-info/RECORD +399 -0
  396. lmcache_cli-0.4.5.dev0.dist-info/WHEEL +5 -0
  397. lmcache_cli-0.4.5.dev0.dist-info/entry_points.txt +2 -0
  398. lmcache_cli-0.4.5.dev0.dist-info/licenses/LICENSE +201 -0
  399. lmcache_cli-0.4.5.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1 @@
1
+ # SPDX-License-Identifier: Apache-2.0
@@ -0,0 +1,587 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """
3
+ Base classes for health monitoring.
4
+ """
5
+
6
+ # Standard
7
+ from abc import ABC, abstractmethod
8
+ from typing import TYPE_CHECKING, Dict, List, Optional
9
+ import threading
10
+
11
+ # First Party
12
+ from lmcache.logging import init_logger
13
+ from lmcache.v1.exceptions import IrrecoverableException
14
+ from lmcache.v1.health_monitor.constants import (
15
+ DEFAULT_FALLBACK_POLICY,
16
+ DEFAULT_PING_INTERVAL,
17
+ FallbackPolicy,
18
+ )
19
+ from lmcache.v1.periodic_thread import (
20
+ PeriodicThread,
21
+ PeriodicThreadRegistry,
22
+ ThreadLevel,
23
+ ThreadRunSummary,
24
+ )
25
+
26
+ if TYPE_CHECKING:
27
+ # First Party
28
+ from lmcache.v1.manager import LMCacheManager
29
+ from lmcache.v1.storage_backend.local_cpu_backend import LocalCPUBackend
30
+ from lmcache.v1.storage_backend.storage_manager import StorageManager
31
+
32
+ logger = init_logger(__name__)
33
+
34
+
35
+ class HealthCheck(ABC):
36
+ """
37
+ Abstract base class for health checks.
38
+
39
+ Subclasses should implement the check() method to perform specific
40
+ health checks. Each health check represents one aspect of system health.
41
+
42
+ Subclasses must also implement the create() classmethod
43
+ to create instances from a LMCacheManager.
44
+
45
+ Attributes:
46
+ fallback_policy: The fallback policy when this health check fails.
47
+ - RECOMPUTE: Skip all cache operations, fall back to recomputation
48
+ - LOCAL_CPU: Fall back to local CPU backend only
49
+
50
+ Example:
51
+ class DatabaseHealthCheck(HealthCheck):
52
+ def __init__(self, db_connection, fallback_policy=FallbackPolicy.RECOMPUTE):
53
+ self._fallback_policy = fallback_policy
54
+ self.db = db_connection
55
+
56
+ def name(self) -> str:
57
+ return "DatabaseHealthCheck"
58
+
59
+ def check(self) -> bool:
60
+ return self.db.ping()
61
+
62
+ @property
63
+ def fallback_policy(self) -> FallbackPolicy:
64
+ return self._fallback_policy
65
+
66
+ @classmethod
67
+ def create(
68
+ cls, manager: "LMCacheManager"
69
+ ) -> List["HealthCheck"]:
70
+ # Create instances from manager's components
71
+ return [cls(manager.lmcache_engine.db_connection)]
72
+ """
73
+
74
+ @abstractmethod
75
+ def name(self) -> str:
76
+ """Return the name of this health check"""
77
+ pass
78
+
79
+ @abstractmethod
80
+ def check(self) -> bool:
81
+ """
82
+ Perform the health check.
83
+
84
+ Returns:
85
+ bool: True if healthy, False otherwise
86
+ """
87
+ pass
88
+
89
+ @property
90
+ def fallback_policy(self) -> FallbackPolicy:
91
+ """
92
+ Return the fallback policy for this health check.
93
+
94
+ Default is RECOMPUTE. Subclasses can override this property
95
+ to return a different policy.
96
+
97
+ Returns:
98
+ FallbackPolicy: The fallback policy
99
+ """
100
+ return DEFAULT_FALLBACK_POLICY
101
+
102
+ def should_skip(self) -> bool:
103
+ """
104
+ Check if this health check should be skipped.
105
+
106
+ Override this method to conditionally skip checks
107
+ (e.g., if the component doesn't support health checks).
108
+
109
+ Returns:
110
+ bool: True if the check should be skipped, False otherwise
111
+ """
112
+ return False
113
+
114
+ def get_bypass_backend_name(self) -> Optional[str]:
115
+ """
116
+ Return the backend name to bypass when this health check fails
117
+ and fallback_policy is LOCAL_CPU.
118
+
119
+ Override this method to specify the backend name.
120
+
121
+ Returns:
122
+ Optional[str]: The backend name to bypass, or None if not applicable
123
+ """
124
+ return None
125
+
126
+ @classmethod
127
+ @abstractmethod
128
+ def create(cls, manager: "LMCacheManager") -> List["HealthCheck"]:
129
+ """
130
+ Create health check instance(s) from a LMCacheManager.
131
+
132
+ This method should extract the necessary components from the manager
133
+ and create one or more health check instances.
134
+
135
+ Args:
136
+ manager: The LMCacheManager instance
137
+
138
+ Returns:
139
+ List[HealthCheck]: List of health check instances.
140
+ Return empty list if the check is not applicable.
141
+ """
142
+ pass
143
+
144
+
145
+ class HealthMonitor(PeriodicThread):
146
+ """
147
+ Health monitor for the entire LMCache system.
148
+
149
+ This is the unified health monitor for the entire LMCache system.
150
+ It supports extensible health checks and provides a centralized way
151
+ to check the health status of the LMCacheManager.
152
+
153
+ The monitor automatically discovers and instantiates all HealthCheck
154
+ subclasses using their create() method.
155
+
156
+ The monitor runs in a background thread and periodically executes
157
+ all registered health checks. If any check fails, the system is
158
+ marked as unhealthy and appropriate fallback actions are taken
159
+ based on each check's fallback_policy.
160
+
161
+ Fallback Policies:
162
+ - RECOMPUTE: Mark system as unhealthy, skip all cache operations
163
+ - LOCAL_CPU: Bypass the failed backend, use local CPU with hot_cache enabled
164
+
165
+ Usage:
166
+ # Create a health monitor with manager
167
+ health_monitor = HealthMonitor(
168
+ manager=manager,
169
+ ping_interval=30.0
170
+ )
171
+
172
+ # Start monitoring
173
+ health_monitor.start()
174
+
175
+ # Check health status
176
+ if health_monitor.is_healthy():
177
+ # Perform normal operations
178
+ pass
179
+
180
+ # Stop monitoring when done
181
+ health_monitor.stop()
182
+ """
183
+
184
+ def __init__(
185
+ self,
186
+ manager: "LMCacheManager",
187
+ ping_interval: float = DEFAULT_PING_INTERVAL,
188
+ ):
189
+ # Initialize PeriodicThread base class
190
+ super().__init__(
191
+ name="health-monitor-thread",
192
+ interval=ping_interval,
193
+ level=ThreadLevel.CRITICAL,
194
+ init_wait=0.0,
195
+ )
196
+
197
+ self._manager = manager
198
+ self._health_checks: List[HealthCheck] = []
199
+
200
+ # Health status
201
+ self._healthy = True
202
+ self._health_lock = threading.RLock()
203
+
204
+ # Configuration (also stored in base class)
205
+ self._ping_interval = ping_interval
206
+
207
+ # Track which backends are currently bypassed due to health check failures
208
+ # Key: backend_name, Value: check_name that caused the bypass
209
+ self._bypassed_backends: Dict[str, str] = {}
210
+ self._bypass_lock = threading.RLock()
211
+
212
+ # Track original hot_cache setting before any LOCAL_CPU fallback
213
+ # This is a global setting, not per-backend
214
+ # None means no fallback is active, otherwise stores the original use_hot value
215
+ self._original_hot_cache: Optional[bool] = None
216
+
217
+ # Track previous health status per check for detecting recovery
218
+ self._previous_check_status: Dict[str, bool] = {}
219
+
220
+ # Auto-discover and instantiate health checks
221
+ self._discover_health_checks()
222
+
223
+ # Register with the global registry
224
+ PeriodicThreadRegistry.get_instance().register(self)
225
+
226
+ def _discover_health_checks(self) -> None:
227
+ """
228
+ Discover all HealthCheck subclasses and instantiate them.
229
+
230
+ This method dynamically scans all modules in the checks package,
231
+ finds all HealthCheck subclasses and calls their `create()`
232
+ method to create instances.
233
+ """
234
+ # Standard
235
+ import importlib
236
+ import inspect
237
+ import pkgutil
238
+
239
+ # First Party
240
+ # Import the checks package
241
+ import lmcache.v1.health_monitor.checks as checks_pkg
242
+
243
+ # Discover all modules in the checks package
244
+ for _, module_name, _ in pkgutil.iter_modules(checks_pkg.__path__):
245
+ # Skip private modules
246
+ if module_name.startswith("_"):
247
+ continue
248
+
249
+ try:
250
+ module = importlib.import_module(f"{checks_pkg.__name__}.{module_name}")
251
+
252
+ # Find all HealthCheck subclasses in the module
253
+ for _, obj in inspect.getmembers(module):
254
+ if (
255
+ inspect.isclass(obj)
256
+ and issubclass(obj, HealthCheck)
257
+ and obj != HealthCheck
258
+ ):
259
+ try:
260
+ instances = obj.create(self._manager)
261
+ for instance in instances:
262
+ self._health_checks.append(instance)
263
+ # Initialize previous status as healthy
264
+ self._previous_check_status[instance.name()] = True
265
+ logger.info(
266
+ f"Registered health check: {instance.name()} "
267
+ f"with fallback_policy: {instance.fallback_policy}"
268
+ )
269
+ except Exception as e:
270
+ logger.warning(
271
+ f"Failed to create health check {obj.__name__}: {e}"
272
+ )
273
+ except ImportError as e:
274
+ logger.warning(f"Failed to import module {module_name}: {e}")
275
+
276
+ def get_health_checks(self) -> List[HealthCheck]:
277
+ """Get all registered health checks"""
278
+ return list(self._health_checks)
279
+
280
+ def is_healthy(self) -> bool:
281
+ """
282
+ Check if the system is currently healthy.
283
+
284
+ Returns:
285
+ bool: True if healthy, False otherwise
286
+ """
287
+ with self._health_lock:
288
+ return self._healthy
289
+
290
+ def _set_healthy(self, healthy: bool) -> None:
291
+ """Set the health status"""
292
+ with self._health_lock:
293
+ if self._healthy != healthy:
294
+ if healthy:
295
+ logger.info(
296
+ "HealthMonitor: System recovered, restoring normal operations"
297
+ )
298
+ else:
299
+ logger.warning(
300
+ "HealthMonitor: System unhealthy, entering degraded mode"
301
+ )
302
+ self._healthy = healthy
303
+
304
+ def _get_storage_manager(self) -> Optional["StorageManager"]:
305
+ """Get the storage manager from the cache engine."""
306
+ engine = self._manager.lmcache_engine
307
+ if engine is None:
308
+ return None
309
+ return engine.storage_manager
310
+
311
+ def _get_local_cpu_backend(
312
+ self, storage_manager: "StorageManager"
313
+ ) -> Optional["LocalCPUBackend"]:
314
+ """
315
+ Get the LocalCPUBackend from the storage manager with proper type.
316
+
317
+ Args:
318
+ storage_manager: The storage manager instance
319
+
320
+ Returns:
321
+ Optional[LocalCPUBackend]: The LocalCPUBackend instance, or None
322
+ """
323
+ # First Party
324
+ from lmcache.v1.storage_backend.local_cpu_backend import LocalCPUBackend
325
+
326
+ backend = storage_manager.local_cpu_backend
327
+ if backend is not None and isinstance(backend, LocalCPUBackend):
328
+ return backend
329
+ return None
330
+
331
+ def _apply_local_cpu_fallback(self, check: HealthCheck) -> None:
332
+ """
333
+ Apply LOCAL_CPU fallback policy for a failed health check.
334
+
335
+ This will:
336
+ 1. Enable bypass for the specified backend in StorageManager
337
+ 2. Enable hot_cache for LocalCPUBackend (only on first fallback)
338
+
339
+ Args:
340
+ check: The health check that failed
341
+ """
342
+ backend_name = check.get_bypass_backend_name()
343
+ if backend_name is None:
344
+ logger.warning(
345
+ f"Health check {check.name()} has LOCAL_CPU fallback but "
346
+ "get_bypass_backend_name() returned None"
347
+ )
348
+ return
349
+
350
+ storage_manager = self._get_storage_manager()
351
+ if storage_manager is None:
352
+ logger.warning("StorageManager is not available for fallback")
353
+ return
354
+
355
+ with self._bypass_lock:
356
+ if backend_name in self._bypassed_backends:
357
+ # Already bypassed
358
+ return
359
+
360
+ local_cpu = self._get_local_cpu_backend(storage_manager)
361
+
362
+ # Save original hot_cache setting only on the first fallback
363
+ # (when no backends are bypassed yet)
364
+ if len(self._bypassed_backends) == 0:
365
+ if local_cpu is not None:
366
+ self._original_hot_cache = local_cpu.use_hot
367
+ else:
368
+ self._original_hot_cache = None
369
+
370
+ # Enable bypass for the backend
371
+ storage_manager.set_backend_bypass(backend_name, True)
372
+
373
+ # Enable hot_cache for LocalCPUBackend
374
+ if local_cpu is not None:
375
+ local_cpu.use_hot = True
376
+ logger.info(
377
+ f"Enabled hot_cache for LocalCPUBackend due to "
378
+ f"{check.name()} failure"
379
+ )
380
+
381
+ # Record this backend as bypassed
382
+ self._bypassed_backends[backend_name] = check.name()
383
+
384
+ logger.info(
385
+ f"Applied LOCAL_CPU fallback for {check.name()}: "
386
+ f"bypassing {backend_name}"
387
+ )
388
+
389
+ def _recover_from_local_cpu_fallback(self, check: HealthCheck) -> None:
390
+ """
391
+ Recover from LOCAL_CPU fallback when a health check passes again.
392
+
393
+ This will:
394
+ 1. Disable bypass for the specified backend in StorageManager
395
+ 2. Only when ALL backends have recovered:
396
+ - Restore original hot_cache setting for LocalCPUBackend
397
+ - Clear hot_cache if it was originally disabled
398
+
399
+ Args:
400
+ check: The health check that recovered
401
+ """
402
+ backend_name = check.get_bypass_backend_name()
403
+ if backend_name is None:
404
+ return
405
+
406
+ storage_manager = self._get_storage_manager()
407
+ if storage_manager is None:
408
+ return
409
+
410
+ with self._bypass_lock:
411
+ if backend_name not in self._bypassed_backends:
412
+ # Not in bypassed state
413
+ return
414
+
415
+ check_name = self._bypassed_backends[backend_name]
416
+
417
+ # Verify this is the same check that caused the bypass
418
+ if check_name != check.name():
419
+ return
420
+
421
+ # Disable bypass for the backend
422
+ storage_manager.set_backend_bypass(backend_name, False)
423
+
424
+ # Remove from bypassed backends
425
+ del self._bypassed_backends[backend_name]
426
+
427
+ logger.info(
428
+ f"Recovered from LOCAL_CPU fallback for {check.name()}: "
429
+ f"restored {backend_name}"
430
+ )
431
+
432
+ # Only restore hot_cache when ALL backends have recovered
433
+ if len(self._bypassed_backends) == 0:
434
+ local_cpu = self._get_local_cpu_backend(storage_manager)
435
+ if local_cpu is not None and self._original_hot_cache is not None:
436
+ # First, restore the original hot_cache setting
437
+ # This prevents new data from being written during clear()
438
+ local_cpu.use_hot = self._original_hot_cache
439
+ logger.info(
440
+ f"Restored hot_cache setting to {self._original_hot_cache} "
441
+ f"for LocalCPUBackend (all backends restored)"
442
+ )
443
+
444
+ # Then, clear hot_cache if it was originally disabled
445
+ # At this point, use_hot is already False, so no new data
446
+ # will be written during the potentially long clear() operation
447
+ if not self._original_hot_cache:
448
+ local_cpu.clear()
449
+ logger.info(
450
+ "Cleared hot_cache for LocalCPUBackend during recovery "
451
+ "(all backends restored)"
452
+ )
453
+ # Reset original_hot_cache tracker
454
+ self._original_hot_cache = None
455
+
456
+ def _run_all_checks(self) -> bool:
457
+ """
458
+ Run all health checks.
459
+
460
+ Returns:
461
+ bool: True if all checks pass (considering fallback policies),
462
+ False if any check with RECOMPUTE policy fails
463
+
464
+ Raises:
465
+ IrrecoverableException: If any check raises an irrecoverable error
466
+ """
467
+ all_healthy = True
468
+
469
+ for check in self._health_checks:
470
+ if check.should_skip():
471
+ continue
472
+
473
+ check_name = check.name()
474
+ was_healthy = self._previous_check_status.get(check_name, True)
475
+
476
+ try:
477
+ is_healthy = check.check()
478
+ except IrrecoverableException:
479
+ logger.error(f"Health check {check_name} raised IrrecoverableException")
480
+ raise
481
+ except Exception as e:
482
+ logger.error(f"Health check {check_name} raised exception: {e}")
483
+ is_healthy = False
484
+
485
+ # Update previous status
486
+ self._previous_check_status[check_name] = is_healthy
487
+
488
+ if is_healthy:
489
+ # Check recovered
490
+ if not was_healthy:
491
+ logger.info(f"Health check {check_name} recovered")
492
+ # If this check was using LOCAL_CPU fallback, recover
493
+ if check.fallback_policy == FallbackPolicy.LOCAL_CPU:
494
+ self._recover_from_local_cpu_fallback(check)
495
+ else:
496
+ # Check failed
497
+ logger.warning(f"Health check failed: {check_name}")
498
+
499
+ if check.fallback_policy == FallbackPolicy.RECOMPUTE:
500
+ # RECOMPUTE policy: mark as unhealthy
501
+ all_healthy = False
502
+ elif check.fallback_policy == FallbackPolicy.LOCAL_CPU:
503
+ # LOCAL_CPU policy: apply fallback
504
+ self._apply_local_cpu_fallback(check)
505
+ # System is still considered healthy with LOCAL_CPU fallback
506
+
507
+ return all_healthy
508
+
509
+ def start(self) -> Optional[threading.Thread]:
510
+ """
511
+ Start the health monitor thread.
512
+
513
+ Returns:
514
+ Optional[threading.Thread]: The started thread,
515
+ or None if no checks need monitoring
516
+ """
517
+ # Check if we have any health checks that need to run
518
+ active_checks = [c for c in self._health_checks if not c.should_skip()]
519
+ if not active_checks:
520
+ logger.info("No active health checks to monitor, skipping monitor thread")
521
+ # Set last_summary even when not starting
522
+ self._last_summary = ThreadRunSummary(
523
+ success=True,
524
+ message="No active health checks to monitor, thread not started",
525
+ extra_info={
526
+ "total_checks": str(len(self._health_checks)),
527
+ "active_checks": "0",
528
+ "skipped": "true",
529
+ },
530
+ )
531
+ self._level = ThreadLevel.LOW
532
+ return None
533
+
534
+ # Use the base class start method
535
+ thread = super().start()
536
+ if thread is not None:
537
+ logger.info(
538
+ f"Started health monitor thread with "
539
+ f"{len(active_checks)} active checks, "
540
+ f"interval: {self._ping_interval}s"
541
+ )
542
+ return thread
543
+
544
+ def stop(self, timeout: float = 5.0) -> None:
545
+ """Stop the health monitor thread"""
546
+ # Unregister from the global registry
547
+ PeriodicThreadRegistry.get_instance().unregister(self.name)
548
+ # Use base class stop method
549
+ super().stop(timeout)
550
+
551
+ def _execute(self) -> ThreadRunSummary:
552
+ """
553
+ Execute one health check cycle.
554
+
555
+ This method is called by the PeriodicThread base class.
556
+
557
+ Returns:
558
+ ThreadRunSummary: Summary of the health check cycle
559
+ """
560
+ try:
561
+ # Run all health checks
562
+ is_healthy = self._run_all_checks()
563
+ self._set_healthy(is_healthy)
564
+
565
+ # Build summary
566
+ failed_checks = [
567
+ name
568
+ for name, healthy in self._previous_check_status.items()
569
+ if not healthy
570
+ ]
571
+
572
+ return ThreadRunSummary(
573
+ success=is_healthy,
574
+ message="All checks passed"
575
+ if is_healthy
576
+ else f"Failed checks: {failed_checks}",
577
+ extra_info={
578
+ "total_checks": str(len(self._health_checks)),
579
+ "failed_checks": str(len(failed_checks)),
580
+ "bypassed_backends": str(len(self._bypassed_backends)),
581
+ },
582
+ )
583
+ except IrrecoverableException as e:
584
+ logger.error(f"Irrecoverable error in health monitor: {e}")
585
+ self._set_healthy(False)
586
+ # Re-raise to stop the thread
587
+ raise
@@ -0,0 +1 @@
1
+ # SPDX-License-Identifier: Apache-2.0