kubiya-control-plane-api 0.9.15__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.
- control_plane_api/LICENSE +676 -0
- control_plane_api/README.md +350 -0
- control_plane_api/__init__.py +4 -0
- control_plane_api/__version__.py +8 -0
- control_plane_api/alembic/README +1 -0
- control_plane_api/alembic/env.py +121 -0
- control_plane_api/alembic/script.py.mako +28 -0
- control_plane_api/alembic/versions/2613c65c3dbe_initial_database_setup.py +32 -0
- control_plane_api/alembic/versions/2df520d4927d_merge_heads.py +28 -0
- control_plane_api/alembic/versions/43abf98d6a01_add_paused_status_to_executions.py +73 -0
- control_plane_api/alembic/versions/6289854264cb_merge_multiple_heads.py +28 -0
- control_plane_api/alembic/versions/6a4d4dc3d8dc_generate_execution_transitions.py +50 -0
- control_plane_api/alembic/versions/87d11cf0a783_add_disconnected_status_to_worker_.py +44 -0
- control_plane_api/alembic/versions/add_ephemeral_queue_support.py +85 -0
- control_plane_api/alembic/versions/add_model_type_to_llm_models.py +31 -0
- control_plane_api/alembic/versions/add_plan_executions_table.py +114 -0
- control_plane_api/alembic/versions/add_trace_span_tables.py +154 -0
- control_plane_api/alembic/versions/add_user_info_to_traces.py +36 -0
- control_plane_api/alembic/versions/adjusting_foreign_keys.py +32 -0
- control_plane_api/alembic/versions/b4983d976db2_initial_tables.py +1128 -0
- control_plane_api/alembic/versions/d181a3b40e71_rename_custom_metadata_to_metadata_in_.py +50 -0
- control_plane_api/alembic/versions/df9117888e82_add_missing_columns.py +82 -0
- control_plane_api/alembic/versions/f25de6ad895a_missing_migrations.py +34 -0
- control_plane_api/alembic/versions/f71305fb69b9_fix_ephemeral_queue_deletion_foreign_key.py +54 -0
- control_plane_api/alembic/versions/mark_local_exec_queues_as_ephemeral.py +68 -0
- control_plane_api/alembic.ini +148 -0
- control_plane_api/api/index.py +12 -0
- control_plane_api/app/__init__.py +11 -0
- control_plane_api/app/activities/__init__.py +20 -0
- control_plane_api/app/activities/agent_activities.py +384 -0
- control_plane_api/app/activities/plan_generation_activities.py +499 -0
- control_plane_api/app/activities/team_activities.py +424 -0
- control_plane_api/app/activities/temporal_cloud_activities.py +588 -0
- control_plane_api/app/config/__init__.py +35 -0
- control_plane_api/app/config/api_config.py +469 -0
- control_plane_api/app/config/config_loader.py +224 -0
- control_plane_api/app/config/model_pricing.py +323 -0
- control_plane_api/app/config/storage_config.py +159 -0
- control_plane_api/app/config.py +115 -0
- control_plane_api/app/controllers/__init__.py +0 -0
- control_plane_api/app/controllers/execution_environment_controller.py +1315 -0
- control_plane_api/app/database.py +135 -0
- control_plane_api/app/exceptions.py +408 -0
- control_plane_api/app/lib/__init__.py +11 -0
- control_plane_api/app/lib/environment.py +65 -0
- control_plane_api/app/lib/event_bus/__init__.py +17 -0
- control_plane_api/app/lib/event_bus/base.py +136 -0
- control_plane_api/app/lib/event_bus/manager.py +335 -0
- control_plane_api/app/lib/event_bus/providers/__init__.py +6 -0
- control_plane_api/app/lib/event_bus/providers/http_provider.py +166 -0
- control_plane_api/app/lib/event_bus/providers/nats_provider.py +324 -0
- control_plane_api/app/lib/event_bus/providers/redis_provider.py +233 -0
- control_plane_api/app/lib/event_bus/providers/websocket_provider.py +497 -0
- control_plane_api/app/lib/job_executor.py +330 -0
- control_plane_api/app/lib/kubiya_client.py +293 -0
- control_plane_api/app/lib/litellm_pricing.py +166 -0
- control_plane_api/app/lib/mcp_validation.py +163 -0
- control_plane_api/app/lib/nats/__init__.py +13 -0
- control_plane_api/app/lib/nats/credentials_manager.py +288 -0
- control_plane_api/app/lib/nats/listener.py +374 -0
- control_plane_api/app/lib/planning_prompt_builder.py +153 -0
- control_plane_api/app/lib/planning_tools/__init__.py +41 -0
- control_plane_api/app/lib/planning_tools/agents.py +409 -0
- control_plane_api/app/lib/planning_tools/agno_toolkit.py +836 -0
- control_plane_api/app/lib/planning_tools/base.py +119 -0
- control_plane_api/app/lib/planning_tools/cognitive_memory_tools.py +403 -0
- control_plane_api/app/lib/planning_tools/context_graph_tools.py +545 -0
- control_plane_api/app/lib/planning_tools/environments.py +218 -0
- control_plane_api/app/lib/planning_tools/knowledge.py +204 -0
- control_plane_api/app/lib/planning_tools/models.py +93 -0
- control_plane_api/app/lib/planning_tools/planning_service.py +646 -0
- control_plane_api/app/lib/planning_tools/resources.py +242 -0
- control_plane_api/app/lib/planning_tools/teams.py +334 -0
- control_plane_api/app/lib/policy_enforcer_client.py +1016 -0
- control_plane_api/app/lib/redis_client.py +803 -0
- control_plane_api/app/lib/sqlalchemy_utils.py +486 -0
- control_plane_api/app/lib/state_transition_tools/__init__.py +7 -0
- control_plane_api/app/lib/state_transition_tools/execution_context.py +388 -0
- control_plane_api/app/lib/storage/__init__.py +20 -0
- control_plane_api/app/lib/storage/base_provider.py +274 -0
- control_plane_api/app/lib/storage/provider_factory.py +157 -0
- control_plane_api/app/lib/storage/vercel_blob_provider.py +468 -0
- control_plane_api/app/lib/supabase.py +71 -0
- control_plane_api/app/lib/supabase_utils.py +138 -0
- control_plane_api/app/lib/task_planning/__init__.py +138 -0
- control_plane_api/app/lib/task_planning/agent_factory.py +308 -0
- control_plane_api/app/lib/task_planning/agents.py +389 -0
- control_plane_api/app/lib/task_planning/cache.py +218 -0
- control_plane_api/app/lib/task_planning/entity_resolver.py +273 -0
- control_plane_api/app/lib/task_planning/helpers.py +293 -0
- control_plane_api/app/lib/task_planning/hooks.py +474 -0
- control_plane_api/app/lib/task_planning/models.py +503 -0
- control_plane_api/app/lib/task_planning/plan_validator.py +166 -0
- control_plane_api/app/lib/task_planning/planning_workflow.py +2911 -0
- control_plane_api/app/lib/task_planning/runner.py +656 -0
- control_plane_api/app/lib/task_planning/streaming_hook.py +213 -0
- control_plane_api/app/lib/task_planning/workflow.py +424 -0
- control_plane_api/app/lib/templating/__init__.py +88 -0
- control_plane_api/app/lib/templating/compiler.py +278 -0
- control_plane_api/app/lib/templating/engine.py +178 -0
- control_plane_api/app/lib/templating/parsers/__init__.py +29 -0
- control_plane_api/app/lib/templating/parsers/base.py +96 -0
- control_plane_api/app/lib/templating/parsers/env.py +85 -0
- control_plane_api/app/lib/templating/parsers/graph.py +112 -0
- control_plane_api/app/lib/templating/parsers/secret.py +87 -0
- control_plane_api/app/lib/templating/parsers/simple.py +81 -0
- control_plane_api/app/lib/templating/resolver.py +366 -0
- control_plane_api/app/lib/templating/types.py +214 -0
- control_plane_api/app/lib/templating/validator.py +201 -0
- control_plane_api/app/lib/temporal_client.py +232 -0
- control_plane_api/app/lib/temporal_credentials_cache.py +178 -0
- control_plane_api/app/lib/temporal_credentials_service.py +203 -0
- control_plane_api/app/lib/validation/__init__.py +24 -0
- control_plane_api/app/lib/validation/runtime_validation.py +388 -0
- control_plane_api/app/main.py +531 -0
- control_plane_api/app/middleware/__init__.py +10 -0
- control_plane_api/app/middleware/auth.py +645 -0
- control_plane_api/app/middleware/exception_handler.py +267 -0
- control_plane_api/app/middleware/prometheus_middleware.py +173 -0
- control_plane_api/app/middleware/rate_limiting.py +384 -0
- control_plane_api/app/middleware/request_id.py +202 -0
- control_plane_api/app/models/__init__.py +40 -0
- control_plane_api/app/models/agent.py +90 -0
- control_plane_api/app/models/analytics.py +206 -0
- control_plane_api/app/models/associations.py +107 -0
- control_plane_api/app/models/auth_user.py +73 -0
- control_plane_api/app/models/context.py +161 -0
- control_plane_api/app/models/custom_integration.py +99 -0
- control_plane_api/app/models/environment.py +64 -0
- control_plane_api/app/models/execution.py +125 -0
- control_plane_api/app/models/execution_transition.py +50 -0
- control_plane_api/app/models/job.py +159 -0
- control_plane_api/app/models/llm_model.py +78 -0
- control_plane_api/app/models/orchestration.py +66 -0
- control_plane_api/app/models/plan_execution.py +102 -0
- control_plane_api/app/models/presence.py +49 -0
- control_plane_api/app/models/project.py +61 -0
- control_plane_api/app/models/project_management.py +85 -0
- control_plane_api/app/models/session.py +29 -0
- control_plane_api/app/models/skill.py +155 -0
- control_plane_api/app/models/system_tables.py +43 -0
- control_plane_api/app/models/task_planning.py +372 -0
- control_plane_api/app/models/team.py +86 -0
- control_plane_api/app/models/trace.py +257 -0
- control_plane_api/app/models/user_profile.py +54 -0
- control_plane_api/app/models/worker.py +221 -0
- control_plane_api/app/models/workflow.py +161 -0
- control_plane_api/app/models/workspace.py +50 -0
- control_plane_api/app/observability/__init__.py +177 -0
- control_plane_api/app/observability/context_logging.py +475 -0
- control_plane_api/app/observability/decorators.py +337 -0
- control_plane_api/app/observability/local_span_processor.py +702 -0
- control_plane_api/app/observability/metrics.py +303 -0
- control_plane_api/app/observability/middleware.py +246 -0
- control_plane_api/app/observability/optional.py +115 -0
- control_plane_api/app/observability/tracing.py +382 -0
- control_plane_api/app/policies/README.md +149 -0
- control_plane_api/app/policies/approved_users.rego +62 -0
- control_plane_api/app/policies/business_hours.rego +51 -0
- control_plane_api/app/policies/rate_limiting.rego +100 -0
- control_plane_api/app/policies/tool_enforcement/README.md +336 -0
- control_plane_api/app/policies/tool_enforcement/bash_command_validation.rego +71 -0
- control_plane_api/app/policies/tool_enforcement/business_hours_enforcement.rego +82 -0
- control_plane_api/app/policies/tool_enforcement/mcp_tool_allowlist.rego +58 -0
- control_plane_api/app/policies/tool_enforcement/production_safeguards.rego +80 -0
- control_plane_api/app/policies/tool_enforcement/role_based_tool_access.rego +44 -0
- control_plane_api/app/policies/tool_restrictions.rego +86 -0
- control_plane_api/app/routers/__init__.py +4 -0
- control_plane_api/app/routers/agents.py +382 -0
- control_plane_api/app/routers/agents_v2.py +1598 -0
- control_plane_api/app/routers/analytics.py +1310 -0
- control_plane_api/app/routers/auth.py +59 -0
- control_plane_api/app/routers/client_config.py +57 -0
- control_plane_api/app/routers/context_graph.py +561 -0
- control_plane_api/app/routers/context_manager.py +577 -0
- control_plane_api/app/routers/custom_integrations.py +490 -0
- control_plane_api/app/routers/enforcer.py +132 -0
- control_plane_api/app/routers/environment_context.py +252 -0
- control_plane_api/app/routers/environments.py +761 -0
- control_plane_api/app/routers/execution_environment.py +847 -0
- control_plane_api/app/routers/executions/__init__.py +28 -0
- control_plane_api/app/routers/executions/router.py +286 -0
- control_plane_api/app/routers/executions/services/__init__.py +22 -0
- control_plane_api/app/routers/executions/services/demo_worker_health.py +156 -0
- control_plane_api/app/routers/executions/services/status_service.py +420 -0
- control_plane_api/app/routers/executions/services/test_worker_health.py +480 -0
- control_plane_api/app/routers/executions/services/worker_health.py +514 -0
- control_plane_api/app/routers/executions/streaming/__init__.py +22 -0
- control_plane_api/app/routers/executions/streaming/deduplication.py +352 -0
- control_plane_api/app/routers/executions/streaming/event_buffer.py +353 -0
- control_plane_api/app/routers/executions/streaming/event_formatter.py +964 -0
- control_plane_api/app/routers/executions/streaming/history_loader.py +588 -0
- control_plane_api/app/routers/executions/streaming/live_source.py +693 -0
- control_plane_api/app/routers/executions/streaming/streamer.py +849 -0
- control_plane_api/app/routers/executions.py +4888 -0
- control_plane_api/app/routers/health.py +165 -0
- control_plane_api/app/routers/health_v2.py +394 -0
- control_plane_api/app/routers/integration_templates.py +496 -0
- control_plane_api/app/routers/integrations.py +287 -0
- control_plane_api/app/routers/jobs.py +1809 -0
- control_plane_api/app/routers/metrics.py +517 -0
- control_plane_api/app/routers/models.py +82 -0
- control_plane_api/app/routers/models_v2.py +628 -0
- control_plane_api/app/routers/plan_executions.py +1481 -0
- control_plane_api/app/routers/plan_generation_async.py +304 -0
- control_plane_api/app/routers/policies.py +669 -0
- control_plane_api/app/routers/presence.py +234 -0
- control_plane_api/app/routers/projects.py +987 -0
- control_plane_api/app/routers/runners.py +379 -0
- control_plane_api/app/routers/runtimes.py +172 -0
- control_plane_api/app/routers/secrets.py +171 -0
- control_plane_api/app/routers/skills.py +1010 -0
- control_plane_api/app/routers/skills_definitions.py +140 -0
- control_plane_api/app/routers/storage.py +456 -0
- control_plane_api/app/routers/task_planning.py +611 -0
- control_plane_api/app/routers/task_queues.py +650 -0
- control_plane_api/app/routers/team_context.py +274 -0
- control_plane_api/app/routers/teams.py +1747 -0
- control_plane_api/app/routers/templates.py +248 -0
- control_plane_api/app/routers/traces.py +571 -0
- control_plane_api/app/routers/websocket_client.py +479 -0
- control_plane_api/app/routers/websocket_executions_status.py +437 -0
- control_plane_api/app/routers/websocket_gateway.py +323 -0
- control_plane_api/app/routers/websocket_traces.py +576 -0
- control_plane_api/app/routers/worker_queues.py +2555 -0
- control_plane_api/app/routers/worker_websocket.py +419 -0
- control_plane_api/app/routers/workers.py +1004 -0
- control_plane_api/app/routers/workflows.py +204 -0
- control_plane_api/app/runtimes/__init__.py +6 -0
- control_plane_api/app/runtimes/validation.py +344 -0
- control_plane_api/app/schemas/__init__.py +1 -0
- control_plane_api/app/schemas/job_schemas.py +302 -0
- control_plane_api/app/schemas/mcp_schemas.py +311 -0
- control_plane_api/app/schemas/template_schemas.py +133 -0
- control_plane_api/app/schemas/trace_schemas.py +168 -0
- control_plane_api/app/schemas/worker_queue_observability_schemas.py +165 -0
- control_plane_api/app/services/__init__.py +1 -0
- control_plane_api/app/services/agno_planning_strategy.py +233 -0
- control_plane_api/app/services/agno_service.py +838 -0
- control_plane_api/app/services/claude_code_planning_service.py +203 -0
- control_plane_api/app/services/context_graph_client.py +224 -0
- control_plane_api/app/services/custom_integration_service.py +415 -0
- control_plane_api/app/services/integration_resolution_service.py +345 -0
- control_plane_api/app/services/litellm_service.py +394 -0
- control_plane_api/app/services/plan_generator.py +79 -0
- control_plane_api/app/services/planning_strategy.py +66 -0
- control_plane_api/app/services/planning_strategy_factory.py +118 -0
- control_plane_api/app/services/policy_service.py +615 -0
- control_plane_api/app/services/state_transition_service.py +755 -0
- control_plane_api/app/services/storage_service.py +593 -0
- control_plane_api/app/services/temporal_cloud_provisioning.py +150 -0
- control_plane_api/app/services/toolsets/context_graph_skill.py +432 -0
- control_plane_api/app/services/trace_retention.py +354 -0
- control_plane_api/app/services/worker_queue_metrics_service.py +190 -0
- control_plane_api/app/services/workflow_cancellation_manager.py +135 -0
- control_plane_api/app/services/workflow_operations_service.py +611 -0
- control_plane_api/app/skills/__init__.py +100 -0
- control_plane_api/app/skills/base.py +239 -0
- control_plane_api/app/skills/builtin/__init__.py +37 -0
- control_plane_api/app/skills/builtin/agent_communication/__init__.py +8 -0
- control_plane_api/app/skills/builtin/agent_communication/skill.py +246 -0
- control_plane_api/app/skills/builtin/code_ingestion/__init__.py +4 -0
- control_plane_api/app/skills/builtin/code_ingestion/skill.py +267 -0
- control_plane_api/app/skills/builtin/cognitive_memory/__init__.py +4 -0
- control_plane_api/app/skills/builtin/cognitive_memory/skill.py +174 -0
- control_plane_api/app/skills/builtin/contextual_awareness/__init__.py +4 -0
- control_plane_api/app/skills/builtin/contextual_awareness/skill.py +387 -0
- control_plane_api/app/skills/builtin/data_visualization/__init__.py +4 -0
- control_plane_api/app/skills/builtin/data_visualization/skill.py +154 -0
- control_plane_api/app/skills/builtin/docker/__init__.py +4 -0
- control_plane_api/app/skills/builtin/docker/skill.py +104 -0
- control_plane_api/app/skills/builtin/file_generation/__init__.py +4 -0
- control_plane_api/app/skills/builtin/file_generation/skill.py +94 -0
- control_plane_api/app/skills/builtin/file_system/__init__.py +4 -0
- control_plane_api/app/skills/builtin/file_system/skill.py +110 -0
- control_plane_api/app/skills/builtin/knowledge_api/__init__.py +5 -0
- control_plane_api/app/skills/builtin/knowledge_api/skill.py +124 -0
- control_plane_api/app/skills/builtin/python/__init__.py +4 -0
- control_plane_api/app/skills/builtin/python/skill.py +92 -0
- control_plane_api/app/skills/builtin/remote_filesystem/__init__.py +5 -0
- control_plane_api/app/skills/builtin/remote_filesystem/skill.py +170 -0
- control_plane_api/app/skills/builtin/shell/__init__.py +4 -0
- control_plane_api/app/skills/builtin/shell/skill.py +161 -0
- control_plane_api/app/skills/builtin/slack/__init__.py +3 -0
- control_plane_api/app/skills/builtin/slack/skill.py +302 -0
- control_plane_api/app/skills/builtin/workflow_executor/__init__.py +4 -0
- control_plane_api/app/skills/builtin/workflow_executor/skill.py +469 -0
- control_plane_api/app/skills/business_intelligence.py +189 -0
- control_plane_api/app/skills/config.py +63 -0
- control_plane_api/app/skills/loaders/__init__.py +14 -0
- control_plane_api/app/skills/loaders/base.py +73 -0
- control_plane_api/app/skills/loaders/filesystem_loader.py +199 -0
- control_plane_api/app/skills/registry.py +125 -0
- control_plane_api/app/utils/helpers.py +12 -0
- control_plane_api/app/utils/workflow_executor.py +354 -0
- control_plane_api/app/workflows/__init__.py +11 -0
- control_plane_api/app/workflows/agent_execution.py +520 -0
- control_plane_api/app/workflows/agent_execution_with_skills.py +223 -0
- control_plane_api/app/workflows/namespace_provisioning.py +326 -0
- control_plane_api/app/workflows/plan_generation.py +254 -0
- control_plane_api/app/workflows/team_execution.py +442 -0
- control_plane_api/scripts/seed_models.py +240 -0
- control_plane_api/scripts/validate_existing_tool_names.py +492 -0
- control_plane_api/shared/__init__.py +8 -0
- control_plane_api/shared/version.py +17 -0
- control_plane_api/test_deduplication.py +274 -0
- control_plane_api/test_executor_deduplication_e2e.py +309 -0
- control_plane_api/test_job_execution_e2e.py +283 -0
- control_plane_api/test_real_integration.py +193 -0
- control_plane_api/version.py +38 -0
- control_plane_api/worker/__init__.py +0 -0
- control_plane_api/worker/activities/__init__.py +0 -0
- control_plane_api/worker/activities/agent_activities.py +1585 -0
- control_plane_api/worker/activities/approval_activities.py +234 -0
- control_plane_api/worker/activities/job_activities.py +199 -0
- control_plane_api/worker/activities/runtime_activities.py +1167 -0
- control_plane_api/worker/activities/skill_activities.py +282 -0
- control_plane_api/worker/activities/team_activities.py +479 -0
- control_plane_api/worker/agent_runtime_server.py +370 -0
- control_plane_api/worker/binary_manager.py +333 -0
- control_plane_api/worker/config/__init__.py +31 -0
- control_plane_api/worker/config/worker_config.py +273 -0
- control_plane_api/worker/control_plane_client.py +1491 -0
- control_plane_api/worker/examples/analytics_integration_example.py +362 -0
- control_plane_api/worker/health_monitor.py +159 -0
- control_plane_api/worker/metrics.py +237 -0
- control_plane_api/worker/models/__init__.py +1 -0
- control_plane_api/worker/models/error_events.py +105 -0
- control_plane_api/worker/models/inputs.py +89 -0
- control_plane_api/worker/runtimes/__init__.py +35 -0
- control_plane_api/worker/runtimes/agent_runtime/runtime.py +485 -0
- control_plane_api/worker/runtimes/agno/__init__.py +34 -0
- control_plane_api/worker/runtimes/agno/config.py +248 -0
- control_plane_api/worker/runtimes/agno/hooks.py +385 -0
- control_plane_api/worker/runtimes/agno/mcp_builder.py +195 -0
- control_plane_api/worker/runtimes/agno/runtime.py +1063 -0
- control_plane_api/worker/runtimes/agno/utils.py +163 -0
- control_plane_api/worker/runtimes/base.py +979 -0
- control_plane_api/worker/runtimes/claude_code/__init__.py +38 -0
- control_plane_api/worker/runtimes/claude_code/cleanup.py +184 -0
- control_plane_api/worker/runtimes/claude_code/client_pool.py +529 -0
- control_plane_api/worker/runtimes/claude_code/config.py +829 -0
- control_plane_api/worker/runtimes/claude_code/hooks.py +482 -0
- control_plane_api/worker/runtimes/claude_code/litellm_proxy.py +1702 -0
- control_plane_api/worker/runtimes/claude_code/mcp_builder.py +467 -0
- control_plane_api/worker/runtimes/claude_code/mcp_discovery.py +558 -0
- control_plane_api/worker/runtimes/claude_code/runtime.py +1546 -0
- control_plane_api/worker/runtimes/claude_code/tool_mapper.py +403 -0
- control_plane_api/worker/runtimes/claude_code/utils.py +149 -0
- control_plane_api/worker/runtimes/factory.py +173 -0
- control_plane_api/worker/runtimes/model_utils.py +107 -0
- control_plane_api/worker/runtimes/validation.py +93 -0
- control_plane_api/worker/services/__init__.py +1 -0
- control_plane_api/worker/services/agent_communication_tools.py +908 -0
- control_plane_api/worker/services/agent_executor.py +485 -0
- control_plane_api/worker/services/agent_executor_v2.py +793 -0
- control_plane_api/worker/services/analytics_collector.py +457 -0
- control_plane_api/worker/services/analytics_service.py +464 -0
- control_plane_api/worker/services/approval_tools.py +310 -0
- control_plane_api/worker/services/approval_tools_agno.py +207 -0
- control_plane_api/worker/services/cancellation_manager.py +177 -0
- control_plane_api/worker/services/code_ingestion_tools.py +465 -0
- control_plane_api/worker/services/contextual_awareness_tools.py +405 -0
- control_plane_api/worker/services/data_visualization.py +834 -0
- control_plane_api/worker/services/event_publisher.py +531 -0
- control_plane_api/worker/services/jira_tools.py +257 -0
- control_plane_api/worker/services/remote_filesystem_tools.py +498 -0
- control_plane_api/worker/services/runtime_analytics.py +328 -0
- control_plane_api/worker/services/session_service.py +365 -0
- control_plane_api/worker/services/skill_context_enhancement.py +181 -0
- control_plane_api/worker/services/skill_factory.py +471 -0
- control_plane_api/worker/services/system_prompt_enhancement.py +410 -0
- control_plane_api/worker/services/team_executor.py +715 -0
- control_plane_api/worker/services/team_executor_v2.py +1866 -0
- control_plane_api/worker/services/tool_enforcement.py +254 -0
- control_plane_api/worker/services/workflow_executor/__init__.py +52 -0
- control_plane_api/worker/services/workflow_executor/event_processor.py +287 -0
- control_plane_api/worker/services/workflow_executor/event_publisher.py +210 -0
- control_plane_api/worker/services/workflow_executor/executors/__init__.py +15 -0
- control_plane_api/worker/services/workflow_executor/executors/base.py +270 -0
- control_plane_api/worker/services/workflow_executor/executors/json_executor.py +50 -0
- control_plane_api/worker/services/workflow_executor/executors/python_executor.py +50 -0
- control_plane_api/worker/services/workflow_executor/models.py +142 -0
- control_plane_api/worker/services/workflow_executor_tools.py +1748 -0
- control_plane_api/worker/skills/__init__.py +12 -0
- control_plane_api/worker/skills/builtin/context_graph_search/README.md +213 -0
- control_plane_api/worker/skills/builtin/context_graph_search/__init__.py +5 -0
- control_plane_api/worker/skills/builtin/context_graph_search/agno_impl.py +808 -0
- control_plane_api/worker/skills/builtin/context_graph_search/skill.yaml +67 -0
- control_plane_api/worker/skills/builtin/contextual_awareness/__init__.py +4 -0
- control_plane_api/worker/skills/builtin/contextual_awareness/agno_impl.py +62 -0
- control_plane_api/worker/skills/builtin/data_visualization/agno_impl.py +18 -0
- control_plane_api/worker/skills/builtin/data_visualization/skill.yaml +84 -0
- control_plane_api/worker/skills/builtin/docker/agno_impl.py +65 -0
- control_plane_api/worker/skills/builtin/docker/skill.yaml +60 -0
- control_plane_api/worker/skills/builtin/file_generation/agno_impl.py +47 -0
- control_plane_api/worker/skills/builtin/file_generation/skill.yaml +64 -0
- control_plane_api/worker/skills/builtin/file_system/agno_impl.py +32 -0
- control_plane_api/worker/skills/builtin/file_system/skill.yaml +54 -0
- control_plane_api/worker/skills/builtin/knowledge_api/__init__.py +4 -0
- control_plane_api/worker/skills/builtin/knowledge_api/agno_impl.py +50 -0
- control_plane_api/worker/skills/builtin/knowledge_api/skill.yaml +66 -0
- control_plane_api/worker/skills/builtin/python/agno_impl.py +25 -0
- control_plane_api/worker/skills/builtin/python/skill.yaml +60 -0
- control_plane_api/worker/skills/builtin/schema_fix_mixin.py +260 -0
- control_plane_api/worker/skills/builtin/shell/agno_impl.py +31 -0
- control_plane_api/worker/skills/builtin/shell/skill.yaml +60 -0
- control_plane_api/worker/skills/builtin/slack/__init__.py +3 -0
- control_plane_api/worker/skills/builtin/slack/agno_impl.py +1282 -0
- control_plane_api/worker/skills/builtin/slack/skill.yaml +276 -0
- control_plane_api/worker/skills/builtin/workflow_executor/agno_impl.py +62 -0
- control_plane_api/worker/skills/builtin/workflow_executor/skill.yaml +79 -0
- control_plane_api/worker/skills/loaders/__init__.py +5 -0
- control_plane_api/worker/skills/loaders/base.py +23 -0
- control_plane_api/worker/skills/loaders/filesystem_loader.py +357 -0
- control_plane_api/worker/skills/registry.py +208 -0
- control_plane_api/worker/tests/__init__.py +1 -0
- control_plane_api/worker/tests/conftest.py +12 -0
- control_plane_api/worker/tests/e2e/__init__.py +0 -0
- control_plane_api/worker/tests/e2e/test_context_graph_real_api.py +338 -0
- control_plane_api/worker/tests/e2e/test_context_graph_templates_e2e.py +523 -0
- control_plane_api/worker/tests/e2e/test_enforcement_e2e.py +344 -0
- control_plane_api/worker/tests/e2e/test_execution_flow.py +571 -0
- control_plane_api/worker/tests/e2e/test_single_execution_mode.py +656 -0
- control_plane_api/worker/tests/integration/__init__.py +0 -0
- control_plane_api/worker/tests/integration/test_builtin_skills_fixes.py +245 -0
- control_plane_api/worker/tests/integration/test_context_graph_search_integration.py +365 -0
- control_plane_api/worker/tests/integration/test_control_plane_integration.py +308 -0
- control_plane_api/worker/tests/integration/test_hook_enforcement_integration.py +579 -0
- control_plane_api/worker/tests/integration/test_scheduled_job_workflow.py +237 -0
- control_plane_api/worker/tests/integration/test_system_prompt_enhancement_integration.py +343 -0
- control_plane_api/worker/tests/unit/__init__.py +0 -0
- control_plane_api/worker/tests/unit/test_builtin_skill_autoload.py +396 -0
- control_plane_api/worker/tests/unit/test_context_graph_search.py +450 -0
- control_plane_api/worker/tests/unit/test_context_graph_templates.py +403 -0
- control_plane_api/worker/tests/unit/test_control_plane_client.py +401 -0
- control_plane_api/worker/tests/unit/test_control_plane_client_jobs.py +345 -0
- control_plane_api/worker/tests/unit/test_job_activities.py +353 -0
- control_plane_api/worker/tests/unit/test_skill_context_enhancement.py +321 -0
- control_plane_api/worker/tests/unit/test_system_prompt_enhancement.py +415 -0
- control_plane_api/worker/tests/unit/test_tool_enforcement.py +324 -0
- control_plane_api/worker/utils/__init__.py +1 -0
- control_plane_api/worker/utils/chunk_batcher.py +330 -0
- control_plane_api/worker/utils/environment.py +65 -0
- control_plane_api/worker/utils/error_publisher.py +260 -0
- control_plane_api/worker/utils/event_batcher.py +256 -0
- control_plane_api/worker/utils/logging_config.py +335 -0
- control_plane_api/worker/utils/logging_helper.py +326 -0
- control_plane_api/worker/utils/parameter_validator.py +120 -0
- control_plane_api/worker/utils/retry_utils.py +60 -0
- control_plane_api/worker/utils/streaming_utils.py +665 -0
- control_plane_api/worker/utils/tool_validation.py +332 -0
- control_plane_api/worker/utils/workspace_manager.py +163 -0
- control_plane_api/worker/websocket_client.py +393 -0
- control_plane_api/worker/worker.py +1297 -0
- control_plane_api/worker/workflows/__init__.py +0 -0
- control_plane_api/worker/workflows/agent_execution.py +909 -0
- control_plane_api/worker/workflows/scheduled_job_wrapper.py +332 -0
- control_plane_api/worker/workflows/team_execution.py +611 -0
- kubiya_control_plane_api-0.9.15.dist-info/METADATA +354 -0
- kubiya_control_plane_api-0.9.15.dist-info/RECORD +479 -0
- kubiya_control_plane_api-0.9.15.dist-info/WHEEL +5 -0
- kubiya_control_plane_api-0.9.15.dist-info/entry_points.txt +5 -0
- kubiya_control_plane_api-0.9.15.dist-info/licenses/LICENSE +676 -0
- kubiya_control_plane_api-0.9.15.dist-info/top_level.txt +3 -0
- scripts/__init__.py +1 -0
- scripts/migrations.py +39 -0
- scripts/seed_worker_queues.py +128 -0
- scripts/setup_agent_runtime.py +142 -0
- worker_internal/__init__.py +1 -0
- worker_internal/planner/__init__.py +1 -0
- worker_internal/planner/activities.py +1499 -0
- worker_internal/planner/agent_tools.py +197 -0
- worker_internal/planner/event_models.py +148 -0
- worker_internal/planner/event_publisher.py +67 -0
- worker_internal/planner/models.py +199 -0
- worker_internal/planner/retry_logic.py +134 -0
- worker_internal/planner/worker.py +300 -0
- worker_internal/planner/workflows.py +970 -0
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
"""Worker Health Checker Service
|
|
2
|
+
|
|
3
|
+
This service detects worker and service availability to enable graceful degradation
|
|
4
|
+
when critical services (Temporal, Redis, Database) are unavailable.
|
|
5
|
+
|
|
6
|
+
Degradation Modes:
|
|
7
|
+
- FULL: All services available (Temporal + Redis + Database)
|
|
8
|
+
- HISTORY_ONLY: Only database available (can serve historical data)
|
|
9
|
+
- LIVE_ONLY: Only Redis available (can serve live events)
|
|
10
|
+
- DEGRADED: Partial functionality available
|
|
11
|
+
- UNAVAILABLE: Critical services down
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
health_checker = WorkerHealthChecker(
|
|
15
|
+
temporal_client=temporal_client,
|
|
16
|
+
redis_client=redis_client,
|
|
17
|
+
db_session=db_session
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
mode = await health_checker.get_degradation_mode()
|
|
21
|
+
capabilities = health_checker.get_capabilities(mode)
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import asyncio
|
|
25
|
+
import time
|
|
26
|
+
from enum import Enum
|
|
27
|
+
from typing import Dict, List, Optional, Any
|
|
28
|
+
import structlog
|
|
29
|
+
from sqlalchemy.orm import Session
|
|
30
|
+
from sqlalchemy import text
|
|
31
|
+
|
|
32
|
+
logger = structlog.get_logger()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class DegradationMode(Enum):
|
|
36
|
+
"""Service degradation modes based on availability."""
|
|
37
|
+
|
|
38
|
+
FULL = "full" # All services available
|
|
39
|
+
HISTORY_ONLY = "history_only" # Only database available
|
|
40
|
+
LIVE_ONLY = "live_only" # Only Redis available
|
|
41
|
+
DEGRADED = "degraded" # Partial functionality
|
|
42
|
+
UNAVAILABLE = "unavailable" # Critical services down
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# Capabilities available in each degradation mode
|
|
46
|
+
CAPABILITIES = {
|
|
47
|
+
DegradationMode.FULL: [
|
|
48
|
+
"history",
|
|
49
|
+
"live_events",
|
|
50
|
+
"status_updates",
|
|
51
|
+
"completion_detection",
|
|
52
|
+
"workflow_queries",
|
|
53
|
+
],
|
|
54
|
+
DegradationMode.HISTORY_ONLY: [
|
|
55
|
+
"history",
|
|
56
|
+
],
|
|
57
|
+
DegradationMode.LIVE_ONLY: [
|
|
58
|
+
"live_events",
|
|
59
|
+
],
|
|
60
|
+
DegradationMode.DEGRADED: [
|
|
61
|
+
"partial_functionality",
|
|
62
|
+
],
|
|
63
|
+
DegradationMode.UNAVAILABLE: [],
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class WorkerHealthChecker:
|
|
68
|
+
"""
|
|
69
|
+
Health checker for worker and service availability.
|
|
70
|
+
|
|
71
|
+
Performs health checks on critical services with proper timeouts to
|
|
72
|
+
avoid blocking operations. Results can be cached to prevent excessive
|
|
73
|
+
health check overhead.
|
|
74
|
+
|
|
75
|
+
Attributes:
|
|
76
|
+
temporal_client: Temporal client instance (optional)
|
|
77
|
+
redis_client: Redis client instance (optional)
|
|
78
|
+
db_session: Database session instance (optional)
|
|
79
|
+
cache_ttl: Time-to-live for health check cache in seconds
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
# Timeout values for health checks (in seconds)
|
|
83
|
+
TEMPORAL_TIMEOUT = 2.0 # Fast timeout - don't block on Temporal
|
|
84
|
+
REDIS_TIMEOUT = 1.0 # Redis should be fast
|
|
85
|
+
DATABASE_TIMEOUT = 1.0 # Database should be fast
|
|
86
|
+
|
|
87
|
+
def __init__(
|
|
88
|
+
self,
|
|
89
|
+
temporal_client=None,
|
|
90
|
+
redis_client=None,
|
|
91
|
+
db_session: Optional[Session] = None,
|
|
92
|
+
cache_ttl: int = 10, # Cache health check results for 10 seconds
|
|
93
|
+
):
|
|
94
|
+
"""
|
|
95
|
+
Initialize WorkerHealthChecker.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
temporal_client: Temporal client instance (can be None)
|
|
99
|
+
redis_client: Redis client instance (can be None)
|
|
100
|
+
db_session: Database session instance (can be None)
|
|
101
|
+
cache_ttl: Cache TTL in seconds for health check results
|
|
102
|
+
"""
|
|
103
|
+
self.temporal_client = temporal_client
|
|
104
|
+
self.redis_client = redis_client
|
|
105
|
+
self.db_session = db_session
|
|
106
|
+
self.cache_ttl = cache_ttl
|
|
107
|
+
|
|
108
|
+
# Cache health check results to avoid excessive checks
|
|
109
|
+
# Format: {"temporal": (timestamp, result), "redis": (timestamp, result), ...}
|
|
110
|
+
self._last_check: Dict[str, tuple[float, bool]] = {}
|
|
111
|
+
|
|
112
|
+
def _is_cached(self, service: str) -> Optional[bool]:
|
|
113
|
+
"""
|
|
114
|
+
Check if health check result is cached and still valid.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
service: Service name ("temporal", "redis", "database")
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
Cached result if valid, None if cache miss or expired
|
|
121
|
+
"""
|
|
122
|
+
if service not in self._last_check:
|
|
123
|
+
return None
|
|
124
|
+
|
|
125
|
+
timestamp, result = self._last_check[service]
|
|
126
|
+
if time.time() - timestamp < self.cache_ttl:
|
|
127
|
+
logger.debug(
|
|
128
|
+
"health_check_cache_hit",
|
|
129
|
+
service=service,
|
|
130
|
+
result=result,
|
|
131
|
+
age_seconds=time.time() - timestamp
|
|
132
|
+
)
|
|
133
|
+
return result
|
|
134
|
+
|
|
135
|
+
return None
|
|
136
|
+
|
|
137
|
+
def _cache_result(self, service: str, result: bool) -> None:
|
|
138
|
+
"""
|
|
139
|
+
Cache health check result.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
service: Service name ("temporal", "redis", "database")
|
|
143
|
+
result: Health check result (True if healthy)
|
|
144
|
+
"""
|
|
145
|
+
self._last_check[service] = (time.time(), result)
|
|
146
|
+
|
|
147
|
+
async def check_temporal_connectivity(self) -> bool:
|
|
148
|
+
"""
|
|
149
|
+
Check if Temporal is accessible.
|
|
150
|
+
|
|
151
|
+
Attempts to verify Temporal client is connected and responsive.
|
|
152
|
+
Uses a fast timeout (2 seconds) to fail quickly when worker is down.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
True if connected and responsive, False otherwise
|
|
156
|
+
|
|
157
|
+
Test Strategy:
|
|
158
|
+
- Test with Temporal unavailable (connection timeout)
|
|
159
|
+
- Test with Temporal available (successful connection)
|
|
160
|
+
- Test timeout behavior (should complete within 2 seconds)
|
|
161
|
+
"""
|
|
162
|
+
# Check cache first
|
|
163
|
+
cached = self._is_cached("temporal")
|
|
164
|
+
if cached is not None:
|
|
165
|
+
return cached
|
|
166
|
+
|
|
167
|
+
if not self.temporal_client:
|
|
168
|
+
logger.debug("temporal_health_check_skipped", reason="no_client")
|
|
169
|
+
self._cache_result("temporal", False)
|
|
170
|
+
return False
|
|
171
|
+
|
|
172
|
+
try:
|
|
173
|
+
# Try to describe the client with timeout
|
|
174
|
+
# This is a lightweight operation that verifies connectivity
|
|
175
|
+
t0 = time.time()
|
|
176
|
+
|
|
177
|
+
# Try getting workflow service with timeout
|
|
178
|
+
result = await asyncio.wait_for(
|
|
179
|
+
self._check_temporal_service(),
|
|
180
|
+
timeout=self.TEMPORAL_TIMEOUT
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
duration_ms = int((time.time() - t0) * 1000)
|
|
184
|
+
logger.debug(
|
|
185
|
+
"temporal_health_check_passed",
|
|
186
|
+
duration_ms=duration_ms,
|
|
187
|
+
result=result
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
self._cache_result("temporal", result)
|
|
191
|
+
return result
|
|
192
|
+
|
|
193
|
+
except asyncio.TimeoutError:
|
|
194
|
+
duration_ms = int((time.time() - t0) * 1000)
|
|
195
|
+
logger.warning(
|
|
196
|
+
"temporal_health_check_timeout",
|
|
197
|
+
timeout_seconds=self.TEMPORAL_TIMEOUT,
|
|
198
|
+
duration_ms=duration_ms
|
|
199
|
+
)
|
|
200
|
+
self._cache_result("temporal", False)
|
|
201
|
+
return False
|
|
202
|
+
|
|
203
|
+
except Exception as e:
|
|
204
|
+
logger.warning(
|
|
205
|
+
"temporal_health_check_failed",
|
|
206
|
+
error=str(e),
|
|
207
|
+
error_type=type(e).__name__
|
|
208
|
+
)
|
|
209
|
+
self._cache_result("temporal", False)
|
|
210
|
+
return False
|
|
211
|
+
|
|
212
|
+
async def _check_temporal_service(self) -> bool:
|
|
213
|
+
"""
|
|
214
|
+
Internal method to check Temporal service availability.
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
True if service is accessible
|
|
218
|
+
"""
|
|
219
|
+
try:
|
|
220
|
+
# Check if client has a workflow service
|
|
221
|
+
# This is a lightweight check that doesn't require a specific workflow
|
|
222
|
+
if hasattr(self.temporal_client, 'workflow_service'):
|
|
223
|
+
# Client is properly initialized
|
|
224
|
+
return True
|
|
225
|
+
|
|
226
|
+
# Fallback: Check if client object exists
|
|
227
|
+
return self.temporal_client is not None
|
|
228
|
+
|
|
229
|
+
except Exception as e:
|
|
230
|
+
logger.debug("temporal_service_check_error", error=str(e))
|
|
231
|
+
return False
|
|
232
|
+
|
|
233
|
+
async def check_redis_connectivity(self) -> bool:
|
|
234
|
+
"""
|
|
235
|
+
Check if Redis is accessible.
|
|
236
|
+
|
|
237
|
+
Performs a simple PING operation to verify Redis connectivity.
|
|
238
|
+
Uses a 1-second timeout to fail quickly.
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
True if connected and responsive, False otherwise
|
|
242
|
+
|
|
243
|
+
Test Strategy:
|
|
244
|
+
- Test with Redis unavailable (connection error)
|
|
245
|
+
- Test with Redis available (successful ping)
|
|
246
|
+
- Test timeout behavior (should complete within 1 second)
|
|
247
|
+
"""
|
|
248
|
+
# Check cache first
|
|
249
|
+
cached = self._is_cached("redis")
|
|
250
|
+
if cached is not None:
|
|
251
|
+
return cached
|
|
252
|
+
|
|
253
|
+
if not self.redis_client:
|
|
254
|
+
logger.debug("redis_health_check_skipped", reason="no_client")
|
|
255
|
+
self._cache_result("redis", False)
|
|
256
|
+
return False
|
|
257
|
+
|
|
258
|
+
try:
|
|
259
|
+
t0 = time.time()
|
|
260
|
+
|
|
261
|
+
# Try a simple PING operation with timeout
|
|
262
|
+
result = await asyncio.wait_for(
|
|
263
|
+
self.redis_client.ping(),
|
|
264
|
+
timeout=self.REDIS_TIMEOUT
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
duration_ms = int((time.time() - t0) * 1000)
|
|
268
|
+
|
|
269
|
+
# Redis ping returns True/PONG on success
|
|
270
|
+
is_healthy = result is True or result == "PONG"
|
|
271
|
+
|
|
272
|
+
logger.debug(
|
|
273
|
+
"redis_health_check_passed",
|
|
274
|
+
duration_ms=duration_ms,
|
|
275
|
+
result=is_healthy
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
self._cache_result("redis", is_healthy)
|
|
279
|
+
return is_healthy
|
|
280
|
+
|
|
281
|
+
except asyncio.TimeoutError:
|
|
282
|
+
duration_ms = int((time.time() - t0) * 1000)
|
|
283
|
+
logger.warning(
|
|
284
|
+
"redis_health_check_timeout",
|
|
285
|
+
timeout_seconds=self.REDIS_TIMEOUT,
|
|
286
|
+
duration_ms=duration_ms
|
|
287
|
+
)
|
|
288
|
+
self._cache_result("redis", False)
|
|
289
|
+
return False
|
|
290
|
+
|
|
291
|
+
except Exception as e:
|
|
292
|
+
logger.warning(
|
|
293
|
+
"redis_health_check_failed",
|
|
294
|
+
error=str(e),
|
|
295
|
+
error_type=type(e).__name__
|
|
296
|
+
)
|
|
297
|
+
self._cache_result("redis", False)
|
|
298
|
+
return False
|
|
299
|
+
|
|
300
|
+
async def check_database_connectivity(self) -> bool:
|
|
301
|
+
"""
|
|
302
|
+
Check if database is accessible.
|
|
303
|
+
|
|
304
|
+
Performs a simple SELECT 1 query to verify database connectivity.
|
|
305
|
+
Uses a 1-second timeout to fail quickly.
|
|
306
|
+
|
|
307
|
+
Returns:
|
|
308
|
+
True if connected and responsive, False otherwise
|
|
309
|
+
|
|
310
|
+
Test Strategy:
|
|
311
|
+
- Test with database unavailable (connection error)
|
|
312
|
+
- Test with database available (successful query)
|
|
313
|
+
- Test timeout behavior (should complete within 1 second)
|
|
314
|
+
"""
|
|
315
|
+
# Check cache first
|
|
316
|
+
cached = self._is_cached("database")
|
|
317
|
+
if cached is not None:
|
|
318
|
+
return cached
|
|
319
|
+
|
|
320
|
+
if not self.db_session:
|
|
321
|
+
logger.debug("database_health_check_skipped", reason="no_session")
|
|
322
|
+
self._cache_result("database", False)
|
|
323
|
+
return False
|
|
324
|
+
|
|
325
|
+
try:
|
|
326
|
+
t0 = time.time()
|
|
327
|
+
|
|
328
|
+
# Try a simple query with timeout
|
|
329
|
+
result = await asyncio.wait_for(
|
|
330
|
+
self._check_database_query(),
|
|
331
|
+
timeout=self.DATABASE_TIMEOUT
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
duration_ms = int((time.time() - t0) * 1000)
|
|
335
|
+
logger.debug(
|
|
336
|
+
"database_health_check_passed",
|
|
337
|
+
duration_ms=duration_ms,
|
|
338
|
+
result=result
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
self._cache_result("database", result)
|
|
342
|
+
return result
|
|
343
|
+
|
|
344
|
+
except asyncio.TimeoutError:
|
|
345
|
+
duration_ms = int((time.time() - t0) * 1000)
|
|
346
|
+
logger.warning(
|
|
347
|
+
"database_health_check_timeout",
|
|
348
|
+
timeout_seconds=self.DATABASE_TIMEOUT,
|
|
349
|
+
duration_ms=duration_ms
|
|
350
|
+
)
|
|
351
|
+
self._cache_result("database", False)
|
|
352
|
+
return False
|
|
353
|
+
|
|
354
|
+
except Exception as e:
|
|
355
|
+
logger.warning(
|
|
356
|
+
"database_health_check_failed",
|
|
357
|
+
error=str(e),
|
|
358
|
+
error_type=type(e).__name__
|
|
359
|
+
)
|
|
360
|
+
self._cache_result("database", False)
|
|
361
|
+
return False
|
|
362
|
+
|
|
363
|
+
async def _check_database_query(self) -> bool:
|
|
364
|
+
"""
|
|
365
|
+
Internal method to execute database health check query.
|
|
366
|
+
|
|
367
|
+
Returns:
|
|
368
|
+
True if query successful
|
|
369
|
+
"""
|
|
370
|
+
try:
|
|
371
|
+
# Execute simple query to verify database connectivity
|
|
372
|
+
result = self.db_session.execute(text("SELECT 1"))
|
|
373
|
+
|
|
374
|
+
# Verify we got a result
|
|
375
|
+
if result:
|
|
376
|
+
return True
|
|
377
|
+
|
|
378
|
+
return False
|
|
379
|
+
|
|
380
|
+
except Exception as e:
|
|
381
|
+
logger.debug("database_query_error", error=str(e))
|
|
382
|
+
return False
|
|
383
|
+
|
|
384
|
+
async def check_all(self) -> Dict[str, bool]:
|
|
385
|
+
"""
|
|
386
|
+
Run all health checks and return results.
|
|
387
|
+
|
|
388
|
+
Executes all health checks concurrently for efficiency.
|
|
389
|
+
|
|
390
|
+
Returns:
|
|
391
|
+
Dictionary with health check results:
|
|
392
|
+
{
|
|
393
|
+
"temporal": bool,
|
|
394
|
+
"redis": bool,
|
|
395
|
+
"database": bool
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
Test Strategy:
|
|
399
|
+
- Test with all services available
|
|
400
|
+
- Test with all services unavailable
|
|
401
|
+
- Test with mixed availability
|
|
402
|
+
"""
|
|
403
|
+
# Run all checks concurrently for efficiency
|
|
404
|
+
temporal_check, redis_check, db_check = await asyncio.gather(
|
|
405
|
+
self.check_temporal_connectivity(),
|
|
406
|
+
self.check_redis_connectivity(),
|
|
407
|
+
self.check_database_connectivity(),
|
|
408
|
+
return_exceptions=True # Don't let one failure stop others
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
# Handle any exceptions from gather
|
|
412
|
+
temporal_ok = temporal_check if isinstance(temporal_check, bool) else False
|
|
413
|
+
redis_ok = redis_check if isinstance(redis_check, bool) else False
|
|
414
|
+
db_ok = db_check if isinstance(db_check, bool) else False
|
|
415
|
+
|
|
416
|
+
results = {
|
|
417
|
+
"temporal": temporal_ok,
|
|
418
|
+
"redis": redis_ok,
|
|
419
|
+
"database": db_ok,
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
logger.info("health_check_all_completed", **results)
|
|
423
|
+
return results
|
|
424
|
+
|
|
425
|
+
async def get_degradation_mode(self) -> DegradationMode:
|
|
426
|
+
"""
|
|
427
|
+
Determine current degradation mode based on service availability.
|
|
428
|
+
|
|
429
|
+
Logic:
|
|
430
|
+
- All available: FULL
|
|
431
|
+
- Only DB: HISTORY_ONLY
|
|
432
|
+
- Only Redis: LIVE_ONLY
|
|
433
|
+
- Some available: DEGRADED
|
|
434
|
+
- None available: UNAVAILABLE
|
|
435
|
+
|
|
436
|
+
Returns:
|
|
437
|
+
Current degradation mode
|
|
438
|
+
|
|
439
|
+
Test Strategy:
|
|
440
|
+
- Test all degradation mode combinations
|
|
441
|
+
- Test mode selection logic
|
|
442
|
+
- Test with various service availability patterns
|
|
443
|
+
"""
|
|
444
|
+
# Get health check results
|
|
445
|
+
temporal_ok = await self.check_temporal_connectivity()
|
|
446
|
+
redis_ok = await self.check_redis_connectivity()
|
|
447
|
+
db_ok = await self.check_database_connectivity()
|
|
448
|
+
|
|
449
|
+
# Determine degradation mode
|
|
450
|
+
if temporal_ok and redis_ok and db_ok:
|
|
451
|
+
mode = DegradationMode.FULL
|
|
452
|
+
|
|
453
|
+
elif db_ok and not (temporal_ok or redis_ok):
|
|
454
|
+
# Database only - can serve historical data
|
|
455
|
+
mode = DegradationMode.HISTORY_ONLY
|
|
456
|
+
|
|
457
|
+
elif redis_ok and not db_ok:
|
|
458
|
+
# Redis only - can serve live events (no history)
|
|
459
|
+
mode = DegradationMode.LIVE_ONLY
|
|
460
|
+
|
|
461
|
+
elif any([temporal_ok, redis_ok, db_ok]):
|
|
462
|
+
# Some services available but not full functionality
|
|
463
|
+
mode = DegradationMode.DEGRADED
|
|
464
|
+
|
|
465
|
+
else:
|
|
466
|
+
# Nothing available
|
|
467
|
+
mode = DegradationMode.UNAVAILABLE
|
|
468
|
+
|
|
469
|
+
logger.info(
|
|
470
|
+
"degradation_mode_determined",
|
|
471
|
+
mode=mode.value,
|
|
472
|
+
temporal=temporal_ok,
|
|
473
|
+
redis=redis_ok,
|
|
474
|
+
database=db_ok
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
return mode
|
|
478
|
+
|
|
479
|
+
def get_capabilities(self, mode: DegradationMode) -> List[str]:
|
|
480
|
+
"""
|
|
481
|
+
Return list of available capabilities for given mode.
|
|
482
|
+
|
|
483
|
+
Args:
|
|
484
|
+
mode: Degradation mode
|
|
485
|
+
|
|
486
|
+
Returns:
|
|
487
|
+
List of capability names available in this mode
|
|
488
|
+
|
|
489
|
+
Examples:
|
|
490
|
+
>>> checker = WorkerHealthChecker()
|
|
491
|
+
>>> checker.get_capabilities(DegradationMode.FULL)
|
|
492
|
+
['history', 'live_events', 'status_updates', 'completion_detection', 'workflow_queries']
|
|
493
|
+
|
|
494
|
+
>>> checker.get_capabilities(DegradationMode.HISTORY_ONLY)
|
|
495
|
+
['history']
|
|
496
|
+
"""
|
|
497
|
+
capabilities = CAPABILITIES.get(mode, [])
|
|
498
|
+
|
|
499
|
+
logger.debug(
|
|
500
|
+
"capabilities_retrieved",
|
|
501
|
+
mode=mode.value,
|
|
502
|
+
capabilities=capabilities
|
|
503
|
+
)
|
|
504
|
+
|
|
505
|
+
return capabilities
|
|
506
|
+
|
|
507
|
+
def clear_cache(self) -> None:
|
|
508
|
+
"""
|
|
509
|
+
Clear all cached health check results.
|
|
510
|
+
|
|
511
|
+
Useful when you want to force fresh health checks.
|
|
512
|
+
"""
|
|
513
|
+
self._last_check.clear()
|
|
514
|
+
logger.debug("health_check_cache_cleared")
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Streaming execution components.
|
|
3
|
+
|
|
4
|
+
This module contains components for handling streaming execution data,
|
|
5
|
+
including deduplication, event management, and message processing.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .deduplication import MessageDeduplicator
|
|
9
|
+
from .history_loader import HistoryLoader
|
|
10
|
+
from .live_source import LiveEventSource
|
|
11
|
+
from .event_buffer import EventBuffer
|
|
12
|
+
from .event_formatter import EventFormatter
|
|
13
|
+
from .streamer import ExecutionStreamer
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"MessageDeduplicator",
|
|
17
|
+
"HistoryLoader",
|
|
18
|
+
"LiveEventSource",
|
|
19
|
+
"EventBuffer",
|
|
20
|
+
"EventFormatter",
|
|
21
|
+
"ExecutionStreamer",
|
|
22
|
+
]
|