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.
- lmcache/__init__.py +84 -0
- lmcache/_version.py +24 -0
- lmcache/cli/__init__.py +1 -0
- lmcache/cli/commands/__init__.py +34 -0
- lmcache/cli/commands/base.py +157 -0
- lmcache/cli/commands/bench/__init__.py +557 -0
- lmcache/cli/commands/bench/engine_bench/__init__.py +1 -0
- lmcache/cli/commands/bench/engine_bench/config.py +245 -0
- lmcache/cli/commands/bench/engine_bench/interactive/__init__.py +274 -0
- lmcache/cli/commands/bench/engine_bench/interactive/config.json +10 -0
- lmcache/cli/commands/bench/engine_bench/interactive/schema.py +352 -0
- lmcache/cli/commands/bench/engine_bench/interactive/state.py +327 -0
- lmcache/cli/commands/bench/engine_bench/interactive/terminal.py +291 -0
- lmcache/cli/commands/bench/engine_bench/progress.py +145 -0
- lmcache/cli/commands/bench/engine_bench/request_sender.py +232 -0
- lmcache/cli/commands/bench/engine_bench/stats.py +275 -0
- lmcache/cli/commands/bench/engine_bench/workloads/__init__.py +153 -0
- lmcache/cli/commands/bench/engine_bench/workloads/base.py +122 -0
- lmcache/cli/commands/bench/engine_bench/workloads/long_doc_permutator.py +435 -0
- lmcache/cli/commands/bench/engine_bench/workloads/long_doc_qa.py +281 -0
- lmcache/cli/commands/bench/engine_bench/workloads/multi_round_chat.py +337 -0
- lmcache/cli/commands/bench/engine_bench/workloads/random_prefill.py +178 -0
- lmcache/cli/commands/describe.py +310 -0
- lmcache/cli/commands/kvcache.py +133 -0
- lmcache/cli/commands/mock.py +75 -0
- lmcache/cli/commands/ping.py +113 -0
- lmcache/cli/commands/query/__init__.py +155 -0
- lmcache/cli/commands/query/prompt.py +134 -0
- lmcache/cli/commands/query/request.py +357 -0
- lmcache/cli/commands/server.py +99 -0
- lmcache/cli/commands/tool/__init__.py +63 -0
- lmcache/cli/commands/tool/cache_simulator.py +113 -0
- lmcache/cli/commands/trace/__init__.py +505 -0
- lmcache/cli/commands/trace/dispatch.py +249 -0
- lmcache/cli/commands/trace/driver.py +372 -0
- lmcache/cli/commands/trace/stats.py +289 -0
- lmcache/cli/documents/lmcache.txt +11 -0
- lmcache/cli/main.py +42 -0
- lmcache/cli/metrics/__init__.py +29 -0
- lmcache/cli/metrics/formatter.py +171 -0
- lmcache/cli/metrics/handler.py +94 -0
- lmcache/cli/metrics/metrics.py +161 -0
- lmcache/cli/metrics/section.py +77 -0
- lmcache/connections.py +173 -0
- lmcache/integration/__init__.py +2 -0
- lmcache/integration/base_service_factory.py +165 -0
- lmcache/integration/request_telemetry/__init__.py +1 -0
- lmcache/integration/request_telemetry/base.py +51 -0
- lmcache/integration/request_telemetry/factory.py +113 -0
- lmcache/integration/request_telemetry/fastapi.py +109 -0
- lmcache/integration/request_telemetry/noop.py +35 -0
- lmcache/integration/sglang/__init__.py +2 -0
- lmcache/integration/sglang/sglang_adapter.py +326 -0
- lmcache/integration/sglang/utils.py +39 -0
- lmcache/integration/vllm/__init__.py +1 -0
- lmcache/integration/vllm/lmcache_connector_v1.py +213 -0
- lmcache/integration/vllm/lmcache_connector_v1_085.py +150 -0
- lmcache/integration/vllm/lmcache_mp_connector_0180.py +1072 -0
- lmcache/integration/vllm/tests/test_mm_hash_utils.py +112 -0
- lmcache/integration/vllm/utils.py +433 -0
- lmcache/integration/vllm/vllm_multi_process_adapter.py +1090 -0
- lmcache/integration/vllm/vllm_service_factory.py +339 -0
- lmcache/integration/vllm/vllm_v1_adapter.py +1713 -0
- lmcache/logging.py +107 -0
- lmcache/native_storage_ops.pyi +230 -0
- lmcache/non_cuda_equivalents.py +1424 -0
- lmcache/observability.py +1958 -0
- lmcache/storage_backend/serde/__init__.py +1 -0
- lmcache/storage_backend/serde/cachegen_basics.py +210 -0
- lmcache/storage_backend/serde/cachegen_decoder.py +207 -0
- lmcache/storage_backend/serde/cachegen_encoder.py +394 -0
- lmcache/storage_backend/serde/serde.py +75 -0
- lmcache/tools/__init__.py +1 -0
- lmcache/tools/cache_simulator/README.md +392 -0
- lmcache/tools/cache_simulator/__init__.py +1 -0
- lmcache/tools/cache_simulator/docs/simulate_example.png +0 -0
- lmcache/tools/cache_simulator/docs/sweep_example.png +0 -0
- lmcache/tools/cache_simulator/gen_bench_dataset.py +360 -0
- lmcache/tools/cache_simulator/lru_cache.py +124 -0
- lmcache/tools/cache_simulator/plot_hit_rate.py +231 -0
- lmcache/tools/cache_simulator/simulator.py +795 -0
- lmcache/tools/controller_benchmark/README.md +161 -0
- lmcache/tools/controller_benchmark/__init__.py +1 -0
- lmcache/tools/controller_benchmark/__main__.py +331 -0
- lmcache/tools/controller_benchmark/benchmark.py +660 -0
- lmcache/tools/controller_benchmark/config.py +44 -0
- lmcache/tools/controller_benchmark/constants.py +10 -0
- lmcache/tools/controller_benchmark/handlers/__init__.py +46 -0
- lmcache/tools/controller_benchmark/handlers/admit.py +52 -0
- lmcache/tools/controller_benchmark/handlers/base.py +47 -0
- lmcache/tools/controller_benchmark/handlers/deregister.py +49 -0
- lmcache/tools/controller_benchmark/handlers/evict.py +52 -0
- lmcache/tools/controller_benchmark/handlers/heartbeat.py +56 -0
- lmcache/tools/controller_benchmark/handlers/p2p_lookup.py +47 -0
- lmcache/tools/controller_benchmark/handlers/register.py +56 -0
- lmcache/tools/mp_status_viewer/__init__.py +1 -0
- lmcache/tools/mp_status_viewer/__main__.py +95 -0
- lmcache/usage_context.py +417 -0
- lmcache/utils.py +665 -0
- lmcache/v1/__init__.py +2 -0
- lmcache/v1/api_server/__init__.py +2 -0
- lmcache/v1/api_server/__main__.py +537 -0
- lmcache/v1/basic_check.py +112 -0
- lmcache/v1/cache_controller/__init__.py +9 -0
- lmcache/v1/cache_controller/commands/__init__.py +15 -0
- lmcache/v1/cache_controller/commands/base.py +35 -0
- lmcache/v1/cache_controller/commands/full_sync.py +49 -0
- lmcache/v1/cache_controller/config.py +176 -0
- lmcache/v1/cache_controller/controller_manager.py +535 -0
- lmcache/v1/cache_controller/controllers/__init__.py +11 -0
- lmcache/v1/cache_controller/controllers/full_sync_tracker.py +473 -0
- lmcache/v1/cache_controller/controllers/kv_controller.py +439 -0
- lmcache/v1/cache_controller/controllers/registration_controller.py +282 -0
- lmcache/v1/cache_controller/executor.py +463 -0
- lmcache/v1/cache_controller/frontend/static/css/style.css +201 -0
- lmcache/v1/cache_controller/frontend/static/img/logo.png +0 -0
- lmcache/v1/cache_controller/frontend/static/index.html +234 -0
- lmcache/v1/cache_controller/frontend/static/js/controller_app.js +660 -0
- lmcache/v1/cache_controller/full_sync_sender.py +475 -0
- lmcache/v1/cache_controller/locks.py +149 -0
- lmcache/v1/cache_controller/message.py +828 -0
- lmcache/v1/cache_controller/observability.py +208 -0
- lmcache/v1/cache_controller/utils.py +679 -0
- lmcache/v1/cache_controller/worker.py +665 -0
- lmcache/v1/cache_engine.py +2058 -0
- lmcache/v1/cache_interface.py +19 -0
- lmcache/v1/check/__init__.py +74 -0
- lmcache/v1/check/check_mode_gen.py +86 -0
- lmcache/v1/check/check_mode_test_l2_adapter.py +284 -0
- lmcache/v1/check/check_mode_test_remote.py +155 -0
- lmcache/v1/check/check_mode_test_storage_manager.py +142 -0
- lmcache/v1/check/utils.py +571 -0
- lmcache/v1/compute/__init__.py +2 -0
- lmcache/v1/compute/attention/__init__.py +0 -0
- lmcache/v1/compute/attention/abstract.py +39 -0
- lmcache/v1/compute/attention/flash_attn.py +129 -0
- lmcache/v1/compute/attention/flash_infer_sparse.py +284 -0
- lmcache/v1/compute/attention/metadata.py +85 -0
- lmcache/v1/compute/attention/utils.py +14 -0
- lmcache/v1/compute/blend/__init__.py +7 -0
- lmcache/v1/compute/blend/blender.py +168 -0
- lmcache/v1/compute/blend/metadata.py +34 -0
- lmcache/v1/compute/blend/utils.py +63 -0
- lmcache/v1/compute/models/__init__.py +0 -0
- lmcache/v1/compute/models/base.py +141 -0
- lmcache/v1/compute/models/llama.py +9 -0
- lmcache/v1/compute/models/qwen3.py +24 -0
- lmcache/v1/compute/models/utils.py +68 -0
- lmcache/v1/compute/positional_encoding.py +199 -0
- lmcache/v1/config.py +848 -0
- lmcache/v1/config_base.py +848 -0
- lmcache/v1/distributed/api.py +248 -0
- lmcache/v1/distributed/config.py +321 -0
- lmcache/v1/distributed/error.py +64 -0
- lmcache/v1/distributed/eviction.py +192 -0
- lmcache/v1/distributed/eviction_policy/__init__.py +21 -0
- lmcache/v1/distributed/eviction_policy/factory.py +27 -0
- lmcache/v1/distributed/eviction_policy/lru.py +244 -0
- lmcache/v1/distributed/eviction_policy/noop.py +50 -0
- lmcache/v1/distributed/internal_api.py +170 -0
- lmcache/v1/distributed/l1_manager.py +835 -0
- lmcache/v1/distributed/l2_adapters/__init__.py +67 -0
- lmcache/v1/distributed/l2_adapters/base.py +360 -0
- lmcache/v1/distributed/l2_adapters/config.py +385 -0
- lmcache/v1/distributed/l2_adapters/factory.py +205 -0
- lmcache/v1/distributed/l2_adapters/fs_l2_adapter.py +747 -0
- lmcache/v1/distributed/l2_adapters/fs_native_l2_adapter.py +167 -0
- lmcache/v1/distributed/l2_adapters/mock_l2_adapter.py +516 -0
- lmcache/v1/distributed/l2_adapters/mooncake_store_l2_adapter.py +135 -0
- lmcache/v1/distributed/l2_adapters/native_connector_l2_adapter.py +468 -0
- lmcache/v1/distributed/l2_adapters/native_plugin_l2_adapter.py +199 -0
- lmcache/v1/distributed/l2_adapters/nixl_store_dynamic_l2_adapter.py +831 -0
- lmcache/v1/distributed/l2_adapters/nixl_store_l2_adapter.py +983 -0
- lmcache/v1/distributed/l2_adapters/plugin_l2_adapter.py +210 -0
- lmcache/v1/distributed/l2_adapters/resp_l2_adapter.py +176 -0
- lmcache/v1/distributed/memory_manager.py +179 -0
- lmcache/v1/distributed/storage_controller.py +39 -0
- lmcache/v1/distributed/storage_controllers/__init__.py +43 -0
- lmcache/v1/distributed/storage_controllers/eviction_controller.py +242 -0
- lmcache/v1/distributed/storage_controllers/prefetch_controller.py +830 -0
- lmcache/v1/distributed/storage_controllers/prefetch_policy.py +193 -0
- lmcache/v1/distributed/storage_controllers/store_controller.py +452 -0
- lmcache/v1/distributed/storage_controllers/store_policy.py +213 -0
- lmcache/v1/distributed/storage_manager.py +532 -0
- lmcache/v1/event_manager.py +145 -0
- lmcache/v1/exceptions/__init__.py +16 -0
- lmcache/v1/gpu_connector/__init__.py +126 -0
- lmcache/v1/gpu_connector/gpu_connectors.py +1906 -0
- lmcache/v1/gpu_connector/gpu_ops.py +85 -0
- lmcache/v1/gpu_connector/hpu_connector.py +326 -0
- lmcache/v1/gpu_connector/mock_gpu_connector.py +67 -0
- lmcache/v1/gpu_connector/utils.py +890 -0
- lmcache/v1/gpu_connector/xpu_connectors.py +916 -0
- lmcache/v1/health_monitor/__init__.py +1 -0
- lmcache/v1/health_monitor/base.py +587 -0
- lmcache/v1/health_monitor/checks/__init__.py +1 -0
- lmcache/v1/health_monitor/checks/remote_backend_check.py +304 -0
- lmcache/v1/health_monitor/constants.py +36 -0
- lmcache/v1/internal_api_server/__init__.py +0 -0
- lmcache/v1/internal_api_server/api_registry.py +59 -0
- lmcache/v1/internal_api_server/api_server.py +120 -0
- lmcache/v1/internal_api_server/common/__init__.py +1 -0
- lmcache/v1/internal_api_server/common/env_api.py +22 -0
- lmcache/v1/internal_api_server/common/loglevel_api.py +57 -0
- lmcache/v1/internal_api_server/common/metrics_api.py +29 -0
- lmcache/v1/internal_api_server/common/periodic_thread_api.py +138 -0
- lmcache/v1/internal_api_server/common/run_script_api.py +73 -0
- lmcache/v1/internal_api_server/common/thread_api.py +63 -0
- lmcache/v1/internal_api_server/controller/__init__.py +1 -0
- lmcache/v1/internal_api_server/controller/key_stats_api.py +81 -0
- lmcache/v1/internal_api_server/controller/worker_info_api.py +136 -0
- lmcache/v1/internal_api_server/utils.py +43 -0
- lmcache/v1/internal_api_server/vllm/__init__.py +1 -0
- lmcache/v1/internal_api_server/vllm/backend_api.py +221 -0
- lmcache/v1/internal_api_server/vllm/bypass_api.py +204 -0
- lmcache/v1/internal_api_server/vllm/cache_api.py +895 -0
- lmcache/v1/internal_api_server/vllm/chunk_statistics_api.py +141 -0
- lmcache/v1/internal_api_server/vllm/conf_api.py +147 -0
- lmcache/v1/internal_api_server/vllm/freeze_api.py +172 -0
- lmcache/v1/internal_api_server/vllm/hot_cache_api.py +184 -0
- lmcache/v1/internal_api_server/vllm/inference_api.py +65 -0
- lmcache/v1/internal_api_server/vllm/load_fs_chunks_api.py +320 -0
- lmcache/v1/internal_api_server/vllm/lookup_api.py +145 -0
- lmcache/v1/internal_api_server/vllm/version_api.py +25 -0
- lmcache/v1/kv_layer_groups.py +267 -0
- lmcache/v1/lazy_memory_allocator.py +284 -0
- lmcache/v1/lookup_client/__init__.py +25 -0
- lmcache/v1/lookup_client/abstract_client.py +77 -0
- lmcache/v1/lookup_client/async_lookup_message.py +50 -0
- lmcache/v1/lookup_client/chunk_statistics_lookup_client.py +200 -0
- lmcache/v1/lookup_client/factory.py +251 -0
- lmcache/v1/lookup_client/hit_limit_lookup_client.py +86 -0
- lmcache/v1/lookup_client/lmcache_async_lookup_client.py +407 -0
- lmcache/v1/lookup_client/lmcache_lookup_client.py +285 -0
- lmcache/v1/lookup_client/lmcache_lookup_client_bypass.py +99 -0
- lmcache/v1/lookup_client/mooncake_lookup_client.py +87 -0
- lmcache/v1/lookup_client/record_strategies/__init__.py +77 -0
- lmcache/v1/lookup_client/record_strategies/base.py +327 -0
- lmcache/v1/lookup_client/record_strategies/file_hash.py +130 -0
- lmcache/v1/lookup_client/record_strategies/memory_bloom_filter.py +81 -0
- lmcache/v1/manager.py +539 -0
- lmcache/v1/memory_management.py +2619 -0
- lmcache/v1/metadata.py +114 -0
- lmcache/v1/mp_observability/AGENTS.override.md +21 -0
- lmcache/v1/mp_observability/README.md +204 -0
- lmcache/v1/mp_observability/config.py +340 -0
- lmcache/v1/mp_observability/event.py +100 -0
- lmcache/v1/mp_observability/event_bus.py +313 -0
- lmcache/v1/mp_observability/otel_init.py +145 -0
- lmcache/v1/mp_observability/subscribers/__init__.py +28 -0
- lmcache/v1/mp_observability/subscribers/logging/__init__.py +19 -0
- lmcache/v1/mp_observability/subscribers/logging/l1.py +56 -0
- lmcache/v1/mp_observability/subscribers/logging/l2.py +73 -0
- lmcache/v1/mp_observability/subscribers/logging/lookup_hash.py +209 -0
- lmcache/v1/mp_observability/subscribers/logging/mp_server.py +90 -0
- lmcache/v1/mp_observability/subscribers/logging/sm.py +59 -0
- lmcache/v1/mp_observability/subscribers/metrics/__init__.py +20 -0
- lmcache/v1/mp_observability/subscribers/metrics/l0_lifecycle.py +290 -0
- lmcache/v1/mp_observability/subscribers/metrics/l1.py +55 -0
- lmcache/v1/mp_observability/subscribers/metrics/l1_lifecycle.py +166 -0
- lmcache/v1/mp_observability/subscribers/metrics/l2.py +121 -0
- lmcache/v1/mp_observability/subscribers/metrics/sm.py +69 -0
- lmcache/v1/mp_observability/subscribers/tracing/__init__.py +12 -0
- lmcache/v1/mp_observability/subscribers/tracing/mp_server.py +333 -0
- lmcache/v1/mp_observability/subscribers/tracing/span_registry.py +148 -0
- lmcache/v1/mp_observability/trace/__init__.py +50 -0
- lmcache/v1/mp_observability/trace/codecs.py +255 -0
- lmcache/v1/mp_observability/trace/decorator.py +147 -0
- lmcache/v1/mp_observability/trace/format.py +132 -0
- lmcache/v1/mp_observability/trace/lifecycle.py +83 -0
- lmcache/v1/mp_observability/trace/reader.py +167 -0
- lmcache/v1/mp_observability/trace/recorder.py +300 -0
- lmcache/v1/multiprocess/__init__.py +0 -0
- lmcache/v1/multiprocess/affinity_pool.py +102 -0
- lmcache/v1/multiprocess/blend_server_v2.py +891 -0
- lmcache/v1/multiprocess/config.py +253 -0
- lmcache/v1/multiprocess/custom_types.py +281 -0
- lmcache/v1/multiprocess/futures.py +194 -0
- lmcache/v1/multiprocess/gpu_context.py +511 -0
- lmcache/v1/multiprocess/http_server.py +235 -0
- lmcache/v1/multiprocess/mp_runtime_plugin_launcher.py +130 -0
- lmcache/v1/multiprocess/mq.py +732 -0
- lmcache/v1/multiprocess/protocol.py +86 -0
- lmcache/v1/multiprocess/protocols/README.md +213 -0
- lmcache/v1/multiprocess/protocols/__init__.py +127 -0
- lmcache/v1/multiprocess/protocols/base.py +89 -0
- lmcache/v1/multiprocess/protocols/blend.py +109 -0
- lmcache/v1/multiprocess/protocols/blend_v2.py +57 -0
- lmcache/v1/multiprocess/protocols/controller.py +53 -0
- lmcache/v1/multiprocess/protocols/debug.py +34 -0
- lmcache/v1/multiprocess/protocols/engine.py +146 -0
- lmcache/v1/multiprocess/protocols/observability.py +39 -0
- lmcache/v1/multiprocess/server.py +1134 -0
- lmcache/v1/multiprocess/session.py +190 -0
- lmcache/v1/multiprocess/token_hasher.py +441 -0
- lmcache/v1/offload_server/__init__.py +17 -0
- lmcache/v1/offload_server/abstract_server.py +37 -0
- lmcache/v1/offload_server/message.py +30 -0
- lmcache/v1/offload_server/zmq_server.py +122 -0
- lmcache/v1/periodic_thread.py +579 -0
- lmcache/v1/pin_monitor.py +246 -0
- lmcache/v1/plugin/__init__.py +0 -0
- lmcache/v1/plugin/runtime_plugin_launcher.py +211 -0
- lmcache/v1/protocol.py +317 -0
- lmcache/v1/rpc/__init__.py +17 -0
- lmcache/v1/rpc/transport.py +105 -0
- lmcache/v1/rpc/zmq_transport.py +213 -0
- lmcache/v1/rpc_utils.py +165 -0
- lmcache/v1/server/__init__.py +2 -0
- lmcache/v1/server/__main__.py +170 -0
- lmcache/v1/server/storage_backend/__init__.py +21 -0
- lmcache/v1/server/storage_backend/abstract_backend.py +80 -0
- lmcache/v1/server/storage_backend/local_backend.py +75 -0
- lmcache/v1/server/utils.py +21 -0
- lmcache/v1/standalone/__init__.py +1 -0
- lmcache/v1/standalone/__main__.py +583 -0
- lmcache/v1/standalone/manager.py +80 -0
- lmcache/v1/standalone/standalone_service_factory.py +86 -0
- lmcache/v1/storage_backend/__init__.py +313 -0
- lmcache/v1/storage_backend/abstract_backend.py +445 -0
- lmcache/v1/storage_backend/audit_backend.py +233 -0
- lmcache/v1/storage_backend/batched_message_sender.py +222 -0
- lmcache/v1/storage_backend/cache_policy/__init__.py +45 -0
- lmcache/v1/storage_backend/cache_policy/base_policy.py +87 -0
- lmcache/v1/storage_backend/cache_policy/fifo.py +58 -0
- lmcache/v1/storage_backend/cache_policy/lfu.py +105 -0
- lmcache/v1/storage_backend/cache_policy/lru.py +81 -0
- lmcache/v1/storage_backend/cache_policy/mru.py +61 -0
- lmcache/v1/storage_backend/connector/__init__.py +443 -0
- lmcache/v1/storage_backend/connector/audit_adapter.py +77 -0
- lmcache/v1/storage_backend/connector/audit_connector.py +320 -0
- lmcache/v1/storage_backend/connector/base_connector.py +379 -0
- lmcache/v1/storage_backend/connector/blackhole_adapter.py +21 -0
- lmcache/v1/storage_backend/connector/blackhole_connector.py +37 -0
- lmcache/v1/storage_backend/connector/eic_adapter.py +31 -0
- lmcache/v1/storage_backend/connector/eic_connector.py +757 -0
- lmcache/v1/storage_backend/connector/external_adapter.py +79 -0
- lmcache/v1/storage_backend/connector/fs_adapter.py +51 -0
- lmcache/v1/storage_backend/connector/fs_connector.py +403 -0
- lmcache/v1/storage_backend/connector/infinistore_adapter.py +56 -0
- lmcache/v1/storage_backend/connector/infinistore_connector.py +177 -0
- lmcache/v1/storage_backend/connector/instrumented_connector.py +219 -0
- lmcache/v1/storage_backend/connector/lm_adapter.py +31 -0
- lmcache/v1/storage_backend/connector/lm_connector.py +176 -0
- lmcache/v1/storage_backend/connector/mock_adapter.py +57 -0
- lmcache/v1/storage_backend/connector/mock_connector.py +349 -0
- lmcache/v1/storage_backend/connector/mooncakestore_adapter.py +43 -0
- lmcache/v1/storage_backend/connector/mooncakestore_connector.py +614 -0
- lmcache/v1/storage_backend/connector/redis_adapter.py +181 -0
- lmcache/v1/storage_backend/connector/redis_connector.py +828 -0
- lmcache/v1/storage_backend/connector/s3_adapter.py +59 -0
- lmcache/v1/storage_backend/connector/s3_connector.py +699 -0
- lmcache/v1/storage_backend/connector/sagemaker_hyperpod_adapter.py +233 -0
- lmcache/v1/storage_backend/connector/sagemaker_hyperpod_connector.py +987 -0
- lmcache/v1/storage_backend/connector/valkey_adapter.py +114 -0
- lmcache/v1/storage_backend/connector/valkey_connector.py +627 -0
- lmcache/v1/storage_backend/gds_backend.py +1199 -0
- lmcache/v1/storage_backend/job_executor/__init__.py +0 -0
- lmcache/v1/storage_backend/job_executor/base_executor.py +34 -0
- lmcache/v1/storage_backend/job_executor/pq_executor.py +235 -0
- lmcache/v1/storage_backend/local_cpu_backend.py +810 -0
- lmcache/v1/storage_backend/local_disk_backend.py +656 -0
- lmcache/v1/storage_backend/maru_backend.py +734 -0
- lmcache/v1/storage_backend/naive_serde/__init__.py +50 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_basics.py +133 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_decoder.py +135 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_encoder.py +83 -0
- lmcache/v1/storage_backend/naive_serde/kivi_serde.py +22 -0
- lmcache/v1/storage_backend/naive_serde/naive_serde.py +18 -0
- lmcache/v1/storage_backend/naive_serde/serde.py +37 -0
- lmcache/v1/storage_backend/native_clients/connector_client_base.py +165 -0
- lmcache/v1/storage_backend/native_clients/resp_client.py +35 -0
- lmcache/v1/storage_backend/nixl_storage_backend.py +1400 -0
- lmcache/v1/storage_backend/p2p_backend.py +788 -0
- lmcache/v1/storage_backend/path_sharder.py +117 -0
- lmcache/v1/storage_backend/pd_backend.py +646 -0
- lmcache/v1/storage_backend/plugins/dax_backend.py +1443 -0
- lmcache/v1/storage_backend/plugins/rust_raw_block_backend.py +1361 -0
- lmcache/v1/storage_backend/remote_backend.py +624 -0
- lmcache/v1/storage_backend/resp_client.py +227 -0
- lmcache/v1/storage_backend/storage_backend_listener.py +19 -0
- lmcache/v1/storage_backend/storage_manager.py +1352 -0
- lmcache/v1/system_detection.py +110 -0
- lmcache/v1/token_database.py +551 -0
- lmcache/v1/transfer_channel/__init__.py +83 -0
- lmcache/v1/transfer_channel/abstract.py +285 -0
- lmcache/v1/transfer_channel/mock_memory_channel.py +156 -0
- lmcache/v1/transfer_channel/nixl_channel.py +639 -0
- lmcache/v1/transfer_channel/py_socket_channel.py +260 -0
- lmcache/v1/transfer_channel/transfer_utils.py +63 -0
- lmcache/v1/utils/__init__.py +1 -0
- lmcache/v1/utils/bloom_filter.py +109 -0
- lmcache/v1/utils/cache_utils.py +125 -0
- lmcache_cli-0.4.5.dev0.dist-info/METADATA +185 -0
- lmcache_cli-0.4.5.dev0.dist-info/RECORD +399 -0
- lmcache_cli-0.4.5.dev0.dist-info/WHEEL +5 -0
- lmcache_cli-0.4.5.dev0.dist-info/entry_points.txt +2 -0
- lmcache_cli-0.4.5.dev0.dist-info/licenses/LICENSE +201 -0
- lmcache_cli-0.4.5.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Standard
|
|
3
|
+
from typing import Union
|
|
4
|
+
import asyncio
|
|
5
|
+
import uuid
|
|
6
|
+
|
|
7
|
+
# Third Party
|
|
8
|
+
import msgspec
|
|
9
|
+
import zmq.asyncio
|
|
10
|
+
|
|
11
|
+
# First Party
|
|
12
|
+
from lmcache.logging import init_logger
|
|
13
|
+
from lmcache.v1.cache_controller.message import ( # noqa: E501
|
|
14
|
+
CheckFinishMsg,
|
|
15
|
+
CheckFinishRetMsg,
|
|
16
|
+
ClearMsg,
|
|
17
|
+
ClearRetMsg,
|
|
18
|
+
ClearWorkerMsg,
|
|
19
|
+
CompressMsg,
|
|
20
|
+
CompressRetMsg,
|
|
21
|
+
CompressWorkerMsg,
|
|
22
|
+
DecompressMsg,
|
|
23
|
+
DecompressRetMsg,
|
|
24
|
+
DecompressWorkerMsg,
|
|
25
|
+
ErrorMsg,
|
|
26
|
+
HealthMsg,
|
|
27
|
+
HealthRetMsg,
|
|
28
|
+
HealthWorkerMsg,
|
|
29
|
+
HealthWorkerRetMsg,
|
|
30
|
+
MoveMsg,
|
|
31
|
+
MoveRetMsg,
|
|
32
|
+
MoveWorkerMsg,
|
|
33
|
+
Msg,
|
|
34
|
+
MsgBase,
|
|
35
|
+
PinMsg,
|
|
36
|
+
PinRetMsg,
|
|
37
|
+
PinWorkerMsg,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
logger = init_logger(__name__)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# NOTE (Jiayi): `LMCacheClusterExecutor` might need to be in different processes
|
|
44
|
+
# in the future for the sake of performance.
|
|
45
|
+
# NOTE (Jiayi): Also, consider scaling up the number of cluster executors
|
|
46
|
+
# in the future.
|
|
47
|
+
# TODO (Jiayi): need better error handling
|
|
48
|
+
class LMCacheClusterExecutor:
|
|
49
|
+
"""
|
|
50
|
+
LMCache Cluster Executor class to handle the execution of cache operations.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__(self, reg_controller):
|
|
54
|
+
"""
|
|
55
|
+
Initialize the LMCache Executor with a cache instance.
|
|
56
|
+
|
|
57
|
+
:param lmcache_instance_id: lmcache_instance_id
|
|
58
|
+
"""
|
|
59
|
+
self.reg_controller = reg_controller
|
|
60
|
+
|
|
61
|
+
async def clear(self, msg: ClearMsg) -> Union[ClearRetMsg, ErrorMsg]:
|
|
62
|
+
"""
|
|
63
|
+
Execute a clear cache operation with error handling.
|
|
64
|
+
"""
|
|
65
|
+
instance_id = msg.instance_id
|
|
66
|
+
location = msg.location
|
|
67
|
+
|
|
68
|
+
worker_ids = self.reg_controller.get_workers(instance_id)
|
|
69
|
+
assert worker_ids is not None
|
|
70
|
+
sockets = []
|
|
71
|
+
serialized_msgs = []
|
|
72
|
+
for worker_id in worker_ids:
|
|
73
|
+
socket = self.reg_controller.get_socket(instance_id, worker_id)
|
|
74
|
+
if socket is None:
|
|
75
|
+
return ErrorMsg(
|
|
76
|
+
error=(
|
|
77
|
+
f"Worker {worker_id} not registered for instance {instance_id}"
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
sockets.append(socket)
|
|
81
|
+
|
|
82
|
+
# TODO(Jiayi): Need a way to trak event_id -> worker_event_id mapping
|
|
83
|
+
# Also, we need to track worker_event_id status
|
|
84
|
+
worker_event_id = f"Worker{worker_id}{msg.event_id}"
|
|
85
|
+
serialized_msg = msgspec.msgpack.encode(
|
|
86
|
+
ClearWorkerMsg(
|
|
87
|
+
worker_event_id=worker_event_id,
|
|
88
|
+
location=location,
|
|
89
|
+
)
|
|
90
|
+
)
|
|
91
|
+
serialized_msgs.append(serialized_msg)
|
|
92
|
+
serialized_results = await self.execute_workers(
|
|
93
|
+
sockets=sockets,
|
|
94
|
+
serialized_msgs=serialized_msgs,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
num_tokens_list = []
|
|
98
|
+
for i, serialized_result in enumerate(serialized_results):
|
|
99
|
+
result = msgspec.msgpack.decode(serialized_result, type=Msg)
|
|
100
|
+
num_tokens_list.append(result.num_tokens)
|
|
101
|
+
|
|
102
|
+
# TODO(Jiayi): Need to ensure cache consistency across workers.
|
|
103
|
+
assert len(set(num_tokens_list)) == 1, (
|
|
104
|
+
"The number of tokens cleared should be the same across all workers."
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
return ClearRetMsg(event_id=msg.event_id, num_tokens=num_tokens_list[0])
|
|
108
|
+
|
|
109
|
+
async def pin(self, msg: PinMsg) -> Union[PinRetMsg, ErrorMsg]:
|
|
110
|
+
"""
|
|
111
|
+
Execute a pin cache operation with error handling.
|
|
112
|
+
"""
|
|
113
|
+
instance_id = msg.instance_id
|
|
114
|
+
tokens = msg.tokens
|
|
115
|
+
location = msg.location
|
|
116
|
+
|
|
117
|
+
worker_ids = self.reg_controller.get_workers(instance_id)
|
|
118
|
+
assert worker_ids is not None
|
|
119
|
+
sockets = []
|
|
120
|
+
serialized_msgs = []
|
|
121
|
+
for worker_id in worker_ids:
|
|
122
|
+
socket = self.reg_controller.get_socket(instance_id, worker_id)
|
|
123
|
+
if socket is None:
|
|
124
|
+
return ErrorMsg(
|
|
125
|
+
error=(
|
|
126
|
+
f"Worker {worker_id} not registered for instance {instance_id}"
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
sockets.append(socket)
|
|
130
|
+
|
|
131
|
+
# TODO(Jiayi): Need a way to trak event_id -> worker_event_id mapping
|
|
132
|
+
# Also, we need to track worker_event_id status
|
|
133
|
+
worker_event_id = f"Worker{worker_id}{msg.event_id}"
|
|
134
|
+
serialized_msg = msgspec.msgpack.encode(
|
|
135
|
+
PinWorkerMsg(
|
|
136
|
+
worker_event_id=worker_event_id,
|
|
137
|
+
tokens=tokens,
|
|
138
|
+
location=location,
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
serialized_msgs.append(serialized_msg)
|
|
142
|
+
serialized_results = await self.execute_workers(
|
|
143
|
+
sockets=sockets,
|
|
144
|
+
serialized_msgs=serialized_msgs,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
num_tokens_list = []
|
|
148
|
+
for i, serialized_result in enumerate(serialized_results):
|
|
149
|
+
result = msgspec.msgpack.decode(serialized_result, type=Msg)
|
|
150
|
+
num_tokens_list.append(result.num_tokens)
|
|
151
|
+
|
|
152
|
+
# TODO(Jiayi): Need to ensure cache consistency across workers.
|
|
153
|
+
assert len(set(num_tokens_list)) == 1, (
|
|
154
|
+
"The number of tokens pinned should be the same across all workers."
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
return PinRetMsg(event_id=msg.event_id, num_tokens=num_tokens_list[0])
|
|
158
|
+
|
|
159
|
+
async def compress(self, msg: CompressMsg) -> Union[CompressRetMsg, ErrorMsg]:
|
|
160
|
+
"""
|
|
161
|
+
Execute a compress operation with error handling.
|
|
162
|
+
"""
|
|
163
|
+
event_id = msg.event_id
|
|
164
|
+
instance_id = msg.instance_id
|
|
165
|
+
method = msg.method
|
|
166
|
+
location = msg.location
|
|
167
|
+
tokens = msg.tokens
|
|
168
|
+
|
|
169
|
+
worker_ids = self.reg_controller.get_workers(instance_id)
|
|
170
|
+
assert worker_ids is not None
|
|
171
|
+
|
|
172
|
+
# TODO(Jiayi): Currently, we do not support PP or heterogeneous TP.
|
|
173
|
+
# NOTE(Jiayi): The TP ranks are already sorted in registration_controller.
|
|
174
|
+
|
|
175
|
+
sockets = []
|
|
176
|
+
serialized_msgs = []
|
|
177
|
+
for worker_id in worker_ids:
|
|
178
|
+
socket = self.reg_controller.get_socket(instance_id, worker_id)
|
|
179
|
+
|
|
180
|
+
if socket is None:
|
|
181
|
+
return ErrorMsg(
|
|
182
|
+
error=(
|
|
183
|
+
f"Worker {worker_id} not registered for "
|
|
184
|
+
f"instance {instance_id} or "
|
|
185
|
+
)
|
|
186
|
+
)
|
|
187
|
+
sockets.append(socket)
|
|
188
|
+
|
|
189
|
+
worker_event_id = f"CompressWorker{worker_id}{str(uuid.uuid4())}"
|
|
190
|
+
serialized_msg = msgspec.msgpack.encode(
|
|
191
|
+
CompressWorkerMsg(
|
|
192
|
+
worker_event_id=worker_event_id,
|
|
193
|
+
method=method,
|
|
194
|
+
location=location,
|
|
195
|
+
tokens=tokens,
|
|
196
|
+
)
|
|
197
|
+
)
|
|
198
|
+
serialized_msgs.append(serialized_msg)
|
|
199
|
+
logger.debug(
|
|
200
|
+
f"Sending compress operation to worker ({instance_id}, {worker_id})"
|
|
201
|
+
)
|
|
202
|
+
serialized_results = await self.execute_workers(
|
|
203
|
+
sockets=sockets,
|
|
204
|
+
serialized_msgs=serialized_msgs,
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
num_tokens_list = []
|
|
208
|
+
for serialized_result in serialized_results:
|
|
209
|
+
result = msgspec.msgpack.decode(serialized_result, type=Msg)
|
|
210
|
+
num_tokens_list.append(result.num_tokens)
|
|
211
|
+
|
|
212
|
+
# TODO(Jiayi): Need to ensure cache consistency across workers.
|
|
213
|
+
assert len(set(num_tokens_list)) == 1, (
|
|
214
|
+
"The number of tokens compressed should be the same across all workers."
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
return CompressRetMsg(
|
|
218
|
+
event_id=event_id,
|
|
219
|
+
num_tokens=num_tokens_list[0],
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
async def decompress(self, msg: DecompressMsg) -> Union[DecompressRetMsg, ErrorMsg]:
|
|
223
|
+
"""
|
|
224
|
+
Execute a decompress operation with error handling.
|
|
225
|
+
"""
|
|
226
|
+
event_id = msg.event_id
|
|
227
|
+
instance_id = msg.instance_id
|
|
228
|
+
method = msg.method
|
|
229
|
+
location = msg.location
|
|
230
|
+
tokens = msg.tokens
|
|
231
|
+
|
|
232
|
+
worker_ids = self.reg_controller.get_workers(instance_id)
|
|
233
|
+
assert worker_ids is not None
|
|
234
|
+
|
|
235
|
+
sockets = []
|
|
236
|
+
serialized_msgs = []
|
|
237
|
+
for worker_id in worker_ids:
|
|
238
|
+
socket = self.reg_controller.get_socket(instance_id, worker_id)
|
|
239
|
+
|
|
240
|
+
if socket is None:
|
|
241
|
+
return ErrorMsg(
|
|
242
|
+
error=(
|
|
243
|
+
f"Worker {worker_id} not registered for "
|
|
244
|
+
f"instance {instance_id} or "
|
|
245
|
+
)
|
|
246
|
+
)
|
|
247
|
+
sockets.append(socket)
|
|
248
|
+
|
|
249
|
+
worker_event_id = f"DecompressWorker{worker_id}{str(uuid.uuid4())}"
|
|
250
|
+
serialized_msg = msgspec.msgpack.encode(
|
|
251
|
+
DecompressWorkerMsg(
|
|
252
|
+
worker_event_id=worker_event_id,
|
|
253
|
+
method=method,
|
|
254
|
+
location=location,
|
|
255
|
+
tokens=tokens,
|
|
256
|
+
)
|
|
257
|
+
)
|
|
258
|
+
serialized_msgs.append(serialized_msg)
|
|
259
|
+
logger.debug(
|
|
260
|
+
f"Sending decompress operation to worker ({instance_id}, {worker_id})"
|
|
261
|
+
)
|
|
262
|
+
serialized_results = await self.execute_workers(
|
|
263
|
+
sockets=sockets,
|
|
264
|
+
serialized_msgs=serialized_msgs,
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
num_tokens_list = []
|
|
268
|
+
for serialized_result in serialized_results:
|
|
269
|
+
result = msgspec.msgpack.decode(serialized_result, type=Msg)
|
|
270
|
+
num_tokens_list.append(result.num_tokens)
|
|
271
|
+
|
|
272
|
+
assert len(set(num_tokens_list)) == 1, (
|
|
273
|
+
"The number of tokens decompressed should be the same across all workers."
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
return DecompressRetMsg(
|
|
277
|
+
event_id=event_id,
|
|
278
|
+
num_tokens=num_tokens_list[0],
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
async def move(self, msg: MoveMsg) -> Union[MoveRetMsg, ErrorMsg]:
|
|
282
|
+
"""
|
|
283
|
+
Execute a move cache operation with error handling.
|
|
284
|
+
"""
|
|
285
|
+
# NOTE(Jiayi): Currently we assume the transfer is push-based.
|
|
286
|
+
src_instance_id = msg.old_position[0]
|
|
287
|
+
dst_instance_id = msg.new_position[0]
|
|
288
|
+
|
|
289
|
+
src_worker_ids = self.reg_controller.get_workers(src_instance_id)
|
|
290
|
+
assert src_worker_ids is not None
|
|
291
|
+
dst_worker_ids = self.reg_controller.get_workers(dst_instance_id)
|
|
292
|
+
assert dst_worker_ids is not None
|
|
293
|
+
|
|
294
|
+
# TODO(Jiayi): Currently, we do not support PP or heterogeneous TP.
|
|
295
|
+
# NOTE(Jiayi): The TP ranks are already sorted in registration_controller.
|
|
296
|
+
|
|
297
|
+
sockets = []
|
|
298
|
+
serialized_msgs = []
|
|
299
|
+
for src_worker_id, dst_worker_id in zip(
|
|
300
|
+
src_worker_ids, dst_worker_ids, strict=False
|
|
301
|
+
):
|
|
302
|
+
socket = self.reg_controller.get_socket(src_instance_id, src_worker_id)
|
|
303
|
+
dst_url = self.reg_controller.get_peer_init_url(
|
|
304
|
+
dst_instance_id, dst_worker_id
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
if socket is None or dst_url is None:
|
|
308
|
+
return ErrorMsg(
|
|
309
|
+
error=(
|
|
310
|
+
f"Src worker {src_worker_id} not registered for "
|
|
311
|
+
f"instance {src_instance_id} or "
|
|
312
|
+
f"dst worker {dst_worker_id} not registered for "
|
|
313
|
+
f"instance {dst_instance_id} or P2P is not enabled."
|
|
314
|
+
)
|
|
315
|
+
)
|
|
316
|
+
sockets.append(socket)
|
|
317
|
+
|
|
318
|
+
worker_event_id = f"MoveWorker{src_worker_id}{str(uuid.uuid4())}"
|
|
319
|
+
serialized_msg = msgspec.msgpack.encode(
|
|
320
|
+
MoveWorkerMsg(
|
|
321
|
+
worker_event_id=worker_event_id,
|
|
322
|
+
old_position=msg.old_position[1],
|
|
323
|
+
new_position=(dst_url, msg.new_position[1]),
|
|
324
|
+
tokens=msg.tokens,
|
|
325
|
+
copy=msg.copy,
|
|
326
|
+
)
|
|
327
|
+
)
|
|
328
|
+
serialized_msgs.append(serialized_msg)
|
|
329
|
+
logger.debug(
|
|
330
|
+
f"Sending move operation to worker ({src_instance_id}, {src_worker_id})"
|
|
331
|
+
)
|
|
332
|
+
serialized_results = await self.execute_workers(
|
|
333
|
+
sockets=sockets,
|
|
334
|
+
serialized_msgs=serialized_msgs,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
num_tokens_list = []
|
|
338
|
+
for serialized_result in serialized_results:
|
|
339
|
+
result = msgspec.msgpack.decode(serialized_result, type=Msg)
|
|
340
|
+
num_tokens_list.append(result.num_tokens)
|
|
341
|
+
|
|
342
|
+
# TODO(Jiayi): Need to ensure cache consistency across workers.
|
|
343
|
+
assert len(set(num_tokens_list)) == 1, (
|
|
344
|
+
"The number of tokens moved should be the same across all workers."
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
return MoveRetMsg(
|
|
348
|
+
event_id=msg.event_id,
|
|
349
|
+
num_tokens=num_tokens_list[0],
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
async def health(self, msg: HealthMsg) -> Union[HealthRetMsg, ErrorMsg]:
|
|
353
|
+
"""
|
|
354
|
+
Execute a compress operation with error handling.
|
|
355
|
+
"""
|
|
356
|
+
instance_id = msg.instance_id
|
|
357
|
+
|
|
358
|
+
worker_ids = self.reg_controller.get_workers(instance_id)
|
|
359
|
+
if worker_ids is None:
|
|
360
|
+
return ErrorMsg(error=f"No workers found for instance {instance_id}")
|
|
361
|
+
|
|
362
|
+
# TODO(Jiayi): Currently, we do not support PP or heterogeneous TP.
|
|
363
|
+
# NOTE(Jiayi): The TP ranks are already sorted in registration_controller.
|
|
364
|
+
|
|
365
|
+
sockets = []
|
|
366
|
+
serialized_msgs = []
|
|
367
|
+
for worker_id in worker_ids:
|
|
368
|
+
socket = self.reg_controller.get_socket(instance_id, worker_id)
|
|
369
|
+
|
|
370
|
+
if socket is None:
|
|
371
|
+
return ErrorMsg(
|
|
372
|
+
error=(
|
|
373
|
+
f"Worker {worker_id} not registered for "
|
|
374
|
+
f"instance {instance_id} or socket not found"
|
|
375
|
+
)
|
|
376
|
+
)
|
|
377
|
+
sockets.append(socket)
|
|
378
|
+
|
|
379
|
+
worker_event_id = f"HealthWorker{worker_id}{str(uuid.uuid4())}"
|
|
380
|
+
serialized_msg = msgspec.msgpack.encode(
|
|
381
|
+
HealthWorkerMsg(
|
|
382
|
+
worker_event_id=worker_event_id,
|
|
383
|
+
)
|
|
384
|
+
)
|
|
385
|
+
serialized_msgs.append(serialized_msg)
|
|
386
|
+
logger.debug(
|
|
387
|
+
f"Sending health check operation to worker ({instance_id}, {worker_id})"
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
# Collect results from all workers
|
|
391
|
+
serialized_results = await self.execute_workers(
|
|
392
|
+
sockets=sockets,
|
|
393
|
+
serialized_msgs=serialized_msgs,
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
# Process results
|
|
397
|
+
error_codes = {}
|
|
398
|
+
for i, serialized_result in enumerate(serialized_results):
|
|
399
|
+
try:
|
|
400
|
+
result = msgspec.msgpack.decode(serialized_result, type=Msg)
|
|
401
|
+
if isinstance(result, HealthWorkerRetMsg):
|
|
402
|
+
error_codes[worker_ids[i]] = result.error_code
|
|
403
|
+
elif isinstance(result, ErrorMsg):
|
|
404
|
+
error_codes[worker_ids[i]] = -1001 # Worker returned error
|
|
405
|
+
else:
|
|
406
|
+
error_codes[worker_ids[i]] = -1002 # Unexpected response
|
|
407
|
+
except Exception as e:
|
|
408
|
+
logger.error(
|
|
409
|
+
f"Failed to parse health response from worker "
|
|
410
|
+
f"{worker_ids[i]}: {str(e)}"
|
|
411
|
+
)
|
|
412
|
+
error_codes[worker_ids[i]] = -1003 # Failed to parse response
|
|
413
|
+
|
|
414
|
+
return HealthRetMsg(
|
|
415
|
+
event_id=msg.event_id,
|
|
416
|
+
error_codes=error_codes,
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
async def check_finish(
|
|
420
|
+
self, msg: CheckFinishMsg
|
|
421
|
+
) -> Union[CheckFinishRetMsg, ErrorMsg]:
|
|
422
|
+
raise NotImplementedError
|
|
423
|
+
|
|
424
|
+
# TODO(Jiayi): need to make the types more specific
|
|
425
|
+
async def execute(self, operation: str, msg: MsgBase) -> MsgBase:
|
|
426
|
+
"""
|
|
427
|
+
Execute a cache operation with error handling.
|
|
428
|
+
|
|
429
|
+
:param operation: The operation to execute
|
|
430
|
+
(e.g., 'clear').
|
|
431
|
+
:param msg: The message containing the operation details.
|
|
432
|
+
:return: The result of the operation or an error message.
|
|
433
|
+
"""
|
|
434
|
+
try:
|
|
435
|
+
method = getattr(self, operation)
|
|
436
|
+
return await method(msg)
|
|
437
|
+
except AttributeError:
|
|
438
|
+
return ErrorMsg(error=f"Operation '{operation}' is not supported.")
|
|
439
|
+
except Exception as e:
|
|
440
|
+
return ErrorMsg(error=str(e))
|
|
441
|
+
|
|
442
|
+
async def execute_workers(
|
|
443
|
+
self,
|
|
444
|
+
sockets: list[zmq.asyncio.Socket],
|
|
445
|
+
serialized_msgs: list[bytes],
|
|
446
|
+
) -> list[bytes]:
|
|
447
|
+
"""
|
|
448
|
+
Execute a list of serialized messages on the given sockets.
|
|
449
|
+
:param sockets: The list of sockets to send the messages to.
|
|
450
|
+
:param serialized_msgs: The list of serialized messages to send.
|
|
451
|
+
:return: A list of serialized results received from the sockets.
|
|
452
|
+
"""
|
|
453
|
+
tasks = []
|
|
454
|
+
for socket, serialized_msg in zip(sockets, serialized_msgs, strict=False):
|
|
455
|
+
|
|
456
|
+
async def send_and_receive(s, msg):
|
|
457
|
+
await s.send(msg)
|
|
458
|
+
return await s.recv()
|
|
459
|
+
|
|
460
|
+
tasks.append(send_and_receive(socket, serialized_msg))
|
|
461
|
+
|
|
462
|
+
serialized_results = await asyncio.gather(*tasks)
|
|
463
|
+
return serialized_results
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/* Controller Dashboard Styles */
|
|
2
|
+
body {
|
|
3
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
4
|
+
background-color: #f8f9fa;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.container-fluid {
|
|
8
|
+
max-width: 1400px;
|
|
9
|
+
margin: 0 auto;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
header {
|
|
13
|
+
border-radius: 0.5rem;
|
|
14
|
+
margin-bottom: 1rem;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.nav-tabs {
|
|
18
|
+
border-bottom: 2px solid #dee2e6;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.nav-tabs .nav-link {
|
|
22
|
+
border: none;
|
|
23
|
+
color: #495057;
|
|
24
|
+
font-weight: 500;
|
|
25
|
+
padding: 0.75rem 1.5rem;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.nav-tabs .nav-link:hover {
|
|
29
|
+
border: none;
|
|
30
|
+
color: #0d6efd;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.nav-tabs .nav-link.active {
|
|
34
|
+
color: #0d6efd;
|
|
35
|
+
border-bottom: 3px solid #0d6efd;
|
|
36
|
+
background-color: transparent;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.tab-content {
|
|
40
|
+
background-color: white;
|
|
41
|
+
border-radius: 0 0 0.5rem 0.5rem;
|
|
42
|
+
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.card {
|
|
46
|
+
border: 1px solid rgba(0, 0, 0, 0.125);
|
|
47
|
+
border-radius: 0.5rem;
|
|
48
|
+
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.card-title {
|
|
52
|
+
color: #495057;
|
|
53
|
+
font-weight: 600;
|
|
54
|
+
margin-bottom: 1rem;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.table-responsive {
|
|
58
|
+
margin-top: 1rem;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.table {
|
|
62
|
+
margin-bottom: 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.table thead th {
|
|
66
|
+
background-color: #f8f9fa;
|
|
67
|
+
border-bottom: 2px solid #dee2e6;
|
|
68
|
+
font-weight: 600;
|
|
69
|
+
color: #495057;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.table tbody tr:hover {
|
|
73
|
+
background-color: #f8f9fa;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.btn {
|
|
77
|
+
border-radius: 0.375rem;
|
|
78
|
+
font-weight: 500;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.btn-primary {
|
|
82
|
+
background-color: #0d6efd;
|
|
83
|
+
border-color: #0d6efd;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.btn-primary:hover {
|
|
87
|
+
background-color: #0b5ed7;
|
|
88
|
+
border-color: #0a58ca;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.btn-outline-primary {
|
|
92
|
+
color: #0d6efd;
|
|
93
|
+
border-color: #0d6efd;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.btn-outline-primary:hover {
|
|
97
|
+
background-color: #0d6efd;
|
|
98
|
+
border-color: #0d6efd;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.form-control, .form-select {
|
|
102
|
+
border-radius: 0.375rem;
|
|
103
|
+
border: 1px solid #ced4da;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.form-control:focus, .form-select:focus {
|
|
107
|
+
border-color: #86b7fe;
|
|
108
|
+
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
pre {
|
|
112
|
+
background-color: #f8f9fa;
|
|
113
|
+
border: 1px solid #dee2e6;
|
|
114
|
+
border-radius: 0.375rem;
|
|
115
|
+
padding: 1rem;
|
|
116
|
+
white-space: pre-wrap;
|
|
117
|
+
word-wrap: break-word;
|
|
118
|
+
font-family: 'Courier New', Courier, monospace;
|
|
119
|
+
font-size: 0.875rem;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.badge {
|
|
123
|
+
font-weight: 500;
|
|
124
|
+
padding: 0.35em 0.65em;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.badge.bg-success {
|
|
128
|
+
background-color: #198754 !important;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.badge.bg-warning {
|
|
132
|
+
background-color: #ffc107 !important;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.badge.bg-danger {
|
|
136
|
+
background-color: #dc3545 !important;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.badge.bg-info {
|
|
140
|
+
background-color: #0dcaf0 !important;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.spinner-border {
|
|
144
|
+
margin: 1rem auto;
|
|
145
|
+
display: block;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.modal-content {
|
|
149
|
+
border-radius: 0.5rem;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.modal-header {
|
|
153
|
+
border-bottom: 1px solid #dee2e6;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.modal-footer {
|
|
157
|
+
border-top: 1px solid #dee2e6;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/* Status indicators */
|
|
161
|
+
.status-active {
|
|
162
|
+
color: #198754;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.status-inactive {
|
|
166
|
+
color: #6c757d;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.status-error {
|
|
170
|
+
color: #dc3545;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.status-warning {
|
|
174
|
+
color: #ffc107;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* Responsive adjustments */
|
|
178
|
+
@media (max-width: 768px) {
|
|
179
|
+
.container-fluid {
|
|
180
|
+
padding: 0.5rem;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.nav-tabs .nav-link {
|
|
184
|
+
padding: 0.5rem 0.75rem;
|
|
185
|
+
font-size: 0.875rem;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.tab-content {
|
|
189
|
+
padding: 1rem;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* Animation for refreshing */
|
|
194
|
+
@keyframes spin {
|
|
195
|
+
0% { transform: rotate(0deg); }
|
|
196
|
+
100% { transform: rotate(360deg); }
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.refreshing {
|
|
200
|
+
animation: spin 1s linear infinite;
|
|
201
|
+
}
|
|
Binary file
|