cancan-microstack 0.0.1__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.
- cancan_microstack/__init__.py +14 -0
- cancan_microstack/__version__.py +10 -0
- cancan_microstack/assets/__init__.py +6 -0
- cancan_microstack/assets/builds/caddy/Caddyfile +187 -0
- cancan_microstack/assets/builds/caddy/DEPLOYMENT.md +303 -0
- cancan_microstack/assets/builds/caddy/Dockerfile +46 -0
- cancan_microstack/assets/builds/caddy/README.md +343 -0
- cancan_microstack/assets/builds/caddy/geoip/README.md +5 -0
- cancan_microstack/assets/builds/caddy/start.sh +78 -0
- cancan_microstack/assets/builds/caddy/waf/coraza.conf +179 -0
- cancan_microstack/assets/builds/service/Dockerfile +59 -0
- cancan_microstack/assets/builds/service/README.md +13 -0
- cancan_microstack/assets/ddl/create_db.sql +22 -0
- cancan_microstack/assets/ddl/infra/execution_log_tbl.sql +46 -0
- cancan_microstack/assets/ddl/infra/node_instance_tbl.sql +56 -0
- cancan_microstack/assets/ddl/infra/service_action_log_tbl.sql +36 -0
- cancan_microstack/assets/ddl/infra/service_config_tbl.sql +26 -0
- cancan_microstack/assets/ddl/infra/service_info_tbl.sql +45 -0
- cancan_microstack/assets/ddl/infra/service_instance_tbl.sql +54 -0
- cancan_microstack/assets/ddl/infra/service_operation_tbl.sql +47 -0
- cancan_microstack/assets/ddl/infra/workflow_definition_tbl.sql +60 -0
- cancan_microstack/assets/ddl/infra/workflow_definition_version_tbl.sql +35 -0
- cancan_microstack/assets/ddl/infra/workflow_engine_alert_tbl.sql +34 -0
- cancan_microstack/assets/ddl/infra/workflow_run_tbl.sql +52 -0
- cancan_microstack/assets/ddl/ops/admin_user_tbl.sql +34 -0
- cancan_microstack/assets/ddl/ops/caddy_access_log_tbl.sql +91 -0
- cancan_microstack/assets/ddl/ops/caddy_certificate_tbl.sql +59 -0
- cancan_microstack/assets/ddl/ops/caddy_rate_limit_tbl.sql +64 -0
- cancan_microstack/assets/ddl/ops/caddy_route_tbl.sql +63 -0
- cancan_microstack/assets/ddl/ops/caddy_stats_tbl.sql +77 -0
- cancan_microstack/assets/ddl/trigger.sql +21 -0
- cancan_microstack/assets/docker/docker-compose.infra.yml +401 -0
- cancan_microstack/assets/scripts/README.md +195 -0
- cancan_microstack/assets/scripts/docker/build_images.sh +44 -0
- cancan_microstack/assets/scripts/docker/force_rebuild_images.sh +38 -0
- cancan_microstack/assets/scripts/docker/rebuild_all.sh +34 -0
- cancan_microstack/assets/scripts/docker/rebuild_compose.sh +61 -0
- cancan_microstack/assets/scripts/docker/restart.sh +35 -0
- cancan_microstack/assets/scripts/docker/restart_compose.sh +35 -0
- cancan_microstack/assets/scripts/docker/start.sh +78 -0
- cancan_microstack/assets/scripts/docker/start_all.sh +46 -0
- cancan_microstack/assets/scripts/docker/start_compose.sh +66 -0
- cancan_microstack/assets/scripts/docker/stop.sh +67 -0
- cancan_microstack/assets/scripts/docker/stop_all.sh +38 -0
- cancan_microstack/assets/scripts/docker/stop_compose.sh +38 -0
- cancan_microstack/assets/scripts/podman/build_images_podman.sh +59 -0
- cancan_microstack/assets/scripts/podman/cleanup_podman.sh +25 -0
- cancan_microstack/assets/scripts/podman/force_rebuild_images_podman.sh +56 -0
- cancan_microstack/assets/scripts/podman/rebuild_all_podman.sh +37 -0
- cancan_microstack/assets/scripts/podman/rebuild_compose_podman.sh +60 -0
- cancan_microstack/assets/scripts/podman/restart_compose_podman.sh +73 -0
- cancan_microstack/assets/scripts/podman/start_all_podman.sh +66 -0
- cancan_microstack/assets/scripts/podman/start_compose_podman.sh +80 -0
- cancan_microstack/assets/scripts/podman/start_podman.sh +91 -0
- cancan_microstack/assets/scripts/podman/stop.sh +73 -0
- cancan_microstack/assets/scripts/podman/stop_all_podman.sh +34 -0
- cancan_microstack/assets/scripts/podman/stop_compose_podman.sh +58 -0
- cancan_microstack/assets/scripts/start_controllersrv.sh +9 -0
- cancan_microstack/assets/scripts/utils/check_all_db_tables.sh +104 -0
- cancan_microstack/assets/scripts/utils/check_env.sh +177 -0
- cancan_microstack/assets/scripts/utils/check_service_management_deployment.sh +225 -0
- cancan_microstack/assets/scripts/utils/deploy_service_management.sh +176 -0
- cancan_microstack/assets/scripts/utils/force_reload_infrasrv.sh +52 -0
- cancan_microstack/assets/scripts/utils/monitor_service_management.sh +187 -0
- cancan_microstack/assets/scripts/utils/reset_postgres_volume.sh +68 -0
- cancan_microstack/assets/scripts/utils/test_async_operations.sh +141 -0
- cancan_microstack/assets/scripts/utils/verify_real_operations.sh +76 -0
- cancan_microstack/assets/service/Dockerfile +65 -0
- cancan_microstack/assets/www/adminops/assets/AppEmpty.vue_vue_type_script_setup_true_lang-BOKUurnM.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ConfigManage-DKV5YOUz.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ConfigManage-Y5bhy7wG.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ConsoleManage-8ljYvCW2.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ConsoleManage-BWpyqbuQ.css +1 -0
- cancan_microstack/assets/www/adminops/assets/DashboardNew-B9Nf1OPl.js +1 -0
- cancan_microstack/assets/www/adminops/assets/DashboardNew-DYWZKQ1V.css +1 -0
- cancan_microstack/assets/www/adminops/assets/LogSearch-CA0Jhe78.js +1 -0
- cancan_microstack/assets/www/adminops/assets/LogSearch-CCZfTNPF.css +1 -0
- cancan_microstack/assets/www/adminops/assets/LoginView-BId3kP3M.css +1 -0
- cancan_microstack/assets/www/adminops/assets/LoginView-BQZTV_Qy.js +1 -0
- cancan_microstack/assets/www/adminops/assets/OperationProgressDialog-BdEYwqFq.js +1 -0
- cancan_microstack/assets/www/adminops/assets/OperationProgressDialog-D-pASR8G.css +1 -0
- cancan_microstack/assets/www/adminops/assets/PageContainer-Byss-yUC.js +1 -0
- cancan_microstack/assets/www/adminops/assets/PageContainer-C3nSZwM7.css +1 -0
- cancan_microstack/assets/www/adminops/assets/RateLimitManage-BDI8jLpC.css +1 -0
- cancan_microstack/assets/www/adminops/assets/RateLimitManage-DJY4NiF-.js +1 -0
- cancan_microstack/assets/www/adminops/assets/RouteManage-DaUQ4QLw.css +1 -0
- cancan_microstack/assets/www/adminops/assets/RouteManage-w9XCU0UA.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceCard-BFzHe6Tw.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceCard-BJUhWnA-.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceDetail-Cw24WuKp.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceDetail-Yum47zdB.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceList-C7ryvbhE.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceList-Cgd01fUx.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceLogs-COpG9H0h.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceLogs-H_Alq0cf.css +1 -0
- cancan_microstack/assets/www/adminops/assets/StatsOverview-D0TwMQkA.js +39 -0
- cancan_microstack/assets/www/adminops/assets/StatsOverview-lqAN6pqM.css +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpBindView-CWlAmzFt.js +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpBindView-HoQC1lhx.css +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpVerifyView-BHN1VtX1.css +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpVerifyView-D3w_lZk8.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowCenter-DU_mpIA0.css +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowCenter-i50rZyxN.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowDesigner-CnHokPL9.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowDesigner-DaZaZpLd.css +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowRuns-B09hK48c.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowRuns-wGutKIIU.css +1 -0
- cancan_microstack/assets/www/adminops/assets/caddy-nnCKf8fG.js +1 -0
- cancan_microstack/assets/www/adminops/assets/format-Cuzxgna9.js +1 -0
- cancan_microstack/assets/www/adminops/assets/index-CiFlm8oc.js +64 -0
- cancan_microstack/assets/www/adminops/assets/index-UW0T1Dkc.css +1 -0
- cancan_microstack/assets/www/adminops/assets/service-BYlgGPs_.js +1 -0
- cancan_microstack/assets/www/adminops/assets/service-operation-6GzLw2Z1.js +1 -0
- cancan_microstack/assets/www/adminops/assets/style-CcIXnQ5y.css +1 -0
- cancan_microstack/assets/www/adminops/assets/style-lRnStdGu.js +39 -0
- cancan_microstack/assets/www/adminops/assets/useDebounce-BRlqfXqf.js +1 -0
- cancan_microstack/assets/www/adminops/assets/workflow-CUXs39Ac.js +1 -0
- cancan_microstack/assets/www/adminops/index.html +16 -0
- cancan_microstack/assets/www/adminops/vite.svg +1 -0
- cancan_microstack/cli/__init__.py +14 -0
- cancan_microstack/cli/__main__.py +9 -0
- cancan_microstack/cli/main.py +552 -0
- cancan_microstack/cmd/__init__.py +54 -0
- cancan_microstack/cmd/cancan/__init__.py +12 -0
- cancan_microstack/cmd/cancan/run.py +395 -0
- cancan_microstack/cmd/controllersrv/__init__.py +0 -0
- cancan_microstack/cmd/controllersrv/run.py +131 -0
- cancan_microstack/cmd/infrasrv/__init__.py +5 -0
- cancan_microstack/cmd/infrasrv/run.py +100 -0
- cancan_microstack/cmd/opsbffsrv/__init__.py +5 -0
- cancan_microstack/cmd/opsbffsrv/run.py +96 -0
- cancan_microstack/core/__init__.py +5 -0
- cancan_microstack/core/assets.py +123 -0
- cancan_microstack/core/compose_builder.py +102 -0
- cancan_microstack/core/doctor.py +152 -0
- cancan_microstack/core/microstack.py +71 -0
- cancan_microstack/core/runner.py +56 -0
- cancan_microstack/core/stack_manager.py +186 -0
- cancan_microstack/public/__init__.py +7 -0
- cancan_microstack/public/api/__init__.py +1 -0
- cancan_microstack/public/api/controllersrv_client.py +277 -0
- cancan_microstack/public/api/infrasrv_client.py +404 -0
- cancan_microstack/public/const/__init__.py +1 -0
- cancan_microstack/public/const/action_consts.py +18 -0
- cancan_microstack/public/const/app_consts.py +42 -0
- cancan_microstack/public/const/caddy_consts.py +22 -0
- cancan_microstack/public/const/controllersrv_consts.py +163 -0
- cancan_microstack/public/const/docker_consts.py +15 -0
- cancan_microstack/public/const/error.py +56 -0
- cancan_microstack/public/const/health_consts.py +52 -0
- cancan_microstack/public/const/hook_enums.py +56 -0
- cancan_microstack/public/const/logging_enums.py +13 -0
- cancan_microstack/public/const/metrics_enums.py +36 -0
- cancan_microstack/public/const/monitor_enums.py +26 -0
- cancan_microstack/public/const/operation_consts.py +53 -0
- cancan_microstack/public/const/opsbffsrv_error.py +92 -0
- cancan_microstack/public/const/overrides_consts.py +13 -0
- cancan_microstack/public/const/redis.py +17 -0
- cancan_microstack/public/const/service_consts.py +15 -0
- cancan_microstack/public/const/workflow_consts.py +65 -0
- cancan_microstack/public/error.py +41 -0
- cancan_microstack/public/logging/__init__.py +0 -0
- cancan_microstack/public/logging/initializer.py +109 -0
- cancan_microstack/public/logging/mq_handler.py +279 -0
- cancan_microstack/public/schemas/__init__.py +1 -0
- cancan_microstack/public/schemas/caddy/__init__.py +381 -0
- cancan_microstack/public/schemas/caddy/analysis.py +90 -0
- cancan_microstack/public/schemas/caddy/route.py +18 -0
- cancan_microstack/public/schemas/common.py +79 -0
- cancan_microstack/public/schemas/controllersrv/__init__.py +3 -0
- cancan_microstack/public/schemas/controllersrv/async_requests.py +30 -0
- cancan_microstack/public/schemas/controllersrv/compose_models.py +47 -0
- cancan_microstack/public/schemas/controllersrv/const.py +24 -0
- cancan_microstack/public/schemas/controllersrv/docker_models.py +45 -0
- cancan_microstack/public/schemas/controllersrv/docker_responses.py +104 -0
- cancan_microstack/public/schemas/controllersrv/requests.py +54 -0
- cancan_microstack/public/schemas/controllersrv/responses.py +124 -0
- cancan_microstack/public/schemas/controllersrv/task_models.py +102 -0
- cancan_microstack/public/schemas/controllersrv/validation.py +23 -0
- cancan_microstack/public/schemas/hook_metrics.py +124 -0
- cancan_microstack/public/schemas/hooks.py +39 -0
- cancan_microstack/public/schemas/infra/__init__.py +0 -0
- cancan_microstack/public/schemas/infra/cleanup.py +25 -0
- cancan_microstack/public/schemas/infra/container.py +74 -0
- cancan_microstack/public/schemas/infra/enums.py +135 -0
- cancan_microstack/public/schemas/infra/health_check.py +42 -0
- cancan_microstack/public/schemas/infra/hook_log.py +42 -0
- cancan_microstack/public/schemas/infra/operation.py +90 -0
- cancan_microstack/public/schemas/infra/overview.py +25 -0
- cancan_microstack/public/schemas/infra/push.py +33 -0
- cancan_microstack/public/schemas/infra/service_action_log.py +47 -0
- cancan_microstack/public/schemas/infra/service_config.py +10 -0
- cancan_microstack/public/schemas/infra/service_info.py +69 -0
- cancan_microstack/public/schemas/infra/service_instance.py +93 -0
- cancan_microstack/public/schemas/infra/service_management.py +152 -0
- cancan_microstack/public/schemas/infra/service_operation.py +79 -0
- cancan_microstack/public/schemas/infra/service_registry.py +158 -0
- cancan_microstack/public/schemas/infra/status_types.py +19 -0
- cancan_microstack/public/schemas/infra/workflow.py +566 -0
- cancan_microstack/public/schemas/logging/__init__.py +1 -0
- cancan_microstack/public/schemas/logging/log_event.py +121 -0
- cancan_microstack/public/schemas/opsbffsrv/__init__.py +1 -0
- cancan_microstack/public/schemas/opsbffsrv/async_ops.py +17 -0
- cancan_microstack/public/schemas/opsbffsrv/db_admin.py +147 -0
- cancan_microstack/public/schemas/opsbffsrv/db_init.py +48 -0
- cancan_microstack/public/schemas/opsbffsrv/service_config.py +89 -0
- cancan_microstack/public/schemas/opsbffsrv/service_logs.py +54 -0
- cancan_microstack/public/schemas/service_operation.py +24 -0
- cancan_microstack/public/schemas/service_registry.py +40 -0
- cancan_microstack/public/types/__init__.py +7 -0
- cancan_microstack/public/web/__init__.py +0 -0
- cancan_microstack/public/web/config_value.py +105 -0
- cancan_microstack/public/web/server.py +385 -0
- cancan_microstack/py.typed +0 -0
- cancan_microstack/runtime/__init__.py +0 -0
- cancan_microstack/runtime/compose_cmd.py +228 -0
- cancan_microstack/runtime/host_daemon.py +318 -0
- cancan_microstack/runtime/overrides.py +103 -0
- cancan_microstack/runtime/resources.py +25 -0
- cancan_microstack/runtime/workspace.py +94 -0
- cancan_microstack/services/__init__.py +0 -0
- cancan_microstack/services/controllersrv/__init__.py +8 -0
- cancan_microstack/services/controllersrv/application/__init__.py +0 -0
- cancan_microstack/services/controllersrv/application/docker_compose_app.py +427 -0
- cancan_microstack/services/controllersrv/conf/__init__.py +0 -0
- cancan_microstack/services/controllersrv/conf/config.py +76 -0
- cancan_microstack/services/controllersrv/conf/settings.py +54 -0
- cancan_microstack/services/controllersrv/domain/__init__.py +0 -0
- cancan_microstack/services/controllersrv/domain/docker_compose/__init__.py +0 -0
- cancan_microstack/services/controllersrv/domain/docker_compose/docker_compose_domain.py +278 -0
- cancan_microstack/services/controllersrv/domain/service_validator.py +327 -0
- cancan_microstack/services/controllersrv/domain/task/__init__.py +17 -0
- cancan_microstack/services/controllersrv/domain/task/task_queue.py +286 -0
- cancan_microstack/services/controllersrv/domain/task/task_worker.py +495 -0
- cancan_microstack/services/controllersrv/infrastructure/__init__.py +0 -0
- cancan_microstack/services/controllersrv/interface/__init__.py +0 -0
- cancan_microstack/services/controllersrv/interface/api/__init__.py +0 -0
- cancan_microstack/services/controllersrv/interface/api/docker_control_api.py +470 -0
- cancan_microstack/services/controllersrv/router.py +132 -0
- cancan_microstack/services/infrasrv/__init__.py +4 -0
- cancan_microstack/services/infrasrv/application/__init__.py +0 -0
- cancan_microstack/services/infrasrv/application/health_check_app.py +24 -0
- cancan_microstack/services/infrasrv/application/logging/__init__.py +1 -0
- cancan_microstack/services/infrasrv/application/logging/log_ingestion_service.py +183 -0
- cancan_microstack/services/infrasrv/application/service_config.py +22 -0
- cancan_microstack/services/infrasrv/application/service_logs_app.py +53 -0
- cancan_microstack/services/infrasrv/application/service_management_app.py +689 -0
- cancan_microstack/services/infrasrv/application/service_operation_tracker.py +251 -0
- cancan_microstack/services/infrasrv/application/service_registry.py +53 -0
- cancan_microstack/services/infrasrv/application/workflow/__init__.py +0 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_app.py +991 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_queue.py +302 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_tasks.py +46 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_worker_runtime.py +122 -0
- cancan_microstack/services/infrasrv/conf/__init__.py +0 -0
- cancan_microstack/services/infrasrv/conf/config.py +98 -0
- cancan_microstack/services/infrasrv/domain/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/health_check/__init__.py +3 -0
- cancan_microstack/services/infrasrv/domain/health_check/health_check_domain.py +576 -0
- cancan_microstack/services/infrasrv/domain/hooks/__init__.py +19 -0
- cancan_microstack/services/infrasrv/domain/hooks/builtin_hooks.py +308 -0
- cancan_microstack/services/infrasrv/domain/hooks/hook_registry.py +43 -0
- cancan_microstack/services/infrasrv/domain/hooks/hooks_log_utils.py +275 -0
- cancan_microstack/services/infrasrv/domain/hooks/init.py +17 -0
- cancan_microstack/services/infrasrv/domain/hooks/metrics.py +205 -0
- cancan_microstack/services/infrasrv/domain/hooks/pre_registration_hooks.py +490 -0
- cancan_microstack/services/infrasrv/domain/registry/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/registry/service_registry.py +509 -0
- cancan_microstack/services/infrasrv/domain/service_config/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/service_config/service_config.py +50 -0
- cancan_microstack/services/infrasrv/domain/service_logs/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/service_logs/service_logs_domain.py +51 -0
- cancan_microstack/services/infrasrv/domain/workflow/__init__.py +4 -0
- cancan_microstack/services/infrasrv/domain/workflow/engine.py +159 -0
- cancan_microstack/services/infrasrv/domain/workflow/node_handlers.py +509 -0
- cancan_microstack/services/infrasrv/domain/workflow/workflow_domain.py +164 -0
- cancan_microstack/services/infrasrv/infrastructure/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/api/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/api/controllersrv_api.py +165 -0
- cancan_microstack/services/infrasrv/infrastructure/cache/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/cache/service_registry_cache.py +174 -0
- cancan_microstack/services/infrasrv/infrastructure/db/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/execution_log_tbl.py +53 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/node_instance_tbl.py +55 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_action_log_tbl.py +44 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_config_tbl.py +30 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_info_tbl.py +59 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_instance_tbl.py +88 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_operation_tbl.py +73 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_definition_tbl.py +55 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_definition_version_tbl.py +43 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_engine_alert_tbl.py +57 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_run_tbl.py +56 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_action_log_op.py +239 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_config.py +80 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_config_manager.py +198 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_info_op.py +297 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_instance_op.py +688 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_operation_op.py +387 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_registry.py +124 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/workflow_op.py +804 -0
- cancan_microstack/services/infrasrv/infrastructure/ddl_manager.py +31 -0
- cancan_microstack/services/infrasrv/infrastructure/mongo/__init__.py +1 -0
- cancan_microstack/services/infrasrv/infrastructure/mongo/log_repository.py +129 -0
- cancan_microstack/services/infrasrv/interface/__init__.py +0 -0
- cancan_microstack/services/infrasrv/interface/api/__init__.py +0 -0
- cancan_microstack/services/infrasrv/interface/api/health_check_api.py +29 -0
- cancan_microstack/services/infrasrv/interface/api/hooks.py +284 -0
- cancan_microstack/services/infrasrv/interface/api/internal.py +49 -0
- cancan_microstack/services/infrasrv/interface/api/internal_instance_api.py +265 -0
- cancan_microstack/services/infrasrv/interface/api/internal_operation_api.py +206 -0
- cancan_microstack/services/infrasrv/interface/api/service_config.py +50 -0
- cancan_microstack/services/infrasrv/interface/api/service_logs_api.py +49 -0
- cancan_microstack/services/infrasrv/interface/api/service_management_api.py +113 -0
- cancan_microstack/services/infrasrv/interface/api/service_registry.py +117 -0
- cancan_microstack/services/infrasrv/interface/api/workflow_api.py +303 -0
- cancan_microstack/services/infrasrv/interface/schedule/__init__.py +0 -0
- cancan_microstack/services/infrasrv/interface/schedule/cleanup.py +13 -0
- cancan_microstack/services/infrasrv/interface/schedule/health_check.py +27 -0
- cancan_microstack/services/infrasrv/interface/schedule/log_cleanup.py +26 -0
- cancan_microstack/services/infrasrv/interface/schedule/operation_tracker.py +25 -0
- cancan_microstack/services/infrasrv/interface/schedule/scheduler.py +39 -0
- cancan_microstack/services/infrasrv/interface/schedule/workflow_scheduler.py +115 -0
- cancan_microstack/services/infrasrv/router.py +341 -0
- cancan_microstack/services/opsbffsrv/__init__.py +4 -0
- cancan_microstack/services/opsbffsrv/application/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/application/async_operation_app.py +150 -0
- cancan_microstack/services/opsbffsrv/application/auth_app.py +285 -0
- cancan_microstack/services/opsbffsrv/application/caddy/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/application/caddy/access_log_analysis_app.py +344 -0
- cancan_microstack/services/opsbffsrv/application/caddy/access_log_ingestion_service.py +169 -0
- cancan_microstack/services/opsbffsrv/application/caddy/certificate_management_app.py +355 -0
- cancan_microstack/services/opsbffsrv/application/caddy/rate_limit_management_app.py +496 -0
- cancan_microstack/services/opsbffsrv/application/caddy/route_management_app.py +401 -0
- cancan_microstack/services/opsbffsrv/application/caddy/stats_aggregation_app.py +364 -0
- cancan_microstack/services/opsbffsrv/application/db_admin_app.py +103 -0
- cancan_microstack/services/opsbffsrv/application/db_init_app.py +283 -0
- cancan_microstack/services/opsbffsrv/application/logging/__init__.py +1 -0
- cancan_microstack/services/opsbffsrv/application/logging/log_query_app.py +28 -0
- cancan_microstack/services/opsbffsrv/application/service_config.py +158 -0
- cancan_microstack/services/opsbffsrv/application/service_logs_app.py +74 -0
- cancan_microstack/services/opsbffsrv/application/service_registry.py +36 -0
- cancan_microstack/services/opsbffsrv/application/workflow_ops_app.py +730 -0
- cancan_microstack/services/opsbffsrv/conf/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/conf/config.py +224 -0
- cancan_microstack/services/opsbffsrv/domain/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/auth/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/auth/admin_init.py +38 -0
- cancan_microstack/services/opsbffsrv/domain/auth/auth_domain.py +108 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/access_log_analysis.py +358 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/certificate_management.py +325 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/default_routes.py +53 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/rate_limit_management.py +308 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/route_management.py +279 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/stats_aggregation.py +654 -0
- cancan_microstack/services/opsbffsrv/domain/db_admin/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/db_admin/db_admin_domain.py +118 -0
- cancan_microstack/services/opsbffsrv/domain/db_init/__init__.py +3 -0
- cancan_microstack/services/opsbffsrv/domain/db_init/db_init_domain.py +358 -0
- cancan_microstack/services/opsbffsrv/domain/logging/__init__.py +1 -0
- cancan_microstack/services/opsbffsrv/domain/logging/log_query_domain.py +99 -0
- cancan_microstack/services/opsbffsrv/domain/service_config/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/service_config/service_config.py +81 -0
- cancan_microstack/services/opsbffsrv/domain/service_registry/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/service_registry/service_registry.py +292 -0
- cancan_microstack/services/opsbffsrv/infrastructure/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/api/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/api/infrasrv_api.py +242 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/captcha_service.py +67 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/password_service.py +12 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/redis_store.py +131 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/totp_service.py +59 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/access_log_parser.py +307 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/admin_api_client.py +678 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/ip_geo_locator.py +176 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/admin_user_tbl.py +33 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_access_log_tbl.py +90 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_certificate_tbl.py +65 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_rate_limit_tbl.py +69 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_route_tbl.py +66 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_stats_tbl.py +78 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_action_log_tbl.py +44 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_config_tbl.py +30 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_info_tbl.py +51 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_instance_tbl.py +68 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/admin_user_operate.py +59 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_access_log.py +531 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_certificate.py +451 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_rate_limit.py +360 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_route.py +271 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_stats.py +343 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_action_log_op.py +57 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_config.py +86 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_info_op.py +79 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_instance.py +58 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_registry.py +138 -0
- cancan_microstack/services/opsbffsrv/infrastructure/ddl_manager.py +31 -0
- cancan_microstack/services/opsbffsrv/infrastructure/mongo/__init__.py +1 -0
- cancan_microstack/services/opsbffsrv/infrastructure/mongo/log_query_repository.py +87 -0
- cancan_microstack/services/opsbffsrv/interface/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/interface/api/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/interface/api/async_operation_api.py +137 -0
- cancan_microstack/services/opsbffsrv/interface/api/auth_api.py +113 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/__init__.py +3 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/access_log_api.py +174 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/certificate_api.py +235 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/rate_limit_api.py +302 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/route_api.py +250 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/stats_api.py +243 -0
- cancan_microstack/services/opsbffsrv/interface/api/db_admin_api.py +62 -0
- cancan_microstack/services/opsbffsrv/interface/api/db_init_api.py +109 -0
- cancan_microstack/services/opsbffsrv/interface/api/instance_management_api.py +165 -0
- cancan_microstack/services/opsbffsrv/interface/api/log_query_api.py +41 -0
- cancan_microstack/services/opsbffsrv/interface/api/mongo_express_proxy_api.py +181 -0
- cancan_microstack/services/opsbffsrv/interface/api/pgweb_proxy_api.py +154 -0
- cancan_microstack/services/opsbffsrv/interface/api/rabbitmq_mgmt_proxy_api.py +518 -0
- cancan_microstack/services/opsbffsrv/interface/api/redis_commander_proxy_api.py +133 -0
- cancan_microstack/services/opsbffsrv/interface/api/service_config.py +146 -0
- cancan_microstack/services/opsbffsrv/interface/api/service_logs_api.py +81 -0
- cancan_microstack/services/opsbffsrv/interface/api/service_registry.py +66 -0
- cancan_microstack/services/opsbffsrv/interface/api/workflow_ops_api.py +413 -0
- cancan_microstack/services/opsbffsrv/interface/middleware/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/interface/middleware/auth_middleware.py +52 -0
- cancan_microstack/services/opsbffsrv/router.py +901 -0
- cancan_microstack/utils/__init__.py +1 -0
- cancan_microstack/utils/container_env.py +218 -0
- cancan_microstack-0.0.1.dist-info/METADATA +155 -0
- cancan_microstack-0.0.1.dist-info/RECORD +440 -0
- cancan_microstack-0.0.1.dist-info/WHEEL +5 -0
- cancan_microstack-0.0.1.dist-info/entry_points.txt +2 -0
- cancan_microstack-0.0.1.dist-info/licenses/LICENSE +21 -0
- cancan_microstack-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
"""Workflow task dispatch helpers for Celery.
|
|
2
|
+
|
|
3
|
+
提供封装后的 Celery 调度工具,避免业务层到处硬编码 task 名称。
|
|
4
|
+
This module centralizes Celery helper functions so higher layers can enqueue work
|
|
5
|
+
without importing Celery primitives directly.
|
|
6
|
+
"""
|
|
7
|
+
import asyncio
|
|
8
|
+
import threading
|
|
9
|
+
import time
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from typing import (
|
|
12
|
+
Awaitable,
|
|
13
|
+
Callable,
|
|
14
|
+
Dict,
|
|
15
|
+
Optional,
|
|
16
|
+
Tuple,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from linglong_web.utils import logger
|
|
20
|
+
|
|
21
|
+
from cancan_microstack.public.const.workflow_consts import WorkflowTask
|
|
22
|
+
from linglong_web import LinglongConfig
|
|
23
|
+
from linglong_web import Rmanager
|
|
24
|
+
|
|
25
|
+
_WORKER_STATUS = {
|
|
26
|
+
"checked_at": 0.0,
|
|
27
|
+
"has_worker": False,
|
|
28
|
+
}
|
|
29
|
+
_WORKER_STATUS_LOCK = threading.Lock()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _missing_inline_orchestrator(run_id: str, node_id: str, loop_index: int) -> Awaitable[None]:
|
|
33
|
+
"""当未注册 orchestrator 时,给出明确错误。
|
|
34
|
+
Raise a clear error when inline orchestrator hasn't been registered.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
async def _raise() -> None:
|
|
38
|
+
raise RuntimeError(
|
|
39
|
+
"Workflow inline orchestrator is not registered. "
|
|
40
|
+
"Ensure workflow_app registers it via register_inline_orchestrator()."
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
return _raise()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
_INLINE_ORCHESTRATOR: Callable[[str, str, int], Awaitable[None]] = _missing_inline_orchestrator
|
|
47
|
+
_INLINE_ORCHESTRATOR_LOCK = threading.Lock()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def register_inline_orchestrator(func: Callable[[str, str, int], Awaitable[None]]) -> None:
|
|
51
|
+
"""注册工作流节点内联执行 orchestrator。
|
|
52
|
+
Register workflow node inline orchestrator.
|
|
53
|
+
|
|
54
|
+
Note:
|
|
55
|
+
This avoids a circular import between workflow_app and workflow_queue.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
if not callable(func):
|
|
59
|
+
raise TypeError("Inline orchestrator must be callable")
|
|
60
|
+
|
|
61
|
+
global _INLINE_ORCHESTRATOR
|
|
62
|
+
with _INLINE_ORCHESTRATOR_LOCK:
|
|
63
|
+
_INLINE_ORCHESTRATOR = func
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _get_inline_orchestrator() -> Callable[[str, str, int], Awaitable[None]]:
|
|
67
|
+
with _INLINE_ORCHESTRATOR_LOCK:
|
|
68
|
+
return _INLINE_ORCHESTRATOR
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _to_positive_int(value, default: int) -> int:
|
|
72
|
+
"""将配置值转换为正整数 / Ensure config-driven integers stay positive."""
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
candidate = int(value)
|
|
76
|
+
except (TypeError, ValueError):
|
|
77
|
+
return default
|
|
78
|
+
return candidate if candidate > 0 else default
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@dataclass(slots=True)
|
|
82
|
+
class _InlineJob:
|
|
83
|
+
"""表示一次内联执行任务 / Represents a single inline execution request."""
|
|
84
|
+
|
|
85
|
+
run_id: str
|
|
86
|
+
node_id: str
|
|
87
|
+
loop_index: int
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class _InlineFallbackExecutor:
|
|
91
|
+
"""受限并发的内联执行器,防止 Celery 降级时无限制堆积。
|
|
92
|
+
Bounded-concurrency inline executor that prevents unbounded fan-out when Celery is unavailable.
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
def __init__(self, *, max_concurrency: int, queue_limit: int) -> None:
|
|
96
|
+
self._max_concurrency = max_concurrency
|
|
97
|
+
self._queue_limit = queue_limit
|
|
98
|
+
self._queues: Dict[int, asyncio.Queue[_InlineJob]] = {}
|
|
99
|
+
|
|
100
|
+
async def _run_job(self, job: _InlineJob) -> None:
|
|
101
|
+
orchestrator = _get_inline_orchestrator()
|
|
102
|
+
await orchestrator(job.run_id, job.node_id, job.loop_index)
|
|
103
|
+
|
|
104
|
+
async def _worker(self, queue: asyncio.Queue[_InlineJob], worker_idx: int) -> None:
|
|
105
|
+
"""后台 worker,串行消费队列任务 / Background worker that drains inline queue with bounded concurrency."""
|
|
106
|
+
|
|
107
|
+
while True:
|
|
108
|
+
job = await queue.get()
|
|
109
|
+
try:
|
|
110
|
+
await self._run_job(job)
|
|
111
|
+
except Exception as exc: # noqa: BLE001 - inline fallback必须兜底 / inline fallback must never crash the orchestrator
|
|
112
|
+
logger.error(
|
|
113
|
+
"Inline workflow worker %s failed for run=%s node=%s: %s",
|
|
114
|
+
worker_idx,
|
|
115
|
+
job.run_id,
|
|
116
|
+
job.node_id,
|
|
117
|
+
exc,
|
|
118
|
+
exc_info=True,
|
|
119
|
+
)
|
|
120
|
+
finally:
|
|
121
|
+
queue.task_done()
|
|
122
|
+
|
|
123
|
+
async def _enqueue_with_backpressure(self, queue: asyncio.Queue[_InlineJob], job: _InlineJob) -> None:
|
|
124
|
+
"""等待队列空位,避免一次性放入过多任务 / Wait for free slot instead of flooding the loop."""
|
|
125
|
+
|
|
126
|
+
await queue.put(job)
|
|
127
|
+
|
|
128
|
+
def _ensure_queue(self, loop: asyncio.AbstractEventLoop) -> asyncio.Queue[_InlineJob]:
|
|
129
|
+
"""按事件循环初始化队列和 worker / Ensure queue + workers exist for the active loop."""
|
|
130
|
+
|
|
131
|
+
loop_id = id(loop)
|
|
132
|
+
queue = self._queues.get(loop_id)
|
|
133
|
+
if queue:
|
|
134
|
+
return queue
|
|
135
|
+
|
|
136
|
+
queue = asyncio.Queue(maxsize=self._queue_limit)
|
|
137
|
+
self._queues[loop_id] = queue
|
|
138
|
+
|
|
139
|
+
for idx in range(self._max_concurrency):
|
|
140
|
+
loop.create_task(
|
|
141
|
+
self._worker(queue, idx + 1),
|
|
142
|
+
name=f"workflow-inline-worker-{idx + 1}",
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
return queue
|
|
146
|
+
|
|
147
|
+
def submit(self, run_id: str, node_id: str, loop_index: int) -> None:
|
|
148
|
+
"""投递内联执行任务,自动施加并发限流。
|
|
149
|
+
Submit inline execution with bounded concurrency to keep fallback predictable.
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
job = _InlineJob(run_id=run_id, node_id=node_id, loop_index=loop_index)
|
|
153
|
+
try:
|
|
154
|
+
loop = asyncio.get_running_loop()
|
|
155
|
+
except RuntimeError:
|
|
156
|
+
logger.warning(
|
|
157
|
+
"No running event loop detected while executing workflow node inline; creating a temporary loop",
|
|
158
|
+
)
|
|
159
|
+
asyncio.run(self._run_job(job))
|
|
160
|
+
return
|
|
161
|
+
|
|
162
|
+
queue = self._ensure_queue(loop)
|
|
163
|
+
|
|
164
|
+
try:
|
|
165
|
+
queue.put_nowait(job)
|
|
166
|
+
except asyncio.QueueFull:
|
|
167
|
+
logger.warning(
|
|
168
|
+
"Inline workflow queue saturated (size=%s limit=%s); applying async backpressure",
|
|
169
|
+
queue.qsize(),
|
|
170
|
+
self._queue_limit,
|
|
171
|
+
)
|
|
172
|
+
loop.create_task(self._enqueue_with_backpressure(queue, job))
|
|
173
|
+
|
|
174
|
+
async def wait_for_idle(self, loop: asyncio.AbstractEventLoop | None = None) -> None:
|
|
175
|
+
"""等待队列清空(测试辅助) / Wait for inline queue to drain (useful for tests)."""
|
|
176
|
+
|
|
177
|
+
target_loop = loop or asyncio.get_running_loop()
|
|
178
|
+
queue = self._queues.get(id(target_loop))
|
|
179
|
+
if not queue:
|
|
180
|
+
return
|
|
181
|
+
await queue.join()
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
_INLINE_EXECUTOR: Optional[_InlineFallbackExecutor] = None
|
|
185
|
+
_INLINE_EXECUTOR_CONFIG: Optional[Tuple[int, int]] = None
|
|
186
|
+
_INLINE_EXECUTOR_OVERRIDE: Optional[_InlineFallbackExecutor] = None
|
|
187
|
+
_INLINE_EXECUTOR_LOCK = threading.Lock()
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _read_inline_executor_config() -> Tuple[int, int]:
|
|
191
|
+
"""读取并规范化内联执行器配置 / Read + normalize inline executor config."""
|
|
192
|
+
|
|
193
|
+
max_concurrency = _to_positive_int(LinglongConfig.WORKFLOW_INLINE_MAX_CONCURRENCY, 4)
|
|
194
|
+
queue_limit_hint = max(max_concurrency * 4, 1024)
|
|
195
|
+
queue_limit = _to_positive_int(LinglongConfig.WORKFLOW_INLINE_QUEUE_LIMIT, queue_limit_hint)
|
|
196
|
+
queue_limit = max(queue_limit, max_concurrency)
|
|
197
|
+
return max_concurrency, queue_limit
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def _get_inline_executor() -> _InlineFallbackExecutor:
|
|
201
|
+
"""根据当前 Config 获取内联执行器,支持热更新。
|
|
202
|
+
Resolve inline executor lazily so Config updates take effect without process restarts.
|
|
203
|
+
"""
|
|
204
|
+
|
|
205
|
+
override = _INLINE_EXECUTOR_OVERRIDE
|
|
206
|
+
if override is not None:
|
|
207
|
+
return override
|
|
208
|
+
|
|
209
|
+
global _INLINE_EXECUTOR, _INLINE_EXECUTOR_CONFIG
|
|
210
|
+
with _INLINE_EXECUTOR_LOCK:
|
|
211
|
+
desired = _read_inline_executor_config()
|
|
212
|
+
if _INLINE_EXECUTOR and _INLINE_EXECUTOR_CONFIG == desired:
|
|
213
|
+
return _INLINE_EXECUTOR
|
|
214
|
+
|
|
215
|
+
max_concurrency, queue_limit = desired
|
|
216
|
+
logger.info(
|
|
217
|
+
"Rebuilding inline executor due to config change: concurrency=%s queue_limit=%s",
|
|
218
|
+
max_concurrency,
|
|
219
|
+
queue_limit,
|
|
220
|
+
)
|
|
221
|
+
_INLINE_EXECUTOR = _InlineFallbackExecutor(
|
|
222
|
+
max_concurrency=max_concurrency,
|
|
223
|
+
queue_limit=queue_limit,
|
|
224
|
+
)
|
|
225
|
+
_INLINE_EXECUTOR_CONFIG = desired
|
|
226
|
+
return _INLINE_EXECUTOR
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
async def wait_for_inline_queue_idle() -> None:
|
|
230
|
+
"""等待内联队列清空(测试辅助) / Wait for inline queue to drain (test helper)."""
|
|
231
|
+
|
|
232
|
+
executor = _get_inline_executor()
|
|
233
|
+
await executor.wait_for_idle()
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def _celery_has_workers(celery_app, cache_ttl: float = 15.0) -> bool:
|
|
237
|
+
"""检测 Celery worker 是否在线,避免任务无限排队。
|
|
238
|
+
Check if at least one Celery worker is alive so we can decide whether to enqueue or run inline."""
|
|
239
|
+
|
|
240
|
+
now = time.monotonic()
|
|
241
|
+
with _WORKER_STATUS_LOCK:
|
|
242
|
+
checked_at = _WORKER_STATUS["checked_at"]
|
|
243
|
+
cached_result = _WORKER_STATUS["has_worker"]
|
|
244
|
+
|
|
245
|
+
if now - checked_at < cache_ttl:
|
|
246
|
+
return cached_result
|
|
247
|
+
|
|
248
|
+
try:
|
|
249
|
+
responses = celery_app.control.ping(timeout=1.0) or []
|
|
250
|
+
has_worker = len(responses) > 0
|
|
251
|
+
except Exception as exc: # noqa: BLE001
|
|
252
|
+
logger.warning("Failed to ping Celery workers: %s", exc)
|
|
253
|
+
has_worker = False
|
|
254
|
+
|
|
255
|
+
with _WORKER_STATUS_LOCK:
|
|
256
|
+
_WORKER_STATUS["checked_at"] = now
|
|
257
|
+
_WORKER_STATUS["has_worker"] = has_worker
|
|
258
|
+
return has_worker
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def _execute_inline_node(run_id: str, node_id: str, loop_index: int) -> None:
|
|
262
|
+
"""直接在当前进程执行节点,但通过队列控制瞬时并发。
|
|
263
|
+
Execute node orchestrator inline while honoring bounded inline concurrency.
|
|
264
|
+
"""
|
|
265
|
+
|
|
266
|
+
executor = _get_inline_executor()
|
|
267
|
+
executor.submit(run_id, node_id, loop_index)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def enqueue_node_execution(run_id: str, node_id: str, loop_index: int) -> None:
|
|
271
|
+
"""将节点执行请求投递到 Celery 队列 / Send a node execution request to Celery."""
|
|
272
|
+
|
|
273
|
+
celery_app = Rmanager.CeleryApp
|
|
274
|
+
if not celery_app:
|
|
275
|
+
logger.warning(
|
|
276
|
+
"Celery is not initialized, executing workflow node inline: run=%s node=%s",
|
|
277
|
+
run_id,
|
|
278
|
+
node_id,
|
|
279
|
+
)
|
|
280
|
+
_execute_inline_node(run_id, node_id, loop_index)
|
|
281
|
+
return
|
|
282
|
+
|
|
283
|
+
if not _celery_has_workers(celery_app):
|
|
284
|
+
logger.warning(
|
|
285
|
+
"Celery has no active workers, executing workflow node inline: run=%s node=%s",
|
|
286
|
+
run_id,
|
|
287
|
+
node_id,
|
|
288
|
+
)
|
|
289
|
+
_execute_inline_node(run_id, node_id, loop_index)
|
|
290
|
+
return
|
|
291
|
+
|
|
292
|
+
try:
|
|
293
|
+
celery_app.send_task(WorkflowTask.EXECUTE_NODE, args=(run_id, node_id, loop_index))
|
|
294
|
+
except Exception as exc: # noqa: BLE001 - we need to capture all Celery backend issues
|
|
295
|
+
logger.error(
|
|
296
|
+
"Failed to enqueue workflow node via Celery (run=%s node=%s). Falling back to inline execution. Error: %s",
|
|
297
|
+
run_id,
|
|
298
|
+
node_id,
|
|
299
|
+
exc,
|
|
300
|
+
exc_info=True,
|
|
301
|
+
)
|
|
302
|
+
_execute_inline_node(run_id, node_id, loop_index)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Workflow Celery task registration helpers.
|
|
2
|
+
|
|
3
|
+
按照项目规范集中注册 Celery 任务,便于在 cmd/infrasrv/run.py 中一眼看出
|
|
4
|
+
服务暴露了哪些任务;同时也避免循环导入。
|
|
5
|
+
This module centralizes Celery task declarations so run.py can register them
|
|
6
|
+
explicitly, making task discovery and testing easier.
|
|
7
|
+
"""
|
|
8
|
+
import asyncio
|
|
9
|
+
import threading
|
|
10
|
+
|
|
11
|
+
from celery import Celery
|
|
12
|
+
|
|
13
|
+
from linglong_web import Rmanager
|
|
14
|
+
from cancan_microstack.public.const.workflow_consts import WorkflowTask
|
|
15
|
+
from cancan_microstack.services.infrasrv.application.workflow.workflow_app import workflow_app
|
|
16
|
+
from cancan_microstack.services.infrasrv.interface.schedule.workflow_scheduler import scan_and_trigger_workflows
|
|
17
|
+
|
|
18
|
+
_TASKS_REGISTERED = False
|
|
19
|
+
_REGISTER_LOCK = threading.Lock()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def register_workflow_tasks() -> None:
|
|
23
|
+
"""注册工作流相关的 Celery 任务 / Register workflow Celery tasks only once."""
|
|
24
|
+
global _TASKS_REGISTERED
|
|
25
|
+
if _TASKS_REGISTERED:
|
|
26
|
+
return
|
|
27
|
+
|
|
28
|
+
# 双重检查锁,避免并发调用重复注册任务
|
|
29
|
+
# Double-checked locking to keep concurrent registrations idempotent
|
|
30
|
+
with _REGISTER_LOCK:
|
|
31
|
+
if _TASKS_REGISTERED:
|
|
32
|
+
return
|
|
33
|
+
|
|
34
|
+
celery_app: Celery = Rmanager.CeleryApp
|
|
35
|
+
|
|
36
|
+
@celery_app.task(name=WorkflowTask.EXECUTE_NODE, bind=True, max_retries=3, acks_late=True)
|
|
37
|
+
def execute_node_task(self, run_id: str, node_id: str, loop_index: int = 1):
|
|
38
|
+
"""调用执行协调器 / Run the async node orchestrator inside Celery."""
|
|
39
|
+
asyncio.run(workflow_app._execute_node_orchestrator(run_id, node_id, loop_index))
|
|
40
|
+
|
|
41
|
+
@celery_app.task(name=WorkflowTask.SCAN_SCHEDULED, bind=True, autoretry_for=(Exception,), retry_backoff=True)
|
|
42
|
+
def scan_scheduled_task(self):
|
|
43
|
+
"""周期扫描数据库查找待执行的工作流 / Periodically scan DB for due workflows."""
|
|
44
|
+
asyncio.run(scan_and_trigger_workflows())
|
|
45
|
+
|
|
46
|
+
_TASKS_REGISTERED = True
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""Embedded Celery worker runtime for infrasrv workflow tasks.
|
|
2
|
+
|
|
3
|
+
在单实例 infrasrv 内启动/停止 Celery worker,避免额外容器或进程。
|
|
4
|
+
The worker runs inside a dedicated daemon thread so the service can keep a
|
|
5
|
+
single deployment unit while still benefiting from Celery's queue semantics.
|
|
6
|
+
"""
|
|
7
|
+
import os
|
|
8
|
+
import threading
|
|
9
|
+
from typing import Optional
|
|
10
|
+
|
|
11
|
+
from celery import Celery
|
|
12
|
+
|
|
13
|
+
from linglong_web import LinglongConfig
|
|
14
|
+
from linglong_web import Rmanager
|
|
15
|
+
from linglong_web.utils import logger
|
|
16
|
+
|
|
17
|
+
_worker_thread: Optional[threading.Thread] = None
|
|
18
|
+
_worker_hostname: Optional[str] = None
|
|
19
|
+
_worker_shutdown_lock = threading.Lock()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _build_worker_hostname() -> str:
|
|
23
|
+
suffix = LinglongConfig.CELERY_WORKER_HOSTNAME_SUFFIX
|
|
24
|
+
base = (
|
|
25
|
+
os.environ.get("SERVICE_WORKER_HOSTNAME")
|
|
26
|
+
or os.environ.get("HOSTNAME")
|
|
27
|
+
or "infrasrv"
|
|
28
|
+
)
|
|
29
|
+
base = base.replace("/", "").split(".")[0]
|
|
30
|
+
suffix = suffix.lstrip(".@") or "inline"
|
|
31
|
+
return f"{base}@{suffix}"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _build_worker_argv(hostname: str) -> list[str]:
|
|
35
|
+
log_level = LinglongConfig.CELERY_WORKER_LOG_LEVEL
|
|
36
|
+
concurrency = LinglongConfig.CELERY_WORKER_CONCURRENCY
|
|
37
|
+
pool = LinglongConfig.CELERY_WORKER_POOL
|
|
38
|
+
enable_beat = LinglongConfig.CELERY_WORKER_ENABLE_BEAT
|
|
39
|
+
|
|
40
|
+
argv = [
|
|
41
|
+
"worker",
|
|
42
|
+
f"--hostname={hostname}",
|
|
43
|
+
f"--loglevel={log_level}",
|
|
44
|
+
"--concurrency",
|
|
45
|
+
str(concurrency),
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
if pool:
|
|
49
|
+
argv.extend(["--pool", str(pool)])
|
|
50
|
+
|
|
51
|
+
if enable_beat:
|
|
52
|
+
argv.append("--beat")
|
|
53
|
+
|
|
54
|
+
return argv
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def start_inline_worker() -> None:
|
|
58
|
+
"""启动内嵌 Celery worker / Start embedded Celery worker."""
|
|
59
|
+
|
|
60
|
+
if not LinglongConfig.CELERY_WORKER_AUTOSTART:
|
|
61
|
+
logger.info("Embedded Celery worker autostart disabled via config")
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
app: Celery | None = Rmanager.CeleryApp
|
|
65
|
+
if not app:
|
|
66
|
+
logger.warning("Celery is not initialized; embedded worker skipped")
|
|
67
|
+
return
|
|
68
|
+
|
|
69
|
+
global _worker_thread, _worker_hostname
|
|
70
|
+
with _worker_shutdown_lock:
|
|
71
|
+
if _worker_thread and _worker_thread.is_alive():
|
|
72
|
+
logger.info("Embedded Celery worker already running: hostname=%s", _worker_hostname)
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
hostname = _build_worker_hostname()
|
|
76
|
+
argv = _build_worker_argv(hostname)
|
|
77
|
+
|
|
78
|
+
def _run_worker():
|
|
79
|
+
logger.info(
|
|
80
|
+
"Starting embedded Celery worker hostname=%s argv=%s",
|
|
81
|
+
hostname,
|
|
82
|
+
" ".join(argv),
|
|
83
|
+
)
|
|
84
|
+
try:
|
|
85
|
+
app.worker_main(argv=argv)
|
|
86
|
+
except SystemExit as exc:
|
|
87
|
+
logger.info("Embedded Celery worker exited: %s", exc)
|
|
88
|
+
except Exception as exc: # noqa: BLE001
|
|
89
|
+
logger.error("Embedded Celery worker crashed: %s", exc, exc_info=True)
|
|
90
|
+
finally:
|
|
91
|
+
logger.info("Embedded Celery worker stopped")
|
|
92
|
+
|
|
93
|
+
worker_thread = threading.Thread(target=_run_worker, name="embedded-celery-worker", daemon=True)
|
|
94
|
+
worker_thread.start()
|
|
95
|
+
_worker_thread = worker_thread
|
|
96
|
+
_worker_hostname = hostname
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def stop_inline_worker(timeout: float = 30.0) -> None:
|
|
100
|
+
"""停止内嵌 Celery worker / Stop embedded Celery worker."""
|
|
101
|
+
|
|
102
|
+
global _worker_thread
|
|
103
|
+
with _worker_shutdown_lock:
|
|
104
|
+
thread = _worker_thread
|
|
105
|
+
if not thread or not thread.is_alive():
|
|
106
|
+
_worker_thread = None
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
app: Celery | None = Rmanager.CeleryApp
|
|
110
|
+
if app and _worker_hostname:
|
|
111
|
+
try:
|
|
112
|
+
logger.info("Sending shutdown signal to embedded Celery worker: %s", _worker_hostname)
|
|
113
|
+
app.control.shutdown(destination=[_worker_hostname])
|
|
114
|
+
except Exception as exc: # noqa: BLE001
|
|
115
|
+
logger.warning("Failed to send shutdown command to worker: %s", exc)
|
|
116
|
+
|
|
117
|
+
thread.join(timeout=timeout)
|
|
118
|
+
if thread.is_alive():
|
|
119
|
+
logger.warning("Embedded Celery worker did not stop within %.1fs", timeout)
|
|
120
|
+
else:
|
|
121
|
+
logger.info("Embedded Celery worker terminated cleanly")
|
|
122
|
+
_worker_thread = None
|
|
File without changes
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from linglong_web import LinglongConfigBase
|
|
5
|
+
from cancan_microstack.public.const.workflow_consts import WorkflowTask
|
|
6
|
+
|
|
7
|
+
from cancan_microstack.runtime.resources import resolve_workspace_or_asset
|
|
8
|
+
from cancan_microstack.runtime.workspace import configure_workspace, ensure_server_log_dir
|
|
9
|
+
|
|
10
|
+
_WORKSPACE_ROOT = str(configure_workspace())
|
|
11
|
+
ensure_server_log_dir()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class _BaseConfig(LinglongConfigBase):
|
|
15
|
+
"""基础配置"""
|
|
16
|
+
DEBUG = False
|
|
17
|
+
|
|
18
|
+
# 项目根目录(动态获取)
|
|
19
|
+
_PROJECT_ROOT = _WORKSPACE_ROOT
|
|
20
|
+
|
|
21
|
+
INFRASRV_HOST = "http://infrasrv.service:8080"
|
|
22
|
+
CONTROLLERSRV_HOST = os.getenv("CONTROLLERSRV_HOST", "http://host.containers.internal:22100")
|
|
23
|
+
|
|
24
|
+
SKIP_SERVICE_REGISTRY = True
|
|
25
|
+
|
|
26
|
+
# DDL 自管理配置
|
|
27
|
+
ENABLE_DDL_AUTO_INIT = True # 启动时自动创建 infra 表
|
|
28
|
+
# DDL 脚本路径使用项目根目录
|
|
29
|
+
# - In Pod: /app/ddl/infra (Dockerfile COPY)
|
|
30
|
+
# - Out Pod: {project_root}/ddl/infra
|
|
31
|
+
DDL_SCRIPT_PATH = str(resolve_workspace_or_asset("ddl/infra", "ddl/infra"))
|
|
32
|
+
|
|
33
|
+
# 数据库配置
|
|
34
|
+
PGSQL_DB = "infra" # infrasrv 使用 infra 数据库
|
|
35
|
+
|
|
36
|
+
# PostgreSQL 连接池配置(兼顾并发与连接上限)
|
|
37
|
+
# PostgreSQL pool settings (balance concurrency and connection cap)
|
|
38
|
+
# 说明:infrasrv 需要同时处理操作轮询、健康检查、日志写入和服务管理写操作。
|
|
39
|
+
# Note: infrasrv handles operation polling, health checks, log ingestion, and management writes concurrently.
|
|
40
|
+
PGSQL_POOL_SIZE = 5
|
|
41
|
+
PGSQL_MAX_OVERFLOW = 5
|
|
42
|
+
|
|
43
|
+
# 服务注册清理配置 / Service registry cleanup settings
|
|
44
|
+
INSTANCE_HEARTBEAT_TIMEOUT_SECONDS = 90 # 僵尸实例的超时阈值(秒) / Stale instance threshold (seconds)
|
|
45
|
+
|
|
46
|
+
# 业务日志消费配置 / Business log ingestion settings
|
|
47
|
+
LOG_PIPELINE_CONSUMER_ENABLED = True
|
|
48
|
+
RABBITMQ_LOG_CONNECTION_NAME = "infrasrv-log-consumer"
|
|
49
|
+
|
|
50
|
+
# RabbitMQ 连接配置(日志消费 + 工作流 broker)
|
|
51
|
+
# RabbitMQ connection settings (log consumer + workflow broker)
|
|
52
|
+
RABBITMQ_HOST = os.getenv("RABBITMQ_HOST", "rabbitmq.internal")
|
|
53
|
+
RABBITMQ_PORT = int(os.getenv("RABBITMQ_PORT", "5672"))
|
|
54
|
+
RABBITMQ_VHOST = os.getenv("RABBITMQ_VHOST", "/")
|
|
55
|
+
RABBITMQ_USERNAME = os.getenv("RABBITMQ_USERNAME", "admin")
|
|
56
|
+
RABBITMQ_PASSWORD = os.getenv("RABBITMQ_PASSWORD", "admin123")
|
|
57
|
+
|
|
58
|
+
# MongoDB 配置(日志存储) / MongoDB settings for log storage
|
|
59
|
+
# 注意:默认使用 root 用户认证数据库 admin
|
|
60
|
+
# Note: default uses root user with authSource=admin
|
|
61
|
+
MONGODB_URI = os.getenv(
|
|
62
|
+
"MONGODB_URI",
|
|
63
|
+
"mongodb://admin:admin123@mongo.internal:27017/admin?authSource=admin",
|
|
64
|
+
)
|
|
65
|
+
MONGODB_DB = "infra_logging"
|
|
66
|
+
MONGODB_COLLECTION = "service_logs"
|
|
67
|
+
|
|
68
|
+
# Celery 调度配置(基于 RabbitMQ + Redis)
|
|
69
|
+
# Celery scheduling settings (broker via RabbitMQ, backend via Redis)
|
|
70
|
+
ENABLE_WORKFLOW_CELERY = True
|
|
71
|
+
CELERY_APP_NAME = "infrasrv_workflow"
|
|
72
|
+
CELERY_RESULT_BACKEND_DB = 5
|
|
73
|
+
CELERY_TIMEZONE = "Asia/Shanghai"
|
|
74
|
+
CELERY_ENABLE_UTC = True
|
|
75
|
+
CELERY_BEAT_SCHEDULE = {
|
|
76
|
+
"scan-workflow-triggers": {
|
|
77
|
+
"task": WorkflowTask.SCAN_SCHEDULED,
|
|
78
|
+
"schedule": 5.0,
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# 日志配置 - 使用项目根目录
|
|
83
|
+
# - In Pod: /app/server_log_data/{}.log (volume 挂载到宿主机)
|
|
84
|
+
# - Out Pod: {project_root}/server_log_data/{}.log
|
|
85
|
+
LOGGING_ENABLE_FILE_HANDLER = True
|
|
86
|
+
LOGGING_FILE_ADDR_FORMAT = os.path.join(_PROJECT_ROOT, "server_log_data", "{}.log")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class _ProductionConfig(_BaseConfig):
|
|
90
|
+
"""生产环境配置"""
|
|
91
|
+
ENV_MODE = "prod"
|
|
92
|
+
DEBUG = False
|
|
93
|
+
LOGGING_LEVEL = logging.INFO
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
service_conf_dict = {
|
|
97
|
+
'prod': _ProductionConfig,
|
|
98
|
+
}
|
|
File without changes
|