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,443 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Standard
3
+ from abc import ABC, abstractmethod
4
+ from dataclasses import dataclass, field
5
+ from typing import Dict, List, Optional
6
+ from urllib.parse import parse_qs, urlparse
7
+ import asyncio
8
+ import importlib
9
+ import inspect
10
+ import pkgutil
11
+
12
+ # First Party
13
+ from lmcache.logging import init_logger
14
+ from lmcache.v1.config import LMCacheEngineConfig
15
+ from lmcache.v1.metadata import LMCacheMetadata
16
+ from lmcache.v1.storage_backend.connector.base_connector import RemoteConnector
17
+ from lmcache.v1.storage_backend.connector.instrumented_connector import (
18
+ InstrumentedRemoteConnector,
19
+ )
20
+ from lmcache.v1.storage_backend.local_cpu_backend import LocalCPUBackend
21
+
22
+ logger = init_logger(__name__)
23
+
24
+
25
+ @dataclass
26
+ class ParsedRemoteURL:
27
+ """
28
+ The parsed URL of the format:
29
+ <host>:<port>[/path][?query]
30
+ """
31
+
32
+ host: str
33
+ port: int
34
+ path: str
35
+ username: Optional[str] = None
36
+ password: Optional[str] = None
37
+ query_params: Dict[str, List[str]] = field(default_factory=dict)
38
+
39
+
40
+ def parse_remote_url(url: str) -> ParsedRemoteURL:
41
+ """
42
+ Parses the remote URL into its constituent parts with support for:
43
+ - Multiple hosts (comma-separated)
44
+ - Path and query parameters in each host definition
45
+ - Forward compatibility with legacy format
46
+
47
+ Args:
48
+ url: The URL to parse
49
+
50
+ Returns:
51
+ ParsedRemoteURL: The parsed URL components
52
+
53
+ Raises:
54
+ ValueError: If the URL is invalid
55
+ """
56
+
57
+ logger.debug(f"Parsing remote URL: {url}")
58
+ parsed = urlparse(url)
59
+
60
+ username = parsed.username
61
+ password = parsed.password
62
+ host = parsed.hostname
63
+ port = parsed.port
64
+ path = parsed.path if parsed.path else ""
65
+ query = parse_qs(parsed.query) if parsed.query else {}
66
+
67
+ assert host is not None, f"Invalid URL {url}: missing host"
68
+ assert port is not None, f"Invalid URL {url}: missing port"
69
+ return ParsedRemoteURL(
70
+ host=host,
71
+ port=port,
72
+ path=path,
73
+ username=username,
74
+ password=password,
75
+ query_params=query,
76
+ )
77
+
78
+
79
+ class SafeLocalCPUBackend(LocalCPUBackend):
80
+ """
81
+ A safe stub for LocalCPUBackend that can be used when local_cpu_backend is None.
82
+ """
83
+
84
+ def __init__(self, config: LMCacheEngineConfig):
85
+ pass
86
+
87
+ def allocate(self, *args, **kwargs):
88
+ raise RuntimeError(
89
+ "SafeLocalCPUBackend.allocate() should never be called. "
90
+ "This indicates a bug where scheduler role is trying to allocate memory."
91
+ )
92
+
93
+ def __str__(self):
94
+ return "SafeLocalCPUBackend(dummy)"
95
+
96
+
97
+ def extract_plugin_type(plugin_name: str) -> str:
98
+ """Extract the type portion from a plugin name.
99
+
100
+ Plugin name format: ``{type}`` or ``{type}.{instance}``.
101
+ Returns the *type* part so that adapters can match by type.
102
+
103
+ Examples:
104
+ >>> extract_plugin_type("fs")
105
+ 'fs'
106
+ >>> extract_plugin_type("fs.primary")
107
+ 'fs'
108
+ """
109
+ return plugin_name.split(".", 1)[0]
110
+
111
+
112
+ class ConnectorContext:
113
+ """
114
+ Context for creating a connector.
115
+
116
+ Attributes:
117
+ url: The remote URL
118
+ loop: The asyncio event loop
119
+ local_cpu_backend: The local CPU backend
120
+ (wrapped as SafeLocalCPUBackend if None)
121
+ config: Optional LMCache engine configuration
122
+ plugin_name: Optional plugin instance name
123
+ (e.g. "fs", "fs.primary")
124
+ """
125
+
126
+ def __init__(
127
+ self,
128
+ url: str,
129
+ loop: asyncio.AbstractEventLoop,
130
+ local_cpu_backend: Optional[LocalCPUBackend],
131
+ config: Optional[LMCacheEngineConfig],
132
+ metadata: Optional[LMCacheMetadata],
133
+ plugin_name: Optional[str] = None,
134
+ ):
135
+ self.url = url
136
+ self.loop = loop
137
+ # Wrap None as SafeLocalCPUBackend to satisfy type requirements
138
+ # The SafeLocalCPUBackend will raise an error if allocate() is called
139
+ self.local_cpu_backend: LocalCPUBackend = (
140
+ local_cpu_backend
141
+ if local_cpu_backend is not None
142
+ else SafeLocalCPUBackend(config)
143
+ )
144
+ self.config = config
145
+ self.metadata = metadata
146
+ self.plugin_name = plugin_name
147
+
148
+ def get_full_chunk_size_bytes(self) -> int:
149
+ """
150
+ return the number of bytes in a full chunk
151
+ useful for S3Connector where we need to preallocate filesystem buffers
152
+ in ramfs for zero-copy transfers
153
+ """
154
+ return self.local_cpu_backend.get_full_chunk_size_bytes()
155
+
156
+
157
+ class ConnectorAdapter(ABC):
158
+ """Base class for connector adapters."""
159
+
160
+ def __init__(self, schema: str = "") -> None:
161
+ self.schema = schema
162
+
163
+ def can_parse(self, url: str) -> bool:
164
+ return self.schema != "" and url.startswith(self.schema)
165
+
166
+ @abstractmethod
167
+ def create_connector(self, context: ConnectorContext) -> RemoteConnector:
168
+ """
169
+ Create a connector using the given context.
170
+ """
171
+ pass
172
+
173
+
174
+ class DynamicConnectorAdapter(ConnectorAdapter):
175
+ """Adapter that wraps a RemoteConnector class loaded
176
+ dynamically from plugin config.
177
+
178
+ When ``class_name`` points to a ``RemoteConnector`` subclass
179
+ rather than a ``ConnectorAdapter``, this wrapper is used to
180
+ instantiate the connector with the proper context.
181
+ """
182
+
183
+ def __init__(
184
+ self,
185
+ plugin_name: str,
186
+ connector_class: type,
187
+ ) -> None:
188
+ schema = "plugin://%s" % extract_plugin_type(plugin_name)
189
+ super().__init__(schema)
190
+ self._plugin_name = plugin_name
191
+ self._connector_class = connector_class
192
+
193
+ def can_parse(self, url: str) -> bool:
194
+ if url.startswith(self.schema):
195
+ return True
196
+ if url.startswith("plugin://"):
197
+ pname = url[len("plugin://") :]
198
+ return extract_plugin_type(pname) == extract_plugin_type(self._plugin_name)
199
+ return False
200
+
201
+ def create_connector(self, context: ConnectorContext) -> RemoteConnector:
202
+ logger.info(
203
+ "Creating dynamic connector %s via %s",
204
+ self._plugin_name,
205
+ self._connector_class.__name__,
206
+ )
207
+ return self._connector_class(
208
+ loop=context.loop,
209
+ local_cpu_backend=context.local_cpu_backend,
210
+ config=context.config,
211
+ )
212
+
213
+
214
+ class ConnectorManager:
215
+ """
216
+ Manager for creating connectors based on URL.
217
+
218
+ This class maintains a registry of connector adapters and creates
219
+ the appropriate connector based on the URL.
220
+ """
221
+
222
+ def __init__(
223
+ self,
224
+ url: str,
225
+ loop: asyncio.AbstractEventLoop,
226
+ local_cpu_backend: Optional[LocalCPUBackend],
227
+ config: Optional[LMCacheEngineConfig] = None,
228
+ metadata: Optional[LMCacheMetadata] = None,
229
+ plugin_name: Optional[str] = None,
230
+ ) -> None:
231
+ logger.info("Initializing ConnectorManager")
232
+ self.context = ConnectorContext(
233
+ url=url,
234
+ loop=loop,
235
+ local_cpu_backend=local_cpu_backend,
236
+ config=config,
237
+ metadata=metadata,
238
+ plugin_name=plugin_name,
239
+ )
240
+ self.adapters: List[ConnectorAdapter] = []
241
+ self._remote_adapters_builtin_launcher()
242
+ self._remote_adapters_plugin_launcher(config)
243
+
244
+ def _remote_adapters_builtin_launcher(self) -> None:
245
+ """Automatically load all builtin remote connector adapters."""
246
+ # Import current package to ensure all modules are loaded
247
+ # First Party
248
+ import lmcache.v1.storage_backend.connector as connector_pkg
249
+
250
+ # Discover all modules in the connector package
251
+ for _, module_name, _ in pkgutil.iter_modules(connector_pkg.__path__):
252
+ # Skip private modules and non-adapter modules
253
+ if module_name.startswith("_") or not module_name.endswith("_adapter"):
254
+ continue
255
+
256
+ try:
257
+ module = importlib.import_module(
258
+ f"{connector_pkg.__name__}.{module_name}"
259
+ )
260
+
261
+ # Find all ConnectorAdapter subclasses in the module
262
+ for _, obj in inspect.getmembers(module):
263
+ if (
264
+ inspect.isclass(obj)
265
+ and issubclass(obj, ConnectorAdapter)
266
+ and obj != ConnectorAdapter
267
+ ):
268
+ try:
269
+ adapter_instance = obj()
270
+ self.adapters.append(adapter_instance)
271
+ logger.info(f"Discovered adapter: {obj.__name__}")
272
+ except Exception as e:
273
+ logger.error(
274
+ "Failed to instantiate adapter "
275
+ f"{obj.__name__}: {str(e)}"
276
+ )
277
+ except ImportError as e:
278
+ logger.warning(f"Failed to import module {module_name}: {e}")
279
+
280
+ def _remote_adapters_plugin_launcher(self, config: LMCacheEngineConfig) -> None:
281
+ """Automatically load all plug and play remote connector adapters."""
282
+
283
+ if config is None:
284
+ logger.warning(
285
+ "Configuration not available to parse remote connector adapters."
286
+ )
287
+ return
288
+
289
+ # Get the list of allowed remote connector adapters if configured
290
+ remote_storage_plugins = (
291
+ set(config.remote_storage_plugins)
292
+ if config.remote_storage_plugins
293
+ else set()
294
+ )
295
+
296
+ for remote_storage_plugin in remote_storage_plugins:
297
+ try:
298
+ extra_config = config.extra_config
299
+
300
+ module_path = (
301
+ extra_config.get(
302
+ "remote_storage_plugin.%s.module_path" % remote_storage_plugin
303
+ )
304
+ if extra_config
305
+ else None
306
+ )
307
+ class_name = (
308
+ extra_config.get(
309
+ "remote_storage_plugin.%s.class_name" % remote_storage_plugin
310
+ )
311
+ if extra_config
312
+ else None
313
+ )
314
+
315
+ if not module_path or not class_name:
316
+ # Skip silently when a builtin adapter
317
+ # already handles this plugin type.
318
+ plugin_url = "plugin://%s" % remote_storage_plugin
319
+ if any(a.can_parse(plugin_url) for a in self.adapters):
320
+ continue
321
+ logger.warning(
322
+ "Remote connector %s missing adapter module_path or class_name",
323
+ remote_storage_plugin,
324
+ )
325
+ continue
326
+
327
+ # Dynamically import the module
328
+ module = importlib.import_module(module_path)
329
+ # Get the class from the module
330
+ loaded_class = getattr(module, class_name)
331
+
332
+ if inspect.isclass(loaded_class) and issubclass(
333
+ loaded_class, ConnectorAdapter
334
+ ):
335
+ adapter_instance = loaded_class()
336
+ elif inspect.isclass(loaded_class) and issubclass(
337
+ loaded_class, RemoteConnector
338
+ ):
339
+ adapter_instance = DynamicConnectorAdapter(
340
+ plugin_name=remote_storage_plugin,
341
+ connector_class=loaded_class,
342
+ )
343
+ else:
344
+ logger.warning(
345
+ "Remote connector %s class %s is "
346
+ "neither a ConnectorAdapter nor a "
347
+ "RemoteConnector subclass",
348
+ remote_storage_plugin,
349
+ class_name,
350
+ )
351
+ continue
352
+ self.adapters.append(adapter_instance)
353
+ logger.info(
354
+ "Discovered adapter: %s",
355
+ loaded_class.__name__,
356
+ )
357
+ except (ImportError, AttributeError) as e:
358
+ logger.error(
359
+ f"Failed to load remote connector {remote_storage_plugin} due to "
360
+ f"import/attribute error: {e}"
361
+ )
362
+ except Exception as e:
363
+ logger.error(
364
+ f"Failed to create remote connector {remote_storage_plugin} "
365
+ f"adapter: {str(e)}"
366
+ )
367
+
368
+ def create_connector(self) -> RemoteConnector:
369
+ for adapter in self.adapters:
370
+ if adapter.can_parse(self.context.url):
371
+ logger.info(f"Creating connector for URL: {self.context.url}")
372
+ connector = adapter.create_connector(self.context)
373
+ return connector
374
+
375
+ raise ValueError(f"No adapter found for URL: {self.context.url}")
376
+
377
+
378
+ def CreateConnector(
379
+ url: str,
380
+ loop: asyncio.AbstractEventLoop,
381
+ local_cpu_backend: Optional[LocalCPUBackend],
382
+ config: Optional[LMCacheEngineConfig] = None,
383
+ metadata: Optional[LMCacheMetadata] = None,
384
+ plugin_name: Optional[str] = None,
385
+ ) -> InstrumentedRemoteConnector:
386
+ """
387
+ Create a remote connector from the given URL.
388
+
389
+ Supported URL formats:
390
+ - redis://[[username]:[password]@]host[:port][/database][?option=value]
391
+ - rediss://[[username]:[password]@]host[:port][/database][?option=value] (SSL)
392
+ - redis-sentinel://[[username]:[password]@]host1:port1[,host2:port2,...]/service_name
393
+ - lm://host:port
394
+ - infinistore://host:port[?device=device_name]
395
+ - mooncakestore://host:port[?device=device_name]
396
+ - blackhole://[any_text]
397
+ - audit://host:port[?verify=true|false]
398
+ - fs://[host:port]/path
399
+ - s3://[bucket].s3express-[az_id].[region].amazonaws.com"
400
+ - mock://[capacity]/?peeking_latency=[ms]&read_throughput=[GB/s]&write_throughput=[GB/s]
401
+ or
402
+ - s3://[bucket].s3.[region].amazonaws.com
403
+
404
+ Examples:
405
+ - redis://localhost:6379
406
+ - rediss://user:password@redis.example.com:6380/0
407
+ - redis-sentinel://user:password@sentinel1:26379,sentinel2:26379/mymaster
408
+ - lm://localhost:65432
409
+ - infinistore://127.0.0.1:12345?device=mlx5_0
410
+ - mooncakestore://127.0.0.1:50051
411
+ - blackhole://
412
+ - audit://localhost:8080?verify=true
413
+ - fs:///tmp/lmcache
414
+ - external://host:0/external_log_connector.lmc_external_log_connector/?connector_name=ExternalLogConnector
415
+ - s3://fakefile--use1-az4--x-s3.s3express-use1-az4.us-east-1.amazonaws.com
416
+ - mock://100/?peeking_latency=1&read_throughput=2&write_throughput=2
417
+ or
418
+ - s3://fakefile--use1-az4--x-s3.s3.us-east-1.amazonaws.com
419
+
420
+ Args:
421
+ url: The remote URL
422
+ loop: The asyncio event loop
423
+ local_cpu_backend: The local CPU backend (can be None for scheduler role)
424
+ config: Optional LMCache engine configuration
425
+ metadata: Optional LMCache engine metadata
426
+
427
+ Returns:
428
+ RemoteConnector: The created connector
429
+
430
+ Raises:
431
+ ValueError: If the connector cannot be created
432
+ """
433
+
434
+ # Basic URL validation - check for scheme
435
+ if "://" not in url:
436
+ raise ValueError(f"Invalid remote url {url}: missing scheme")
437
+
438
+ manager = ConnectorManager(
439
+ url, loop, local_cpu_backend, config, metadata, plugin_name
440
+ )
441
+ connector = manager.create_connector()
442
+
443
+ return InstrumentedRemoteConnector(connector)
@@ -0,0 +1,77 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # First Party
3
+ from lmcache.logging import init_logger
4
+ from lmcache.v1.storage_backend.connector import (
5
+ ConnectorAdapter,
6
+ ConnectorContext,
7
+ CreateConnector,
8
+ parse_remote_url,
9
+ )
10
+ from lmcache.v1.storage_backend.connector.base_connector import RemoteConnector
11
+
12
+ logger = init_logger(__name__)
13
+
14
+
15
+ class AuditConnectorAdapter(ConnectorAdapter):
16
+ """Adapter for Audit connectors (for debugging and verification)."""
17
+
18
+ def __init__(self) -> None:
19
+ super().__init__("audit://")
20
+
21
+ def create_connector(self, context: ConnectorContext) -> RemoteConnector:
22
+ # Local
23
+ from .audit_connector import AuditConnector
24
+
25
+ """
26
+ Create an Audit connector. This connector wraps another connector
27
+ and audits all operations.
28
+
29
+ extra_config:
30
+ - audit_actual_remote_url: The actual remote URL to connect to.
31
+ - audit_calc_checksum: Whether to calculate checksums.
32
+ - audit_verify_checksum: Whether to verify checksums.
33
+
34
+ URL format:
35
+ - audit://host:port[?verify=true|false]
36
+
37
+ Examples:
38
+ - audit://localhost:8080
39
+ - audit://audit-server.example.com:8080?verify=true
40
+ - audit://127.0.0.1:8080?verify=false
41
+ """
42
+ logger.info(f"Creating Audit connector for URL: {context.url}")
43
+ hosts = context.url.split(",")
44
+ if len(hosts) > 1:
45
+ raise ValueError(
46
+ f"Only one host is supported for audit connector, but got {hosts}"
47
+ )
48
+ if not context.config:
49
+ raise ValueError("Config is not set")
50
+
51
+ parse_url = parse_remote_url(context.url)
52
+ # (Deprecated) verify URL parameter will be removed in future versions
53
+ # Use the extra config instead
54
+ verify_param = parse_url.query_params.get("verify", ["false"])[0]
55
+ verify_checksum = verify_param.lower() in ("true", "1", "yes")
56
+ # Get the actual remote URL from the extra config first to keep consistency
57
+ real_url = context.config.extra_config.get(
58
+ "audit_actual_remote_url", context.config.audit_actual_remote_url
59
+ )
60
+ if not real_url:
61
+ raise ValueError(
62
+ "audit_actual_remote_url is not set in the config or extra_config"
63
+ )
64
+ # Store verify_checksum in extra_config if not already set
65
+ if context.config.extra_config is None:
66
+ context.config.extra_config = {}
67
+ if "audit_verify_checksum" not in context.config.extra_config:
68
+ context.config.extra_config["audit_verify_checksum"] = verify_checksum
69
+ connector = CreateConnector(
70
+ real_url,
71
+ context.loop,
72
+ context.local_cpu_backend,
73
+ context.config,
74
+ context.metadata,
75
+ )
76
+ # Metaclass dynamically implements all abstract methods at runtime
77
+ return AuditConnector(connector.getWrappedConnector(), context.config) # type: ignore[abstract]