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,385 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
3
+ """
4
+ Configuration for L2 adapters.
5
+
6
+ Supports multiple adapter instances (including multiple instances of the same
7
+ adapter type with different configs) via repeatable --l2-adapter <JSON>.
8
+ Each JSON object must include "type" (adapter type name) and type-specific keys.
9
+ """
10
+
11
+ # Future
12
+ from __future__ import annotations
13
+
14
+ # Standard
15
+ from abc import ABC, abstractmethod
16
+ from dataclasses import dataclass
17
+ from typing import TYPE_CHECKING, TypeVar
18
+ import argparse
19
+ import json
20
+
21
+ if TYPE_CHECKING:
22
+ # First Party
23
+ from lmcache.v1.distributed.config import EvictionConfig
24
+
25
+ # First Party
26
+ from lmcache.logging import init_logger
27
+
28
+ logger = init_logger(__name__)
29
+
30
+ T = TypeVar("T", bound="L2AdapterConfigBase")
31
+
32
+
33
+ @dataclass(frozen=True)
34
+ class PersistConfig:
35
+ """
36
+ Configuration for persist on an L2 adapter.
37
+
38
+ When enabled, data files are kept on disk at shutdown instead of
39
+ deleted. Lookup always checks secondary storage (disk) on miss
40
+ regardless of this setting.
41
+ """
42
+
43
+ persist_enabled: bool = True
44
+ """ If True, data files are kept on disk at shutdown instead of deleted. """
45
+
46
+
47
+ # -----------------------------------------------------------------------------
48
+ # Registry: adapter type name -> config class
49
+ # -----------------------------------------------------------------------------
50
+
51
+ _L2_ADAPTER_CONFIG_REGISTRY: dict[str, type[L2AdapterConfigBase]] = {}
52
+
53
+
54
+ def register_l2_adapter_type(
55
+ name: str,
56
+ config_cls: type[L2AdapterConfigBase],
57
+ ) -> None:
58
+ """
59
+ Register an L2 adapter config class under a type name.
60
+
61
+ The type name is used in JSON specs as the "type" field.
62
+ Each adapter config module should call this at import time.
63
+
64
+ Args:
65
+ name: Adapter type name (e.g. "fs", "mock").
66
+ config_cls: Config class that can parse from dict
67
+ via ``from_dict()``.
68
+ """
69
+ if name in _L2_ADAPTER_CONFIG_REGISTRY:
70
+ raise ValueError("L2 adapter type already registered: %s" % repr(name))
71
+ _L2_ADAPTER_CONFIG_REGISTRY[name] = config_cls
72
+
73
+
74
+ def _ensure_config_loaded(name: str) -> None:
75
+ """Trigger lazy import for *name* if it is not
76
+ yet in the config registry.
77
+
78
+ Raises:
79
+ ImportError: If the adapter module cannot be
80
+ imported (missing dependency).
81
+ """
82
+ if name in _L2_ADAPTER_CONFIG_REGISTRY:
83
+ return
84
+ # Lazy import lives in factory to avoid circular deps
85
+ # First Party
86
+ from lmcache.v1.distributed.l2_adapters.factory import ( # noqa: PLC0415
87
+ ensure_adapter_loaded,
88
+ )
89
+
90
+ ensure_adapter_loaded(name)
91
+
92
+
93
+ def get_registered_l2_adapter_types() -> list[str]:
94
+ """Return all known adapter type names (eager
95
+ and lazy)."""
96
+ # First Party
97
+ from lmcache.v1.distributed.l2_adapters.factory import ( # noqa: PLC0415
98
+ get_all_registered_names,
99
+ )
100
+
101
+ return get_all_registered_names()
102
+
103
+
104
+ def get_type_name_for_config(
105
+ config: L2AdapterConfigBase,
106
+ ) -> str:
107
+ """
108
+ Reverse-lookup the registered type name for a config
109
+ instance.
110
+
111
+ Args:
112
+ config: An L2 adapter config instance.
113
+
114
+ Returns:
115
+ The registered type name (e.g., "mock", "fs").
116
+
117
+ Raises:
118
+ ValueError: If the config's class is not registered.
119
+ """
120
+ for name, cls in _L2_ADAPTER_CONFIG_REGISTRY.items():
121
+ if type(config) is cls:
122
+ return name
123
+ raise ValueError("Unregistered L2 adapter config type: %s" % type(config).__name__)
124
+
125
+
126
+ # -----------------------------------------------------------------------------
127
+ # Base config class for a single L2 adapter
128
+ # -----------------------------------------------------------------------------
129
+
130
+
131
+ class L2AdapterConfigBase(ABC):
132
+ """
133
+ Base class for per-adapter configs.
134
+
135
+ Each adapter type (e.g. disk, redis) defines a config class that:
136
+ - Subclasses this base.
137
+ - Implements from_dict() to parse a dict (from JSON) into an instance.
138
+ - Is registered via register_l2_adapter_type("type_name", ConfigClass).
139
+
140
+ An optional ``"eviction"`` key in the JSON dict enables per-adapter L2
141
+ eviction. When present it is parsed by ``_parse_eviction_config()`` and
142
+ stored on ``eviction_config``; the L2EvictionController is then created
143
+ for this adapter in the StorageManager.
144
+ """
145
+
146
+ #: Populated by ``_parse_eviction_config`` after ``from_dict``; ``None``
147
+ #: means L2 eviction is disabled for this adapter.
148
+ eviction_config: EvictionConfig | None = None
149
+
150
+ #: Populated by ``_parse_persist_config`` after ``from_dict``.
151
+ #: Defaults to ``PersistConfig()`` (persist enabled).
152
+ persist_config: PersistConfig = PersistConfig()
153
+
154
+ @staticmethod
155
+ def _parse_eviction_config(d: dict) -> EvictionConfig | None:
156
+ """
157
+ Parse an optional ``"eviction"`` sub-dict from an adapter JSON spec.
158
+
159
+ Expected format::
160
+
161
+ {
162
+ "type": "mock",
163
+ ...
164
+ "eviction": {
165
+ "eviction_policy": "LRU",
166
+ "trigger_watermark": 0.8,
167
+ "eviction_ratio": 0.2
168
+ }
169
+ }
170
+
171
+ Returns ``None`` when the key is absent (eviction disabled).
172
+ """
173
+ eviction_dict = d.get("eviction")
174
+ if eviction_dict is None:
175
+ return None
176
+
177
+ # Lazy import to avoid circular dependency:
178
+ # l2_adapters/config.py <- config.py <- l2_adapters/config.py
179
+ # First Party
180
+ from lmcache.v1.distributed.config import EvictionConfig # noqa: PLC0415
181
+
182
+ policy = eviction_dict.get("eviction_policy")
183
+ if policy not in ("LRU", "noop"):
184
+ raise ValueError(
185
+ f"eviction.eviction_policy must be 'LRU' or 'noop', got {policy!r}"
186
+ )
187
+ return EvictionConfig(
188
+ eviction_policy=policy,
189
+ trigger_watermark=float(eviction_dict.get("trigger_watermark", 0.8)),
190
+ eviction_ratio=float(eviction_dict.get("eviction_ratio", 0.2)),
191
+ )
192
+
193
+ @staticmethod
194
+ def _parse_persist_config(d: dict) -> PersistConfig:
195
+ """
196
+ Parse optional ``"persist_enabled"`` key from an adapter JSON spec.
197
+
198
+ Defaults to ``True``.
199
+
200
+ Expected format::
201
+
202
+ {
203
+ "type": "nixl_store_dynamic",
204
+ ...
205
+ "persist_enabled": true
206
+ }
207
+ """
208
+ persist_enabled = bool(d.get("persist_enabled", True))
209
+ return PersistConfig(persist_enabled=persist_enabled)
210
+
211
+ @classmethod
212
+ @abstractmethod
213
+ def from_dict(cls: type[T], d: dict) -> T:
214
+ """
215
+ Build a config instance from a dict (e.g. from parsed JSON).
216
+
217
+ The dict will contain the "type" key used for dispatch; the concrete
218
+ class may ignore it. All other keys are type-specific.
219
+
220
+ Args:
221
+ d: Adapter spec dict (must include type-specific keys).
222
+
223
+ Returns:
224
+ An instance of the config class.
225
+
226
+ Raises:
227
+ ValueError: If required keys are missing or values are invalid.
228
+ """
229
+ ...
230
+
231
+ @classmethod
232
+ @abstractmethod
233
+ def help(cls) -> str:
234
+ """
235
+ Return a help string describing the config fields for this adapter type.
236
+
237
+ This is used in command-line help to explain the expected JSON format for
238
+ each adapter type.
239
+
240
+ Returns:
241
+ A help string describing the config fields for this adapter type.
242
+ """
243
+ ...
244
+
245
+
246
+ # -----------------------------------------------------------------------------
247
+ # Main config: list of adapter configs (order = adapter order)
248
+ # -----------------------------------------------------------------------------
249
+
250
+
251
+ @dataclass
252
+ class L2AdaptersConfig:
253
+ """
254
+ Main config for L2 adapters.
255
+
256
+ Holds an ordered list of adapter configs. Each element corresponds to one
257
+ L2 adapter instance (e.g. two disk adapters with different paths appear
258
+ as two entries).
259
+ """
260
+
261
+ adapters: list[L2AdapterConfigBase]
262
+ """ Ordered list of adapter configs; one per L2 adapter instance. """
263
+
264
+
265
+ # -----------------------------------------------------------------------------
266
+ # Command-line: add args and parse to config
267
+ # -----------------------------------------------------------------------------
268
+
269
+ _L2_ADAPTER_ARG_DEST = "l2_adapter"
270
+
271
+
272
+ def add_l2_adapters_args(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
273
+ """
274
+ Add L2 adapter configuration arguments to an existing parser.
275
+
276
+ Adds a repeatable --l2-adapter <JSON> argument. Each JSON object specifies
277
+ one adapter: it must include "type" (registered adapter type name) and
278
+ type-specific keys. Order of arguments is the order of adapters.
279
+
280
+ Args:
281
+ parser: The argument parser to add arguments to.
282
+
283
+ Returns:
284
+ The same parser with L2 adapter arguments added.
285
+
286
+ Example:
287
+ >>> parser = argparse.ArgumentParser()
288
+ >>> add_l2_adapters_args(parser)
289
+ >>> args = parser.parse_args(["--l2-adapter", '{"type":"disk","path":"/data"}'])
290
+ >>> config = parse_args_to_l2_adapters_config(args)
291
+ """
292
+ group = parser.add_argument_group(
293
+ "L2 Adapters",
294
+ "L2 adapter instances. Each --l2-adapter is a JSON object with 'type' and "
295
+ "type-specific keys. Repeat for multiple adapters.",
296
+ )
297
+ group.add_argument(
298
+ "--l2-adapter",
299
+ dest=_L2_ADAPTER_ARG_DEST,
300
+ action="append",
301
+ default=[],
302
+ type=str,
303
+ metavar="JSON",
304
+ help='Adapter spec as JSON with a "type" field and adapter-specific configs'
305
+ ', e.g. \'{"type":"disk","path":"/data"}\'.'
306
+ "Repeat for multiple adapters."
307
+ "Supported adapters are: ["
308
+ + ", ".join(sorted(get_registered_l2_adapter_types()))
309
+ + "].",
310
+ )
311
+ return parser
312
+
313
+
314
+ def parse_args_to_l2_adapters_config(args: argparse.Namespace) -> L2AdaptersConfig:
315
+ """
316
+ Build L2AdaptersConfig from parsed command-line arguments.
317
+
318
+ Expects args to have the attribute added by add_l2_adapters_args (a list
319
+ of JSON strings). Each string is parsed; the "type" field selects the
320
+ config class from the registry, and from_dict() builds the config instance.
321
+
322
+ Args:
323
+ args: Parsed arguments (e.g. from parser.parse_args()).
324
+
325
+ Returns:
326
+ L2AdaptersConfig with one entry per --l2-adapter argument.
327
+
328
+ Raises:
329
+ KeyError: If an adapter "type" is not registered.
330
+ ValueError: If JSON is invalid or a config class raises from_dict().
331
+ """
332
+ raw_list = getattr(args, _L2_ADAPTER_ARG_DEST, None)
333
+ if raw_list is None:
334
+ raw_list = []
335
+
336
+ adapter_configs: list[L2AdapterConfigBase] = []
337
+ for i, raw in enumerate(raw_list):
338
+ try:
339
+ d = json.loads(raw)
340
+ except json.JSONDecodeError as e:
341
+ raise ValueError(f"Invalid JSON for --l2-adapter #{i + 1}: {e}") from e
342
+
343
+ if not isinstance(d, dict):
344
+ raise ValueError(
345
+ f"--l2-adapter #{i + 1}: expected a JSON object, got {type(d).__name__}"
346
+ )
347
+
348
+ type_name = d.get("type")
349
+ if type_name is None:
350
+ raise ValueError("--l2-adapter #%d: missing 'type' field" % (i + 1))
351
+
352
+ # Trigger lazy import for this adapter type
353
+ _ensure_config_loaded(type_name)
354
+
355
+ if type_name not in _L2_ADAPTER_CONFIG_REGISTRY:
356
+ known = ", ".join(sorted(_L2_ADAPTER_CONFIG_REGISTRY)) or "(none)"
357
+ raise ValueError(
358
+ f"--l2-adapter #{i + 1}: unknown adapter type "
359
+ f"{type_name!r}. Known: {known}"
360
+ )
361
+
362
+ config_cls = _L2_ADAPTER_CONFIG_REGISTRY[type_name]
363
+ try:
364
+ adapter_cfg = config_cls.from_dict(d)
365
+ adapter_cfg.eviction_config = L2AdapterConfigBase._parse_eviction_config(d)
366
+ adapter_cfg.persist_config = L2AdapterConfigBase._parse_persist_config(d)
367
+ adapter_configs.append(adapter_cfg)
368
+ except (TypeError, ValueError) as e:
369
+ logger.error(
370
+ "Error parsing --l2-adapter #%d (type %r): %s",
371
+ i + 1,
372
+ type_name,
373
+ e,
374
+ )
375
+ logger.error(
376
+ "Adapter config help for %s adapter:\n"
377
+ "---------------------\n"
378
+ "%s\n"
379
+ "---------------------\n\n",
380
+ type_name,
381
+ config_cls.help(),
382
+ )
383
+ raise ValueError(f"--l2-adapter #{i + 1} ({type_name!r}): {e}") from e
384
+
385
+ return L2AdaptersConfig(adapters=adapter_configs)
@@ -0,0 +1,205 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """
3
+ Factory registry for L2 adapters.
4
+
5
+ Each adapter module self-registers a factory callable via
6
+ ``register_l2_adapter_factory`` at import time. The factory
7
+ signature is
8
+ ``(L2AdapterConfigBase, Optional[L1MemoryDesc]) -> L2AdapterInterface``.
9
+
10
+ Built-in adapters are discovered via ``pkgutil`` but only
11
+ imported on demand -- their modules (and third-party
12
+ dependencies) are loaded only when the adapter type is
13
+ actually requested.
14
+ """
15
+
16
+ # Future
17
+ from __future__ import annotations
18
+
19
+ # Standard
20
+ from typing import TYPE_CHECKING, Callable, Optional
21
+ import importlib
22
+
23
+ if TYPE_CHECKING:
24
+ from lmcache.v1.distributed.internal_api import (
25
+ L1MemoryDesc,
26
+ )
27
+ from lmcache.v1.distributed.l2_adapters.base import (
28
+ L2AdapterInterface,
29
+ )
30
+ from lmcache.v1.distributed.l2_adapters.config import (
31
+ L2AdapterConfigBase,
32
+ )
33
+
34
+ # First Party
35
+ from lmcache.logging import init_logger
36
+
37
+ logger = init_logger(__name__)
38
+
39
+ # Type alias for factory callables:
40
+ # (config, l1_memory_desc) -> L2AdapterInterface
41
+ L2AdapterFactory = Callable[
42
+ ["L2AdapterConfigBase", "Optional[L1MemoryDesc]"],
43
+ "L2AdapterInterface",
44
+ ]
45
+
46
+ # -----------------------------------------------------------------
47
+ # Registry: adapter type name -> factory callable
48
+ # -----------------------------------------------------------------
49
+
50
+ _L2_ADAPTER_FACTORY_REGISTRY: dict[str, L2AdapterFactory] = {}
51
+
52
+ # -----------------------------------------------------------------
53
+ # Pending modules: fully-qualified module paths that have
54
+ # been discovered (e.g. via pkgutil) but not yet imported.
55
+ # When a type name is not found in the eager registry we
56
+ # import these one-by-one until the name appears.
57
+ # -----------------------------------------------------------------
58
+
59
+ _PENDING_MODULES: list[str] = []
60
+
61
+
62
+ def register_l2_adapter_factory(
63
+ name: str,
64
+ factory: L2AdapterFactory,
65
+ ) -> None:
66
+ """Register an adapter factory for the given type
67
+ name.
68
+
69
+ Each adapter module should call this at import time
70
+ **after** its config class has been registered via
71
+ ``register_l2_adapter_type``.
72
+
73
+ Args:
74
+ name: Adapter type name (must match the name used
75
+ in ``register_l2_adapter_type``).
76
+ factory: ``(config, l1_memory_desc)``
77
+ -> ``L2AdapterInterface``.
78
+ """
79
+ if name in _L2_ADAPTER_FACTORY_REGISTRY:
80
+ raise ValueError("L2 adapter factory already registered: %s" % name)
81
+ _L2_ADAPTER_FACTORY_REGISTRY[name] = factory
82
+
83
+
84
+ def add_pending_module(module_path: str) -> None:
85
+ """Register a module path for deferred import.
86
+
87
+ The module will only be imported when a type name
88
+ lookup misses the eager registry. Importing the
89
+ module triggers its ``register_l2_adapter_type``
90
+ and ``register_l2_adapter_factory`` calls.
91
+
92
+ Args:
93
+ module_path: Fully-qualified module path
94
+ (e.g. ``"lmcache.v1.distributed.
95
+ l2_adapters.fs_l2_adapter"``).
96
+ """
97
+ if module_path not in _PENDING_MODULES:
98
+ _PENDING_MODULES.append(module_path)
99
+
100
+
101
+ def ensure_adapter_loaded(name: str) -> None:
102
+ """Import pending modules until *name* appears in
103
+ the factory registry (or all pending modules have
104
+ been tried).
105
+
106
+ Raises:
107
+ ImportError: If a module fails to import due to
108
+ a missing third-party dependency **and** it
109
+ was the last candidate.
110
+ """
111
+ if name in _L2_ADAPTER_FACTORY_REGISTRY:
112
+ return
113
+
114
+ last_err: ImportError | None = None
115
+ while _PENDING_MODULES:
116
+ mod_path = _PENDING_MODULES.pop(0)
117
+ try:
118
+ importlib.import_module(mod_path)
119
+ except ImportError as exc:
120
+ logger.debug(
121
+ "Skipping module %s (import failed: %s)",
122
+ mod_path,
123
+ exc,
124
+ )
125
+ last_err = exc
126
+ continue
127
+ # Check if the name is now registered
128
+ if name in _L2_ADAPTER_FACTORY_REGISTRY:
129
+ return
130
+
131
+ # If we exhausted all pending modules and still
132
+ # didn't find the name, the last ImportError (if
133
+ # any) might be the root cause.
134
+ if last_err is not None and name not in _L2_ADAPTER_FACTORY_REGISTRY:
135
+ raise last_err
136
+
137
+
138
+ def load_all_adapters() -> None:
139
+ """Force-import all pending adapter modules.
140
+
141
+ Useful for CLI help that needs to list every
142
+ registered type name.
143
+ """
144
+ while _PENDING_MODULES:
145
+ mod_path = _PENDING_MODULES.pop(0)
146
+ try:
147
+ importlib.import_module(mod_path)
148
+ except ImportError:
149
+ logger.debug(
150
+ "Skipping module %s during bulk load",
151
+ mod_path,
152
+ )
153
+
154
+
155
+ def get_all_registered_names() -> list[str]:
156
+ """Return all known adapter type names.
157
+
158
+ Forces import of all pending modules so that the
159
+ returned list is complete.
160
+ """
161
+ load_all_adapters()
162
+ return sorted(_L2_ADAPTER_FACTORY_REGISTRY)
163
+
164
+
165
+ def create_l2_adapter_from_registry(
166
+ config: "L2AdapterConfigBase",
167
+ l1_memory_desc: "Optional[L1MemoryDesc]" = None,
168
+ ) -> "L2AdapterInterface":
169
+ """Create an L2 adapter using the factory registry.
170
+
171
+ Looks up the type name for *config* via the config
172
+ registry, then calls the matching factory.
173
+
174
+ Args:
175
+ config: An adapter config instance.
176
+ l1_memory_desc: Optional L1 memory descriptor,
177
+ required by adapters that register L1 memory
178
+ with an external backend (e.g. Nixl).
179
+
180
+ Returns:
181
+ A new ``L2AdapterInterface`` instance.
182
+
183
+ Raises:
184
+ ValueError: If no factory is registered for this
185
+ config type.
186
+ """
187
+ # Import here to avoid circular dependency
188
+ # First Party
189
+ from lmcache.v1.distributed.l2_adapters.config import (
190
+ get_type_name_for_config,
191
+ )
192
+
193
+ name = get_type_name_for_config(config)
194
+
195
+ # Trigger lazy import if needed
196
+ ensure_adapter_loaded(name)
197
+
198
+ factory = _L2_ADAPTER_FACTORY_REGISTRY.get(name)
199
+ if factory is None:
200
+ raise ValueError(
201
+ "No adapter factory registered for type "
202
+ "%s. Make sure the adapter module is "
203
+ "imported." % name
204
+ )
205
+ return factory(config, l1_memory_desc)