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.
Files changed (440) hide show
  1. cancan_microstack/__init__.py +14 -0
  2. cancan_microstack/__version__.py +10 -0
  3. cancan_microstack/assets/__init__.py +6 -0
  4. cancan_microstack/assets/builds/caddy/Caddyfile +187 -0
  5. cancan_microstack/assets/builds/caddy/DEPLOYMENT.md +303 -0
  6. cancan_microstack/assets/builds/caddy/Dockerfile +46 -0
  7. cancan_microstack/assets/builds/caddy/README.md +343 -0
  8. cancan_microstack/assets/builds/caddy/geoip/README.md +5 -0
  9. cancan_microstack/assets/builds/caddy/start.sh +78 -0
  10. cancan_microstack/assets/builds/caddy/waf/coraza.conf +179 -0
  11. cancan_microstack/assets/builds/service/Dockerfile +59 -0
  12. cancan_microstack/assets/builds/service/README.md +13 -0
  13. cancan_microstack/assets/ddl/create_db.sql +22 -0
  14. cancan_microstack/assets/ddl/infra/execution_log_tbl.sql +46 -0
  15. cancan_microstack/assets/ddl/infra/node_instance_tbl.sql +56 -0
  16. cancan_microstack/assets/ddl/infra/service_action_log_tbl.sql +36 -0
  17. cancan_microstack/assets/ddl/infra/service_config_tbl.sql +26 -0
  18. cancan_microstack/assets/ddl/infra/service_info_tbl.sql +45 -0
  19. cancan_microstack/assets/ddl/infra/service_instance_tbl.sql +54 -0
  20. cancan_microstack/assets/ddl/infra/service_operation_tbl.sql +47 -0
  21. cancan_microstack/assets/ddl/infra/workflow_definition_tbl.sql +60 -0
  22. cancan_microstack/assets/ddl/infra/workflow_definition_version_tbl.sql +35 -0
  23. cancan_microstack/assets/ddl/infra/workflow_engine_alert_tbl.sql +34 -0
  24. cancan_microstack/assets/ddl/infra/workflow_run_tbl.sql +52 -0
  25. cancan_microstack/assets/ddl/ops/admin_user_tbl.sql +34 -0
  26. cancan_microstack/assets/ddl/ops/caddy_access_log_tbl.sql +91 -0
  27. cancan_microstack/assets/ddl/ops/caddy_certificate_tbl.sql +59 -0
  28. cancan_microstack/assets/ddl/ops/caddy_rate_limit_tbl.sql +64 -0
  29. cancan_microstack/assets/ddl/ops/caddy_route_tbl.sql +63 -0
  30. cancan_microstack/assets/ddl/ops/caddy_stats_tbl.sql +77 -0
  31. cancan_microstack/assets/ddl/trigger.sql +21 -0
  32. cancan_microstack/assets/docker/docker-compose.infra.yml +401 -0
  33. cancan_microstack/assets/scripts/README.md +195 -0
  34. cancan_microstack/assets/scripts/docker/build_images.sh +44 -0
  35. cancan_microstack/assets/scripts/docker/force_rebuild_images.sh +38 -0
  36. cancan_microstack/assets/scripts/docker/rebuild_all.sh +34 -0
  37. cancan_microstack/assets/scripts/docker/rebuild_compose.sh +61 -0
  38. cancan_microstack/assets/scripts/docker/restart.sh +35 -0
  39. cancan_microstack/assets/scripts/docker/restart_compose.sh +35 -0
  40. cancan_microstack/assets/scripts/docker/start.sh +78 -0
  41. cancan_microstack/assets/scripts/docker/start_all.sh +46 -0
  42. cancan_microstack/assets/scripts/docker/start_compose.sh +66 -0
  43. cancan_microstack/assets/scripts/docker/stop.sh +67 -0
  44. cancan_microstack/assets/scripts/docker/stop_all.sh +38 -0
  45. cancan_microstack/assets/scripts/docker/stop_compose.sh +38 -0
  46. cancan_microstack/assets/scripts/podman/build_images_podman.sh +59 -0
  47. cancan_microstack/assets/scripts/podman/cleanup_podman.sh +25 -0
  48. cancan_microstack/assets/scripts/podman/force_rebuild_images_podman.sh +56 -0
  49. cancan_microstack/assets/scripts/podman/rebuild_all_podman.sh +37 -0
  50. cancan_microstack/assets/scripts/podman/rebuild_compose_podman.sh +60 -0
  51. cancan_microstack/assets/scripts/podman/restart_compose_podman.sh +73 -0
  52. cancan_microstack/assets/scripts/podman/start_all_podman.sh +66 -0
  53. cancan_microstack/assets/scripts/podman/start_compose_podman.sh +80 -0
  54. cancan_microstack/assets/scripts/podman/start_podman.sh +91 -0
  55. cancan_microstack/assets/scripts/podman/stop.sh +73 -0
  56. cancan_microstack/assets/scripts/podman/stop_all_podman.sh +34 -0
  57. cancan_microstack/assets/scripts/podman/stop_compose_podman.sh +58 -0
  58. cancan_microstack/assets/scripts/start_controllersrv.sh +9 -0
  59. cancan_microstack/assets/scripts/utils/check_all_db_tables.sh +104 -0
  60. cancan_microstack/assets/scripts/utils/check_env.sh +177 -0
  61. cancan_microstack/assets/scripts/utils/check_service_management_deployment.sh +225 -0
  62. cancan_microstack/assets/scripts/utils/deploy_service_management.sh +176 -0
  63. cancan_microstack/assets/scripts/utils/force_reload_infrasrv.sh +52 -0
  64. cancan_microstack/assets/scripts/utils/monitor_service_management.sh +187 -0
  65. cancan_microstack/assets/scripts/utils/reset_postgres_volume.sh +68 -0
  66. cancan_microstack/assets/scripts/utils/test_async_operations.sh +141 -0
  67. cancan_microstack/assets/scripts/utils/verify_real_operations.sh +76 -0
  68. cancan_microstack/assets/service/Dockerfile +65 -0
  69. cancan_microstack/assets/www/adminops/assets/AppEmpty.vue_vue_type_script_setup_true_lang-BOKUurnM.js +1 -0
  70. cancan_microstack/assets/www/adminops/assets/ConfigManage-DKV5YOUz.js +1 -0
  71. cancan_microstack/assets/www/adminops/assets/ConfigManage-Y5bhy7wG.css +1 -0
  72. cancan_microstack/assets/www/adminops/assets/ConsoleManage-8ljYvCW2.js +1 -0
  73. cancan_microstack/assets/www/adminops/assets/ConsoleManage-BWpyqbuQ.css +1 -0
  74. cancan_microstack/assets/www/adminops/assets/DashboardNew-B9Nf1OPl.js +1 -0
  75. cancan_microstack/assets/www/adminops/assets/DashboardNew-DYWZKQ1V.css +1 -0
  76. cancan_microstack/assets/www/adminops/assets/LogSearch-CA0Jhe78.js +1 -0
  77. cancan_microstack/assets/www/adminops/assets/LogSearch-CCZfTNPF.css +1 -0
  78. cancan_microstack/assets/www/adminops/assets/LoginView-BId3kP3M.css +1 -0
  79. cancan_microstack/assets/www/adminops/assets/LoginView-BQZTV_Qy.js +1 -0
  80. cancan_microstack/assets/www/adminops/assets/OperationProgressDialog-BdEYwqFq.js +1 -0
  81. cancan_microstack/assets/www/adminops/assets/OperationProgressDialog-D-pASR8G.css +1 -0
  82. cancan_microstack/assets/www/adminops/assets/PageContainer-Byss-yUC.js +1 -0
  83. cancan_microstack/assets/www/adminops/assets/PageContainer-C3nSZwM7.css +1 -0
  84. cancan_microstack/assets/www/adminops/assets/RateLimitManage-BDI8jLpC.css +1 -0
  85. cancan_microstack/assets/www/adminops/assets/RateLimitManage-DJY4NiF-.js +1 -0
  86. cancan_microstack/assets/www/adminops/assets/RouteManage-DaUQ4QLw.css +1 -0
  87. cancan_microstack/assets/www/adminops/assets/RouteManage-w9XCU0UA.js +1 -0
  88. cancan_microstack/assets/www/adminops/assets/ServiceCard-BFzHe6Tw.css +1 -0
  89. cancan_microstack/assets/www/adminops/assets/ServiceCard-BJUhWnA-.js +1 -0
  90. cancan_microstack/assets/www/adminops/assets/ServiceDetail-Cw24WuKp.js +1 -0
  91. cancan_microstack/assets/www/adminops/assets/ServiceDetail-Yum47zdB.css +1 -0
  92. cancan_microstack/assets/www/adminops/assets/ServiceList-C7ryvbhE.js +1 -0
  93. cancan_microstack/assets/www/adminops/assets/ServiceList-Cgd01fUx.css +1 -0
  94. cancan_microstack/assets/www/adminops/assets/ServiceLogs-COpG9H0h.js +1 -0
  95. cancan_microstack/assets/www/adminops/assets/ServiceLogs-H_Alq0cf.css +1 -0
  96. cancan_microstack/assets/www/adminops/assets/StatsOverview-D0TwMQkA.js +39 -0
  97. cancan_microstack/assets/www/adminops/assets/StatsOverview-lqAN6pqM.css +1 -0
  98. cancan_microstack/assets/www/adminops/assets/TotpBindView-CWlAmzFt.js +1 -0
  99. cancan_microstack/assets/www/adminops/assets/TotpBindView-HoQC1lhx.css +1 -0
  100. cancan_microstack/assets/www/adminops/assets/TotpVerifyView-BHN1VtX1.css +1 -0
  101. cancan_microstack/assets/www/adminops/assets/TotpVerifyView-D3w_lZk8.js +1 -0
  102. cancan_microstack/assets/www/adminops/assets/WorkflowCenter-DU_mpIA0.css +1 -0
  103. cancan_microstack/assets/www/adminops/assets/WorkflowCenter-i50rZyxN.js +1 -0
  104. cancan_microstack/assets/www/adminops/assets/WorkflowDesigner-CnHokPL9.js +1 -0
  105. cancan_microstack/assets/www/adminops/assets/WorkflowDesigner-DaZaZpLd.css +1 -0
  106. cancan_microstack/assets/www/adminops/assets/WorkflowRuns-B09hK48c.js +1 -0
  107. cancan_microstack/assets/www/adminops/assets/WorkflowRuns-wGutKIIU.css +1 -0
  108. cancan_microstack/assets/www/adminops/assets/caddy-nnCKf8fG.js +1 -0
  109. cancan_microstack/assets/www/adminops/assets/format-Cuzxgna9.js +1 -0
  110. cancan_microstack/assets/www/adminops/assets/index-CiFlm8oc.js +64 -0
  111. cancan_microstack/assets/www/adminops/assets/index-UW0T1Dkc.css +1 -0
  112. cancan_microstack/assets/www/adminops/assets/service-BYlgGPs_.js +1 -0
  113. cancan_microstack/assets/www/adminops/assets/service-operation-6GzLw2Z1.js +1 -0
  114. cancan_microstack/assets/www/adminops/assets/style-CcIXnQ5y.css +1 -0
  115. cancan_microstack/assets/www/adminops/assets/style-lRnStdGu.js +39 -0
  116. cancan_microstack/assets/www/adminops/assets/useDebounce-BRlqfXqf.js +1 -0
  117. cancan_microstack/assets/www/adminops/assets/workflow-CUXs39Ac.js +1 -0
  118. cancan_microstack/assets/www/adminops/index.html +16 -0
  119. cancan_microstack/assets/www/adminops/vite.svg +1 -0
  120. cancan_microstack/cli/__init__.py +14 -0
  121. cancan_microstack/cli/__main__.py +9 -0
  122. cancan_microstack/cli/main.py +552 -0
  123. cancan_microstack/cmd/__init__.py +54 -0
  124. cancan_microstack/cmd/cancan/__init__.py +12 -0
  125. cancan_microstack/cmd/cancan/run.py +395 -0
  126. cancan_microstack/cmd/controllersrv/__init__.py +0 -0
  127. cancan_microstack/cmd/controllersrv/run.py +131 -0
  128. cancan_microstack/cmd/infrasrv/__init__.py +5 -0
  129. cancan_microstack/cmd/infrasrv/run.py +100 -0
  130. cancan_microstack/cmd/opsbffsrv/__init__.py +5 -0
  131. cancan_microstack/cmd/opsbffsrv/run.py +96 -0
  132. cancan_microstack/core/__init__.py +5 -0
  133. cancan_microstack/core/assets.py +123 -0
  134. cancan_microstack/core/compose_builder.py +102 -0
  135. cancan_microstack/core/doctor.py +152 -0
  136. cancan_microstack/core/microstack.py +71 -0
  137. cancan_microstack/core/runner.py +56 -0
  138. cancan_microstack/core/stack_manager.py +186 -0
  139. cancan_microstack/public/__init__.py +7 -0
  140. cancan_microstack/public/api/__init__.py +1 -0
  141. cancan_microstack/public/api/controllersrv_client.py +277 -0
  142. cancan_microstack/public/api/infrasrv_client.py +404 -0
  143. cancan_microstack/public/const/__init__.py +1 -0
  144. cancan_microstack/public/const/action_consts.py +18 -0
  145. cancan_microstack/public/const/app_consts.py +42 -0
  146. cancan_microstack/public/const/caddy_consts.py +22 -0
  147. cancan_microstack/public/const/controllersrv_consts.py +163 -0
  148. cancan_microstack/public/const/docker_consts.py +15 -0
  149. cancan_microstack/public/const/error.py +56 -0
  150. cancan_microstack/public/const/health_consts.py +52 -0
  151. cancan_microstack/public/const/hook_enums.py +56 -0
  152. cancan_microstack/public/const/logging_enums.py +13 -0
  153. cancan_microstack/public/const/metrics_enums.py +36 -0
  154. cancan_microstack/public/const/monitor_enums.py +26 -0
  155. cancan_microstack/public/const/operation_consts.py +53 -0
  156. cancan_microstack/public/const/opsbffsrv_error.py +92 -0
  157. cancan_microstack/public/const/overrides_consts.py +13 -0
  158. cancan_microstack/public/const/redis.py +17 -0
  159. cancan_microstack/public/const/service_consts.py +15 -0
  160. cancan_microstack/public/const/workflow_consts.py +65 -0
  161. cancan_microstack/public/error.py +41 -0
  162. cancan_microstack/public/logging/__init__.py +0 -0
  163. cancan_microstack/public/logging/initializer.py +109 -0
  164. cancan_microstack/public/logging/mq_handler.py +279 -0
  165. cancan_microstack/public/schemas/__init__.py +1 -0
  166. cancan_microstack/public/schemas/caddy/__init__.py +381 -0
  167. cancan_microstack/public/schemas/caddy/analysis.py +90 -0
  168. cancan_microstack/public/schemas/caddy/route.py +18 -0
  169. cancan_microstack/public/schemas/common.py +79 -0
  170. cancan_microstack/public/schemas/controllersrv/__init__.py +3 -0
  171. cancan_microstack/public/schemas/controllersrv/async_requests.py +30 -0
  172. cancan_microstack/public/schemas/controllersrv/compose_models.py +47 -0
  173. cancan_microstack/public/schemas/controllersrv/const.py +24 -0
  174. cancan_microstack/public/schemas/controllersrv/docker_models.py +45 -0
  175. cancan_microstack/public/schemas/controllersrv/docker_responses.py +104 -0
  176. cancan_microstack/public/schemas/controllersrv/requests.py +54 -0
  177. cancan_microstack/public/schemas/controllersrv/responses.py +124 -0
  178. cancan_microstack/public/schemas/controllersrv/task_models.py +102 -0
  179. cancan_microstack/public/schemas/controllersrv/validation.py +23 -0
  180. cancan_microstack/public/schemas/hook_metrics.py +124 -0
  181. cancan_microstack/public/schemas/hooks.py +39 -0
  182. cancan_microstack/public/schemas/infra/__init__.py +0 -0
  183. cancan_microstack/public/schemas/infra/cleanup.py +25 -0
  184. cancan_microstack/public/schemas/infra/container.py +74 -0
  185. cancan_microstack/public/schemas/infra/enums.py +135 -0
  186. cancan_microstack/public/schemas/infra/health_check.py +42 -0
  187. cancan_microstack/public/schemas/infra/hook_log.py +42 -0
  188. cancan_microstack/public/schemas/infra/operation.py +90 -0
  189. cancan_microstack/public/schemas/infra/overview.py +25 -0
  190. cancan_microstack/public/schemas/infra/push.py +33 -0
  191. cancan_microstack/public/schemas/infra/service_action_log.py +47 -0
  192. cancan_microstack/public/schemas/infra/service_config.py +10 -0
  193. cancan_microstack/public/schemas/infra/service_info.py +69 -0
  194. cancan_microstack/public/schemas/infra/service_instance.py +93 -0
  195. cancan_microstack/public/schemas/infra/service_management.py +152 -0
  196. cancan_microstack/public/schemas/infra/service_operation.py +79 -0
  197. cancan_microstack/public/schemas/infra/service_registry.py +158 -0
  198. cancan_microstack/public/schemas/infra/status_types.py +19 -0
  199. cancan_microstack/public/schemas/infra/workflow.py +566 -0
  200. cancan_microstack/public/schemas/logging/__init__.py +1 -0
  201. cancan_microstack/public/schemas/logging/log_event.py +121 -0
  202. cancan_microstack/public/schemas/opsbffsrv/__init__.py +1 -0
  203. cancan_microstack/public/schemas/opsbffsrv/async_ops.py +17 -0
  204. cancan_microstack/public/schemas/opsbffsrv/db_admin.py +147 -0
  205. cancan_microstack/public/schemas/opsbffsrv/db_init.py +48 -0
  206. cancan_microstack/public/schemas/opsbffsrv/service_config.py +89 -0
  207. cancan_microstack/public/schemas/opsbffsrv/service_logs.py +54 -0
  208. cancan_microstack/public/schemas/service_operation.py +24 -0
  209. cancan_microstack/public/schemas/service_registry.py +40 -0
  210. cancan_microstack/public/types/__init__.py +7 -0
  211. cancan_microstack/public/web/__init__.py +0 -0
  212. cancan_microstack/public/web/config_value.py +105 -0
  213. cancan_microstack/public/web/server.py +385 -0
  214. cancan_microstack/py.typed +0 -0
  215. cancan_microstack/runtime/__init__.py +0 -0
  216. cancan_microstack/runtime/compose_cmd.py +228 -0
  217. cancan_microstack/runtime/host_daemon.py +318 -0
  218. cancan_microstack/runtime/overrides.py +103 -0
  219. cancan_microstack/runtime/resources.py +25 -0
  220. cancan_microstack/runtime/workspace.py +94 -0
  221. cancan_microstack/services/__init__.py +0 -0
  222. cancan_microstack/services/controllersrv/__init__.py +8 -0
  223. cancan_microstack/services/controllersrv/application/__init__.py +0 -0
  224. cancan_microstack/services/controllersrv/application/docker_compose_app.py +427 -0
  225. cancan_microstack/services/controllersrv/conf/__init__.py +0 -0
  226. cancan_microstack/services/controllersrv/conf/config.py +76 -0
  227. cancan_microstack/services/controllersrv/conf/settings.py +54 -0
  228. cancan_microstack/services/controllersrv/domain/__init__.py +0 -0
  229. cancan_microstack/services/controllersrv/domain/docker_compose/__init__.py +0 -0
  230. cancan_microstack/services/controllersrv/domain/docker_compose/docker_compose_domain.py +278 -0
  231. cancan_microstack/services/controllersrv/domain/service_validator.py +327 -0
  232. cancan_microstack/services/controllersrv/domain/task/__init__.py +17 -0
  233. cancan_microstack/services/controllersrv/domain/task/task_queue.py +286 -0
  234. cancan_microstack/services/controllersrv/domain/task/task_worker.py +495 -0
  235. cancan_microstack/services/controllersrv/infrastructure/__init__.py +0 -0
  236. cancan_microstack/services/controllersrv/interface/__init__.py +0 -0
  237. cancan_microstack/services/controllersrv/interface/api/__init__.py +0 -0
  238. cancan_microstack/services/controllersrv/interface/api/docker_control_api.py +470 -0
  239. cancan_microstack/services/controllersrv/router.py +132 -0
  240. cancan_microstack/services/infrasrv/__init__.py +4 -0
  241. cancan_microstack/services/infrasrv/application/__init__.py +0 -0
  242. cancan_microstack/services/infrasrv/application/health_check_app.py +24 -0
  243. cancan_microstack/services/infrasrv/application/logging/__init__.py +1 -0
  244. cancan_microstack/services/infrasrv/application/logging/log_ingestion_service.py +183 -0
  245. cancan_microstack/services/infrasrv/application/service_config.py +22 -0
  246. cancan_microstack/services/infrasrv/application/service_logs_app.py +53 -0
  247. cancan_microstack/services/infrasrv/application/service_management_app.py +689 -0
  248. cancan_microstack/services/infrasrv/application/service_operation_tracker.py +251 -0
  249. cancan_microstack/services/infrasrv/application/service_registry.py +53 -0
  250. cancan_microstack/services/infrasrv/application/workflow/__init__.py +0 -0
  251. cancan_microstack/services/infrasrv/application/workflow/workflow_app.py +991 -0
  252. cancan_microstack/services/infrasrv/application/workflow/workflow_queue.py +302 -0
  253. cancan_microstack/services/infrasrv/application/workflow/workflow_tasks.py +46 -0
  254. cancan_microstack/services/infrasrv/application/workflow/workflow_worker_runtime.py +122 -0
  255. cancan_microstack/services/infrasrv/conf/__init__.py +0 -0
  256. cancan_microstack/services/infrasrv/conf/config.py +98 -0
  257. cancan_microstack/services/infrasrv/domain/__init__.py +0 -0
  258. cancan_microstack/services/infrasrv/domain/health_check/__init__.py +3 -0
  259. cancan_microstack/services/infrasrv/domain/health_check/health_check_domain.py +576 -0
  260. cancan_microstack/services/infrasrv/domain/hooks/__init__.py +19 -0
  261. cancan_microstack/services/infrasrv/domain/hooks/builtin_hooks.py +308 -0
  262. cancan_microstack/services/infrasrv/domain/hooks/hook_registry.py +43 -0
  263. cancan_microstack/services/infrasrv/domain/hooks/hooks_log_utils.py +275 -0
  264. cancan_microstack/services/infrasrv/domain/hooks/init.py +17 -0
  265. cancan_microstack/services/infrasrv/domain/hooks/metrics.py +205 -0
  266. cancan_microstack/services/infrasrv/domain/hooks/pre_registration_hooks.py +490 -0
  267. cancan_microstack/services/infrasrv/domain/registry/__init__.py +0 -0
  268. cancan_microstack/services/infrasrv/domain/registry/service_registry.py +509 -0
  269. cancan_microstack/services/infrasrv/domain/service_config/__init__.py +0 -0
  270. cancan_microstack/services/infrasrv/domain/service_config/service_config.py +50 -0
  271. cancan_microstack/services/infrasrv/domain/service_logs/__init__.py +0 -0
  272. cancan_microstack/services/infrasrv/domain/service_logs/service_logs_domain.py +51 -0
  273. cancan_microstack/services/infrasrv/domain/workflow/__init__.py +4 -0
  274. cancan_microstack/services/infrasrv/domain/workflow/engine.py +159 -0
  275. cancan_microstack/services/infrasrv/domain/workflow/node_handlers.py +509 -0
  276. cancan_microstack/services/infrasrv/domain/workflow/workflow_domain.py +164 -0
  277. cancan_microstack/services/infrasrv/infrastructure/__init__.py +0 -0
  278. cancan_microstack/services/infrasrv/infrastructure/api/__init__.py +0 -0
  279. cancan_microstack/services/infrasrv/infrastructure/api/controllersrv_api.py +165 -0
  280. cancan_microstack/services/infrasrv/infrastructure/cache/__init__.py +0 -0
  281. cancan_microstack/services/infrasrv/infrastructure/cache/service_registry_cache.py +174 -0
  282. cancan_microstack/services/infrasrv/infrastructure/db/__init__.py +0 -0
  283. cancan_microstack/services/infrasrv/infrastructure/db/model/__init__.py +0 -0
  284. cancan_microstack/services/infrasrv/infrastructure/db/model/execution_log_tbl.py +53 -0
  285. cancan_microstack/services/infrasrv/infrastructure/db/model/node_instance_tbl.py +55 -0
  286. cancan_microstack/services/infrasrv/infrastructure/db/model/service_action_log_tbl.py +44 -0
  287. cancan_microstack/services/infrasrv/infrastructure/db/model/service_config_tbl.py +30 -0
  288. cancan_microstack/services/infrasrv/infrastructure/db/model/service_info_tbl.py +59 -0
  289. cancan_microstack/services/infrasrv/infrastructure/db/model/service_instance_tbl.py +88 -0
  290. cancan_microstack/services/infrasrv/infrastructure/db/model/service_operation_tbl.py +73 -0
  291. cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_definition_tbl.py +55 -0
  292. cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_definition_version_tbl.py +43 -0
  293. cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_engine_alert_tbl.py +57 -0
  294. cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_run_tbl.py +56 -0
  295. cancan_microstack/services/infrasrv/infrastructure/db/operate/__init__.py +0 -0
  296. cancan_microstack/services/infrasrv/infrastructure/db/operate/service_action_log_op.py +239 -0
  297. cancan_microstack/services/infrasrv/infrastructure/db/operate/service_config.py +80 -0
  298. cancan_microstack/services/infrasrv/infrastructure/db/operate/service_config_manager.py +198 -0
  299. cancan_microstack/services/infrasrv/infrastructure/db/operate/service_info_op.py +297 -0
  300. cancan_microstack/services/infrasrv/infrastructure/db/operate/service_instance_op.py +688 -0
  301. cancan_microstack/services/infrasrv/infrastructure/db/operate/service_operation_op.py +387 -0
  302. cancan_microstack/services/infrasrv/infrastructure/db/operate/service_registry.py +124 -0
  303. cancan_microstack/services/infrasrv/infrastructure/db/operate/workflow_op.py +804 -0
  304. cancan_microstack/services/infrasrv/infrastructure/ddl_manager.py +31 -0
  305. cancan_microstack/services/infrasrv/infrastructure/mongo/__init__.py +1 -0
  306. cancan_microstack/services/infrasrv/infrastructure/mongo/log_repository.py +129 -0
  307. cancan_microstack/services/infrasrv/interface/__init__.py +0 -0
  308. cancan_microstack/services/infrasrv/interface/api/__init__.py +0 -0
  309. cancan_microstack/services/infrasrv/interface/api/health_check_api.py +29 -0
  310. cancan_microstack/services/infrasrv/interface/api/hooks.py +284 -0
  311. cancan_microstack/services/infrasrv/interface/api/internal.py +49 -0
  312. cancan_microstack/services/infrasrv/interface/api/internal_instance_api.py +265 -0
  313. cancan_microstack/services/infrasrv/interface/api/internal_operation_api.py +206 -0
  314. cancan_microstack/services/infrasrv/interface/api/service_config.py +50 -0
  315. cancan_microstack/services/infrasrv/interface/api/service_logs_api.py +49 -0
  316. cancan_microstack/services/infrasrv/interface/api/service_management_api.py +113 -0
  317. cancan_microstack/services/infrasrv/interface/api/service_registry.py +117 -0
  318. cancan_microstack/services/infrasrv/interface/api/workflow_api.py +303 -0
  319. cancan_microstack/services/infrasrv/interface/schedule/__init__.py +0 -0
  320. cancan_microstack/services/infrasrv/interface/schedule/cleanup.py +13 -0
  321. cancan_microstack/services/infrasrv/interface/schedule/health_check.py +27 -0
  322. cancan_microstack/services/infrasrv/interface/schedule/log_cleanup.py +26 -0
  323. cancan_microstack/services/infrasrv/interface/schedule/operation_tracker.py +25 -0
  324. cancan_microstack/services/infrasrv/interface/schedule/scheduler.py +39 -0
  325. cancan_microstack/services/infrasrv/interface/schedule/workflow_scheduler.py +115 -0
  326. cancan_microstack/services/infrasrv/router.py +341 -0
  327. cancan_microstack/services/opsbffsrv/__init__.py +4 -0
  328. cancan_microstack/services/opsbffsrv/application/__init__.py +0 -0
  329. cancan_microstack/services/opsbffsrv/application/async_operation_app.py +150 -0
  330. cancan_microstack/services/opsbffsrv/application/auth_app.py +285 -0
  331. cancan_microstack/services/opsbffsrv/application/caddy/__init__.py +0 -0
  332. cancan_microstack/services/opsbffsrv/application/caddy/access_log_analysis_app.py +344 -0
  333. cancan_microstack/services/opsbffsrv/application/caddy/access_log_ingestion_service.py +169 -0
  334. cancan_microstack/services/opsbffsrv/application/caddy/certificate_management_app.py +355 -0
  335. cancan_microstack/services/opsbffsrv/application/caddy/rate_limit_management_app.py +496 -0
  336. cancan_microstack/services/opsbffsrv/application/caddy/route_management_app.py +401 -0
  337. cancan_microstack/services/opsbffsrv/application/caddy/stats_aggregation_app.py +364 -0
  338. cancan_microstack/services/opsbffsrv/application/db_admin_app.py +103 -0
  339. cancan_microstack/services/opsbffsrv/application/db_init_app.py +283 -0
  340. cancan_microstack/services/opsbffsrv/application/logging/__init__.py +1 -0
  341. cancan_microstack/services/opsbffsrv/application/logging/log_query_app.py +28 -0
  342. cancan_microstack/services/opsbffsrv/application/service_config.py +158 -0
  343. cancan_microstack/services/opsbffsrv/application/service_logs_app.py +74 -0
  344. cancan_microstack/services/opsbffsrv/application/service_registry.py +36 -0
  345. cancan_microstack/services/opsbffsrv/application/workflow_ops_app.py +730 -0
  346. cancan_microstack/services/opsbffsrv/conf/__init__.py +0 -0
  347. cancan_microstack/services/opsbffsrv/conf/config.py +224 -0
  348. cancan_microstack/services/opsbffsrv/domain/__init__.py +0 -0
  349. cancan_microstack/services/opsbffsrv/domain/auth/__init__.py +0 -0
  350. cancan_microstack/services/opsbffsrv/domain/auth/admin_init.py +38 -0
  351. cancan_microstack/services/opsbffsrv/domain/auth/auth_domain.py +108 -0
  352. cancan_microstack/services/opsbffsrv/domain/caddy/__init__.py +0 -0
  353. cancan_microstack/services/opsbffsrv/domain/caddy/access_log_analysis.py +358 -0
  354. cancan_microstack/services/opsbffsrv/domain/caddy/certificate_management.py +325 -0
  355. cancan_microstack/services/opsbffsrv/domain/caddy/default_routes.py +53 -0
  356. cancan_microstack/services/opsbffsrv/domain/caddy/rate_limit_management.py +308 -0
  357. cancan_microstack/services/opsbffsrv/domain/caddy/route_management.py +279 -0
  358. cancan_microstack/services/opsbffsrv/domain/caddy/stats_aggregation.py +654 -0
  359. cancan_microstack/services/opsbffsrv/domain/db_admin/__init__.py +0 -0
  360. cancan_microstack/services/opsbffsrv/domain/db_admin/db_admin_domain.py +118 -0
  361. cancan_microstack/services/opsbffsrv/domain/db_init/__init__.py +3 -0
  362. cancan_microstack/services/opsbffsrv/domain/db_init/db_init_domain.py +358 -0
  363. cancan_microstack/services/opsbffsrv/domain/logging/__init__.py +1 -0
  364. cancan_microstack/services/opsbffsrv/domain/logging/log_query_domain.py +99 -0
  365. cancan_microstack/services/opsbffsrv/domain/service_config/__init__.py +0 -0
  366. cancan_microstack/services/opsbffsrv/domain/service_config/service_config.py +81 -0
  367. cancan_microstack/services/opsbffsrv/domain/service_registry/__init__.py +0 -0
  368. cancan_microstack/services/opsbffsrv/domain/service_registry/service_registry.py +292 -0
  369. cancan_microstack/services/opsbffsrv/infrastructure/__init__.py +0 -0
  370. cancan_microstack/services/opsbffsrv/infrastructure/api/__init__.py +0 -0
  371. cancan_microstack/services/opsbffsrv/infrastructure/api/infrasrv_api.py +242 -0
  372. cancan_microstack/services/opsbffsrv/infrastructure/auth/__init__.py +0 -0
  373. cancan_microstack/services/opsbffsrv/infrastructure/auth/captcha_service.py +67 -0
  374. cancan_microstack/services/opsbffsrv/infrastructure/auth/password_service.py +12 -0
  375. cancan_microstack/services/opsbffsrv/infrastructure/auth/redis_store.py +131 -0
  376. cancan_microstack/services/opsbffsrv/infrastructure/auth/totp_service.py +59 -0
  377. cancan_microstack/services/opsbffsrv/infrastructure/caddy/__init__.py +0 -0
  378. cancan_microstack/services/opsbffsrv/infrastructure/caddy/access_log_parser.py +307 -0
  379. cancan_microstack/services/opsbffsrv/infrastructure/caddy/admin_api_client.py +678 -0
  380. cancan_microstack/services/opsbffsrv/infrastructure/caddy/ip_geo_locator.py +176 -0
  381. cancan_microstack/services/opsbffsrv/infrastructure/db/__init__.py +0 -0
  382. cancan_microstack/services/opsbffsrv/infrastructure/db/model/__init__.py +0 -0
  383. cancan_microstack/services/opsbffsrv/infrastructure/db/model/admin_user_tbl.py +33 -0
  384. cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_access_log_tbl.py +90 -0
  385. cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_certificate_tbl.py +65 -0
  386. cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_rate_limit_tbl.py +69 -0
  387. cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_route_tbl.py +66 -0
  388. cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_stats_tbl.py +78 -0
  389. cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_action_log_tbl.py +44 -0
  390. cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_config_tbl.py +30 -0
  391. cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_info_tbl.py +51 -0
  392. cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_instance_tbl.py +68 -0
  393. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/__init__.py +0 -0
  394. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/admin_user_operate.py +59 -0
  395. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_access_log.py +531 -0
  396. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_certificate.py +451 -0
  397. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_rate_limit.py +360 -0
  398. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_route.py +271 -0
  399. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_stats.py +343 -0
  400. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_action_log_op.py +57 -0
  401. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_config.py +86 -0
  402. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_info_op.py +79 -0
  403. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_instance.py +58 -0
  404. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_registry.py +138 -0
  405. cancan_microstack/services/opsbffsrv/infrastructure/ddl_manager.py +31 -0
  406. cancan_microstack/services/opsbffsrv/infrastructure/mongo/__init__.py +1 -0
  407. cancan_microstack/services/opsbffsrv/infrastructure/mongo/log_query_repository.py +87 -0
  408. cancan_microstack/services/opsbffsrv/interface/__init__.py +0 -0
  409. cancan_microstack/services/opsbffsrv/interface/api/__init__.py +0 -0
  410. cancan_microstack/services/opsbffsrv/interface/api/async_operation_api.py +137 -0
  411. cancan_microstack/services/opsbffsrv/interface/api/auth_api.py +113 -0
  412. cancan_microstack/services/opsbffsrv/interface/api/caddy/__init__.py +3 -0
  413. cancan_microstack/services/opsbffsrv/interface/api/caddy/access_log_api.py +174 -0
  414. cancan_microstack/services/opsbffsrv/interface/api/caddy/certificate_api.py +235 -0
  415. cancan_microstack/services/opsbffsrv/interface/api/caddy/rate_limit_api.py +302 -0
  416. cancan_microstack/services/opsbffsrv/interface/api/caddy/route_api.py +250 -0
  417. cancan_microstack/services/opsbffsrv/interface/api/caddy/stats_api.py +243 -0
  418. cancan_microstack/services/opsbffsrv/interface/api/db_admin_api.py +62 -0
  419. cancan_microstack/services/opsbffsrv/interface/api/db_init_api.py +109 -0
  420. cancan_microstack/services/opsbffsrv/interface/api/instance_management_api.py +165 -0
  421. cancan_microstack/services/opsbffsrv/interface/api/log_query_api.py +41 -0
  422. cancan_microstack/services/opsbffsrv/interface/api/mongo_express_proxy_api.py +181 -0
  423. cancan_microstack/services/opsbffsrv/interface/api/pgweb_proxy_api.py +154 -0
  424. cancan_microstack/services/opsbffsrv/interface/api/rabbitmq_mgmt_proxy_api.py +518 -0
  425. cancan_microstack/services/opsbffsrv/interface/api/redis_commander_proxy_api.py +133 -0
  426. cancan_microstack/services/opsbffsrv/interface/api/service_config.py +146 -0
  427. cancan_microstack/services/opsbffsrv/interface/api/service_logs_api.py +81 -0
  428. cancan_microstack/services/opsbffsrv/interface/api/service_registry.py +66 -0
  429. cancan_microstack/services/opsbffsrv/interface/api/workflow_ops_api.py +413 -0
  430. cancan_microstack/services/opsbffsrv/interface/middleware/__init__.py +0 -0
  431. cancan_microstack/services/opsbffsrv/interface/middleware/auth_middleware.py +52 -0
  432. cancan_microstack/services/opsbffsrv/router.py +901 -0
  433. cancan_microstack/utils/__init__.py +1 -0
  434. cancan_microstack/utils/container_env.py +218 -0
  435. cancan_microstack-0.0.1.dist-info/METADATA +155 -0
  436. cancan_microstack-0.0.1.dist-info/RECORD +440 -0
  437. cancan_microstack-0.0.1.dist-info/WHEEL +5 -0
  438. cancan_microstack-0.0.1.dist-info/entry_points.txt +2 -0
  439. cancan_microstack-0.0.1.dist-info/licenses/LICENSE +21 -0
  440. cancan_microstack-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,205 @@
1
+ """
2
+ 钩子监控指标模块
3
+
4
+ 提供钩子执行相关的指标收集和暴露功能
5
+ """
6
+ import threading
7
+ from datetime import (
8
+ datetime,
9
+ timezone,
10
+ )
11
+ from typing import (
12
+ Dict,
13
+ List,
14
+ Optional,
15
+ Union,
16
+ Callable,
17
+ )
18
+
19
+ from cancan_microstack.public.const.metrics_enums import (
20
+ MetricType,
21
+ HookMetricName,
22
+ HookMetricResult,
23
+ )
24
+ from cancan_microstack.public.schemas.hook_metrics import (
25
+ HookExecutionLabels,
26
+ HookFailureLabels,
27
+ ActiveHooksLabels,
28
+ HookRejectionLabels,
29
+ Metric,
30
+ )
31
+ from linglong_web.utils import logger
32
+
33
+ # 类型别名,用于表示所有可能的标签模型
34
+ LabelModel = Union[HookExecutionLabels, HookFailureLabels, ActiveHooksLabels, HookRejectionLabels]
35
+
36
+
37
+ class HookMetrics:
38
+ """钩子指标收集器"""
39
+
40
+ def __init__(self):
41
+ self._metrics: Dict[str, Metric] = {}
42
+ self._lock = threading.Lock()
43
+ self._init_default_metrics()
44
+
45
+ def _init_default_metrics(self):
46
+ """初始化默认指标"""
47
+ self.register_metric(
48
+ HookMetricName.EXECUTIONS_TOTAL,
49
+ MetricType.COUNTER,
50
+ "Total number of hook executions",
51
+ )
52
+ self.register_metric(
53
+ HookMetricName.EXECUTION_DURATION_SECONDS,
54
+ MetricType.HISTOGRAM,
55
+ "Time spent executing hooks",
56
+ )
57
+ self.register_metric(
58
+ HookMetricName.FAILURES_TOTAL,
59
+ MetricType.COUNTER,
60
+ "Total number of hook failures",
61
+ )
62
+ self.register_metric(
63
+ HookMetricName.ACTIVE_HOOKS,
64
+ MetricType.GAUGE,
65
+ "Number of active hooks",
66
+ )
67
+ self.register_metric(
68
+ HookMetricName.REJECTIONS_TOTAL,
69
+ MetricType.COUNTER,
70
+ "Total number of service rejections by hooks",
71
+ )
72
+
73
+ def register_metric(self, name: HookMetricName, metric_type: MetricType, description: str) -> None:
74
+ """注册指标"""
75
+ with self._lock:
76
+ self._metrics[name] = Metric(
77
+ name=name,
78
+ metric_type=metric_type,
79
+ description=description,
80
+ )
81
+ logger.debug(f"Registered metric: {name}")
82
+
83
+ def _update_metric(self, name: HookMetricName, value: float, labels: Optional[LabelModel],
84
+ update_func: Callable[[Metric, float], None]) -> None:
85
+ """通用指标更新方法"""
86
+ with self._lock:
87
+ metric_name_str = name
88
+ if metric_name_str not in self._metrics:
89
+ logger.warning(f"Metric {metric_name_str} not registered")
90
+ return
91
+
92
+ metric = self._metrics[metric_name_str]
93
+ update_func(metric, value)
94
+ metric.labels = labels.model_dump() if labels else {}
95
+ metric.timestamp = datetime.now(timezone.utc)
96
+ logger.debug(f"Updated metric {metric_name_str} with value {value}")
97
+
98
+ def increment_counter(self, name: HookMetricName, value: float = 1.0, labels: Optional[LabelModel] = None) -> None:
99
+ """增加计数器指标"""
100
+
101
+ def _increment(metric: Metric, val: float):
102
+ metric.value += val
103
+
104
+ self._update_metric(name, value, labels, _increment)
105
+
106
+ def set_gauge(self, name: HookMetricName, value: float, labels: Optional[LabelModel] = None) -> None:
107
+ """设置仪表盘指标值"""
108
+
109
+ def _set(metric: Metric, val: float):
110
+ metric.value = val
111
+
112
+ self._update_metric(name, value, labels, _set)
113
+
114
+ def observe_histogram(self, name: HookMetricName, value: float, labels: Optional[LabelModel] = None) -> None:
115
+ """观察直方图指标值"""
116
+
117
+ def update_histogram(metric: Metric, new_value: float):
118
+ if metric.value == 0:
119
+ metric.value = new_value
120
+ else:
121
+ metric.value = (metric.value + new_value) / 2 # 简单移动平均
122
+
123
+ self._update_metric(name, value, labels, update_histogram)
124
+
125
+ def get_metric(self, name: HookMetricName) -> Optional[Metric]:
126
+ """获取指标"""
127
+ with self._lock:
128
+ return self._metrics.get(name)
129
+
130
+ def get_all_metrics(self) -> List[Metric]:
131
+ """获取所有指标"""
132
+ with self._lock:
133
+ return list(self._metrics.values())
134
+
135
+
136
+ class HookMetricsCollector:
137
+ """钩子指标收集器 - 用于在钩子执行过程中收集指标"""
138
+
139
+ def __init__(self, metrics: HookMetrics):
140
+ self._metrics = metrics
141
+
142
+ def record_hook_execution(self, hook_name: str, hook_type: str,
143
+ success: bool, duration: float,
144
+ error_type: Optional[str] = None) -> None:
145
+ """记录钩子执行"""
146
+ result = HookMetricResult.SUCCESS if success else HookMetricResult.FAILURE
147
+ execution_labels = HookExecutionLabels(
148
+ hook_name=hook_name,
149
+ hook_type=hook_type,
150
+ result=result
151
+ )
152
+ self._metrics.increment_counter(HookMetricName.EXECUTIONS_TOTAL, labels=execution_labels)
153
+
154
+ duration_labels = HookExecutionLabels(hook_name=hook_name, hook_type=hook_type, result=result)
155
+ self._metrics.observe_histogram(
156
+ HookMetricName.EXECUTION_DURATION_SECONDS,
157
+ duration,
158
+ labels=duration_labels
159
+ )
160
+
161
+ if not success:
162
+ failure_labels = HookFailureLabels(
163
+ hook_name=hook_name,
164
+ hook_type=hook_type,
165
+ error_type=error_type or "unknown"
166
+ )
167
+ self._metrics.increment_counter(HookMetricName.FAILURES_TOTAL, labels=failure_labels)
168
+
169
+ def record_hook_rejection(self, hook_name: str, reason: str) -> None:
170
+ """记录钩子拒绝注册"""
171
+ rejection_labels = HookRejectionLabels(hook_name=hook_name, reason=reason)
172
+ self._metrics.increment_counter(HookMetricName.REJECTIONS_TOTAL, labels=rejection_labels)
173
+
174
+ def update_active_hooks_count(self, hook_type: str, count: int) -> None:
175
+ """更新活跃钩子数量"""
176
+ active_hooks_labels = ActiveHooksLabels(hook_type=hook_type)
177
+ self._metrics.set_gauge(HookMetricName.ACTIVE_HOOKS, count, labels=active_hooks_labels)
178
+
179
+
180
+ # 全局指标实例
181
+ _global_metrics: Optional[HookMetrics] = None
182
+ _global_collector: Optional[HookMetricsCollector] = None
183
+
184
+
185
+ def get_metrics() -> HookMetrics:
186
+ """获取全局指标实例"""
187
+ global _global_metrics
188
+ if _global_metrics is None:
189
+ _global_metrics = HookMetrics()
190
+ return _global_metrics
191
+
192
+
193
+ def get_metrics_collector() -> HookMetricsCollector:
194
+ """获取全局指标收集器实例"""
195
+ global _global_collector
196
+ if _global_collector is None:
197
+ _global_collector = HookMetricsCollector(get_metrics())
198
+ return _global_collector
199
+
200
+
201
+ def reset_metrics() -> None:
202
+ """重置全局指标"""
203
+ global _global_metrics, _global_collector
204
+ _global_metrics = None
205
+ _global_collector = None
@@ -0,0 +1,490 @@
1
+ """
2
+ 预注册钩子 (Pre-registration Hooks) 机制
3
+
4
+ 提供服务注册前的钩子处理功能,允许在服务注册核心逻辑执行前,
5
+ 动态地插入自定义的、可插拔的业务逻辑单元。
6
+ 这是实现业务逻辑与核心流程解耦的关键。
7
+ """
8
+
9
+ import asyncio
10
+ from abc import ABC, abstractmethod
11
+ from datetime import datetime
12
+ from typing import (
13
+ Dict,
14
+ List,
15
+ Optional,
16
+ Callable,
17
+ )
18
+ from functools import wraps
19
+ import inspect
20
+
21
+ from cancan_microstack.public.schemas.infra.enums import (
22
+ HookExecutionResult as HookResult,
23
+ HookPriority,
24
+ )
25
+ from cancan_microstack.public.schemas.hooks import (
26
+ HookContext,
27
+ HookExecutionResult,
28
+ )
29
+ from linglong_web.utils import logger
30
+ from .hooks_log_utils import (
31
+ log_hook_registration,
32
+ log_hook_deregistration,
33
+ log_hook_execution_start,
34
+ log_hook_execution_success,
35
+ log_hook_execution_failure,
36
+ log_hook_rejection,
37
+ )
38
+ from .metrics import get_metrics_collector
39
+
40
+
41
+ class BaseHook(ABC):
42
+ """
43
+ 钩子基类 (Abstract TableBase Class)。
44
+
45
+ 定义了所有具体 Hook 实现必须遵守的接口协定。
46
+ 这是一种策略模式(Strategy Pattern)的体现,每个 Hook 都是一个可替换的策略。
47
+ """
48
+
49
+ def __init__(self, name: str, priority: HookPriority = HookPriority.NORMAL):
50
+ """
51
+ 初始化一个 Hook 实例。
52
+
53
+ :param name: Hook 的唯一名称,用于识别和日志记录。
54
+ :param priority: Hook 的执行优先级。值越小,优先级越高。
55
+ """
56
+ self.name = name
57
+ self.priority = priority
58
+
59
+ @abstractmethod
60
+ async def execute(self, context: HookContext) -> HookExecutionResult:
61
+ """
62
+ 执行钩子的核心逻辑。
63
+
64
+ 这是一个异步的抽象方法,所有子类都必须实现此方法。
65
+ 它接收一个 HookContext 对象,其中包含了执行决策所需的所有信息。
66
+
67
+ :param context: 钩子执行的上下文信息。
68
+ :return: 钩子执行的结果。
69
+ """
70
+ pass
71
+
72
+ def __str__(self):
73
+ return f"{self.__class__.__name__}(name={self.name}, priority={self.priority.name})"
74
+
75
+
76
+ class FunctionHook(BaseHook):
77
+ """
78
+ 函数钩子 (Function-based Hook)。
79
+
80
+ 将一个普通的 Python 函数(同步或异步)包装成一个符合 BaseHook 接口的对象。
81
+ 这使得开发者可以简单地通过编写一个函数来定义一个 Hook 的逻辑。
82
+ """
83
+
84
+ def __init__(self, name: str, func: Callable, priority: HookPriority = HookPriority.NORMAL):
85
+ super().__init__(name, priority)
86
+ self.func = func # 被包装的函数
87
+
88
+ async def execute(self, context: HookContext) -> HookExecutionResult:
89
+ """
90
+ 执行被包装的函数,并处理其返回结果。
91
+ """
92
+ start_time = datetime.now()
93
+ error = None
94
+ result = HookResult.SUCCESS
95
+ message = ""
96
+
97
+ try:
98
+ # 优雅地处理同步和异步函数
99
+ if inspect.iscoroutinefunction(self.func):
100
+ # 如果是协程函数 (async def),直接 await 调用
101
+ hook_result = await self.func(context)
102
+ else:
103
+ # 如果是普通同步函数 (def),在线程池中执行以避免阻塞事件循环
104
+ loop = asyncio.get_event_loop()
105
+ hook_result = await loop.run_in_executor(None, self.func, context)
106
+
107
+ # 对被包装函数的返回值进行标准化处理,转换为 HookExecutionResult
108
+ if isinstance(hook_result, HookResult):
109
+ result = hook_result
110
+ message = f"Hook {self.name} executed with result: {result.value}"
111
+ elif isinstance(hook_result, bool):
112
+ result = HookResult.SUCCESS if hook_result else HookResult.FAILURE
113
+ message = f"Hook {self.name} returned: {hook_result}"
114
+ elif isinstance(hook_result, tuple) and len(hook_result) == 2:
115
+ result, message = hook_result
116
+ if not isinstance(result, HookResult):
117
+ result = HookResult.SUCCESS if result else HookResult.FAILURE
118
+ else:
119
+ message = f"Hook {self.name} returned: {hook_result}"
120
+
121
+ except Exception as e:
122
+ # 捕获执行过程中的任何异常,并将其转化为一个 FAILURE 结果
123
+ error = f"{type(e).__name__}: {str(e)}"
124
+ result = HookResult.FAILURE
125
+ message = f"Hook {self.name} failed: {error}"
126
+ logger.error(f"Error executing hook {self.name}: {e}")
127
+
128
+ execution_time = (datetime.now() - start_time).total_seconds()
129
+
130
+ # 返回一个标准的、结构化的执行结果对象
131
+ return HookExecutionResult(
132
+ hook_name=self.name,
133
+ result=result,
134
+ message=message,
135
+ execution_time=execution_time,
136
+ error=error
137
+ )
138
+
139
+
140
+ class HookManager:
141
+ """
142
+ 钩子管理器 (Hook Manager)。
143
+
144
+ 作为整个 Hook 机制的中心调度器,负责 Hook 的注册、发现、组织和执行。
145
+ """
146
+
147
+ def __init__(self):
148
+ # 按 service_type 存储的钩子,实现差异化流程
149
+ self._hooks: Dict[str, List[BaseHook]] = {}
150
+ # 全局钩子,对所有 service_type 都生效
151
+ self._global_hooks: List[BaseHook] = []
152
+ # 存储最近的 Hook 执行历史,用于调试和监控
153
+ self._execution_history: List[HookExecutionResult] = []
154
+ self._max_history = 1000 # 最大历史记录条数
155
+ # 指标收集器,用于 Prometheus/Grafana 等监控系统
156
+ self._metrics_collector = get_metrics_collector()
157
+
158
+ def register_hook(self, hook: BaseHook, service_type: Optional[str] = None):
159
+ """
160
+ 注册一个 Hook。
161
+
162
+ 可以将 Hook 注册为全局的,或针对特定的 service_type。
163
+ 注册后会根据优先级进行排序。
164
+
165
+ :param hook: 要注册的 Hook 实例。
166
+ :param service_type: 如果提供,则该 Hook 只对指定类型的服务生效。
167
+ """
168
+ if service_type:
169
+ # 注册针对特定 service_type 的 Hook
170
+ if service_type not in self._hooks:
171
+ self._hooks[service_type] = []
172
+ self._hooks[service_type].append(hook)
173
+ # 根据优先级排序,值越小优先级越高
174
+ self._hooks[service_type].sort(key=lambda h: h.priority.value)
175
+ logger.info(f"Registered hook {hook.name} for service type {service_type}")
176
+
177
+ self._metrics_collector.update_active_hooks_count(service_type, len(self._hooks[service_type]))
178
+ log_hook_registration(logger, hook.name, service_type)
179
+ else:
180
+ # 注册全局 Hook
181
+ self._global_hooks.append(hook)
182
+ self._global_hooks.sort(key=lambda h: h.priority.value)
183
+ logger.info(f"Registered global hook {hook.name}")
184
+
185
+ self._metrics_collector.update_active_hooks_count("global", len(self._global_hooks))
186
+ log_hook_registration(logger, hook.name, "global")
187
+
188
+ def unregister_hook(self, hook_name: str, service_type: Optional[str] = None):
189
+ """
190
+ 注销一个 Hook。
191
+
192
+ :param hook_name: 要注销的 Hook 的名称。
193
+ :param service_type: 如果提供,则只注销指定 service_type 下的同名 Hook。
194
+ """
195
+ if service_type and service_type in self._hooks:
196
+ self._hooks[service_type] = [h for h in self._hooks[service_type] if h.name != hook_name]
197
+ logger.info(f"Unregistered hook {hook_name} for service type {service_type}")
198
+ self._metrics_collector.update_active_hooks_count(service_type, len(self._hooks[service_type]))
199
+ log_hook_deregistration(logger, hook_name, service_type)
200
+ else:
201
+ self._global_hooks = [h for h in self._global_hooks if h.name != hook_name]
202
+ logger.info(f"Unregistered global hook {hook_name}")
203
+ self._metrics_collector.update_active_hooks_count("global", len(self._global_hooks))
204
+ log_hook_deregistration(logger, hook_name, "global")
205
+
206
+ def get_hooks(self, service_type: Optional[str] = None) -> List[BaseHook]:
207
+ """
208
+ 根据 service_type 获取将要执行的 Hook 列表。
209
+
210
+ 返回的列表是全局 Hooks 和特定类型 Hooks 的并集,并已按优先级排序。
211
+
212
+ :param service_type: 服务的类型。
213
+ :return: 一个有序的 Hook 列表。
214
+ """
215
+ hooks = self._global_hooks.copy()
216
+ if service_type and service_type in self._hooks:
217
+ hooks.extend(self._hooks[service_type])
218
+ hooks.sort(key=lambda h: h.priority.value)
219
+ return hooks
220
+
221
+ async def execute_hooks(self, context: HookContext) -> List[HookExecutionResult]:
222
+ """
223
+ 执行与给定上下文匹配的所有 Hooks。
224
+
225
+ 这是 Hook 机制的核心调度方法。它负责:
226
+ 1. 筛选合适的 Hooks。
227
+ 2. 按顺序执行它们。
228
+ 3. 处理每个 Hook 的返回结果,包括重试、中断和超时。
229
+ 4. 记录详细的日志和监控指标。
230
+
231
+ :param context: 本次执行的上下文。
232
+ :return: 所有已执行的 Hooks 的结果列表。
233
+ """
234
+ hooks = self.get_hooks(context.service_type)
235
+ results = []
236
+
237
+ for hook in hooks:
238
+ retry_count = 0
239
+ max_retries = context.max_retries
240
+
241
+ while retry_count <= max_retries:
242
+ try:
243
+ # 为每个 Hook 创建独立的上下文副本,防止互相污染
244
+ hook_context = HookContext(
245
+ service_name=context.service_name,
246
+ service_type=context.service_type,
247
+ instance_id=context.instance_id,
248
+ host=context.host,
249
+ port=context.port,
250
+ metadata=context.metadata.copy(),
251
+ created_at=context.created_at,
252
+ retry_count=retry_count,
253
+ max_retries=max_retries,
254
+ timeout=context.timeout,
255
+ dry_run=context.dry_run
256
+ )
257
+
258
+ log_hook_execution_start(logger, hook.name, context.service_type, hook_context.metadata)
259
+
260
+ # 使用 asyncio.wait_for 实现单个 Hook 的超时控制
261
+ result = await asyncio.wait_for(
262
+ hook.execute(hook_context),
263
+ timeout=context.timeout
264
+ )
265
+
266
+ result.retry_count = retry_count
267
+
268
+ # 如果 Hook 成功执行并修改了元数据,将变更合并回主上下文
269
+ if result.result == HookResult.SUCCESS:
270
+ context.metadata.update(hook_context.metadata)
271
+
272
+ results.append(result)
273
+ self._add_to_history(result)
274
+ self._metrics_collector.record_hook_execution(
275
+ hook.name,
276
+ context.service_type,
277
+ result.result == HookResult.SUCCESS,
278
+ result.execution_time,
279
+ None if result.result == HookResult.SUCCESS else result.message
280
+ )
281
+
282
+ # 根据结果进行结构化日志记录
283
+ if result.result == HookResult.SUCCESS:
284
+ log_hook_execution_success(logger, hook.name, context.service_type, result.execution_time,
285
+ hook_context.metadata)
286
+ elif result.result == HookResult.FAILURE:
287
+ log_hook_execution_failure(logger, hook.name, context.service_type, result.execution_time,
288
+ result.message, hook_context.metadata)
289
+ elif result.result == HookResult.TERMINATE:
290
+ log_hook_rejection(logger, hook.name, context.service_type, result.message,
291
+ hook_context.metadata)
292
+
293
+ # 核心流程控制逻辑
294
+ if result.result == HookResult.TERMINATE:
295
+ # 熔断机制:立即停止执行后续所有 Hooks
296
+ logger.warning(f"Hook {hook.name} terminated the execution chain")
297
+ return results
298
+ elif result.result == HookResult.FAILURE and retry_count >= max_retries:
299
+ logger.error(f"Hook {hook.name} failed after {max_retries} retries")
300
+ return results
301
+ elif result.result == HookResult.FAILURE:
302
+ # 失败重试
303
+ logger.warning(f"Hook {hook.name} failed, retrying ({retry_count + 1}/{max_retries})")
304
+ retry_count += 1
305
+ await asyncio.sleep(1) # 重试前等待
306
+ continue
307
+ elif result.result == HookResult.RETRY:
308
+ # Hook 主动请求重试
309
+ logger.info(f"Hook {hook.name} requested retry ({retry_count + 1}/{max_retries})")
310
+ retry_count += 1
311
+ await asyncio.sleep(1)
312
+ continue
313
+ else:
314
+ # SUCCESS 或 SKIP,跳出重试循环,继续下一个 Hook
315
+ break
316
+
317
+ except asyncio.TimeoutError:
318
+ # 超时处理
319
+ error_msg = f"Hook {hook.name} timed out after {context.timeout} seconds"
320
+ logger.error(error_msg)
321
+ result = HookExecutionResult(hook_name=hook.name, result=HookResult.FAILURE, message=error_msg,
322
+ retry_count=retry_count)
323
+ results.append(result)
324
+ self._add_to_history(result)
325
+ log_hook_execution_failure(logger, hook.name, context.service_type, 0, error_msg, context.metadata)
326
+ self._metrics_collector.record_hook_execution(hook.name, context.service_type, False, 0, error_msg)
327
+ retry_count += 1
328
+
329
+ except Exception as e:
330
+ # 未知异常处理
331
+ error_msg = f"Unexpected error executing hook {hook.name}: {str(e)}"
332
+ logger.error(error_msg)
333
+ result = HookExecutionResult(hook_name=hook.name, result=HookResult.FAILURE, message=error_msg,
334
+ error=str(e), retry_count=retry_count)
335
+ results.append(result)
336
+ self._add_to_history(result)
337
+ log_hook_execution_failure(logger, hook.name, context.service_type, 0, error_msg, context.metadata,
338
+ e)
339
+ self._metrics_collector.record_hook_execution(hook.name, context.service_type, False, 0, error_msg)
340
+ retry_count += 1
341
+
342
+ return results
343
+
344
+ def _add_to_history(self, result: HookExecutionResult):
345
+ """添加执行结果到内存中的历史记录队列。"""
346
+ self._execution_history.append(result)
347
+ if len(self._execution_history) > self._max_history:
348
+ self._execution_history.pop(0)
349
+
350
+ def get_execution_history(self, service_name: Optional[str] = None,
351
+ hook_name: Optional[str] = None,
352
+ limit: int = 100) -> List[HookExecutionResult]:
353
+ """获取 Hook 执行历史,用于 API 查询或调试。"""
354
+ history = self._execution_history
355
+ if service_name:
356
+ pass
357
+ if hook_name:
358
+ history = [r for r in history if r.hook_name == hook_name]
359
+ return history[-limit:] if limit > 0 else history
360
+
361
+ def clear_history(self):
362
+ """清空执行历史。"""
363
+ self._execution_history.clear()
364
+ logger.info("Cleared hook execution history")
365
+
366
+
367
+ def hook(name: Optional[str] = None, priority: HookPriority = HookPriority.NORMAL,
368
+ service_type: Optional[str] = None):
369
+ """
370
+ Hook 装饰器。
371
+
372
+ 提供一种声明式的方式来创建和注册一个 FunctionHook。
373
+ 这是添加新 Hook 的首选方式,因为它非常简洁和直观。
374
+
375
+ 示例:
376
+ @hook(name="my_validation_hook", priority=HookPriority.HIGH)
377
+ def my_hook_logic(context: HookContext):
378
+ # ...
379
+ """
380
+
381
+ def decorator(func: Callable):
382
+ hook_name = name or f"{func.__module__}.{func.__name__}"
383
+ function_hook = FunctionHook(hook_name, func, priority)
384
+
385
+ # 导入并获取全局 HookManager 实例来注册自己
386
+ from .hook_registry import get_hook_manager
387
+ hook_manager = get_hook_manager()
388
+ hook_manager.register_hook(function_hook, service_type)
389
+
390
+ @wraps(func)
391
+ async def wrapper(*args, **kwargs):
392
+ # 装饰器本身不改变原函数的行为
393
+ return func(*args, **kwargs)
394
+
395
+ return wrapper
396
+
397
+ return decorator
398
+
399
+
400
+ # -------------------
401
+ # 预定义的、通用的 Hook 实现
402
+ # -------------------
403
+
404
+ class LoggingHook(BaseHook):
405
+ """
406
+ 日志记录钩子。
407
+
408
+ 一个简单的示例 Hook,用于在执行链的开始记录一条日志。
409
+ 通常具有最高的优先级,以确保它总是第一个执行。
410
+ """
411
+
412
+ def __init__(self, name: str = "logging_hook", priority: HookPriority = HookPriority.HIGHEST):
413
+ super().__init__(name, priority)
414
+
415
+ async def execute(self, context: HookContext) -> HookExecutionResult:
416
+ logger.info(f"Executing pre-registration hook for service {context.service_name} "
417
+ f"(type: {context.service_type}, instance: {context.instance_id})")
418
+ return HookExecutionResult(
419
+ hook_name=self.name,
420
+ result=HookResult.SUCCESS,
421
+ message="Logged service registration"
422
+ )
423
+
424
+
425
+ class ValidationHook(BaseHook):
426
+ """
427
+ 验证钩子。
428
+
429
+ 用于执行基本的数据验证,确保传入的注册信息包含所有必要字段。
430
+ """
431
+
432
+ def __init__(self, name: str = "validation_hook", priority: HookPriority = HookPriority.HIGH):
433
+ super().__init__(name, priority)
434
+
435
+ async def execute(self, context: HookContext) -> HookExecutionResult:
436
+ if not context.service_name:
437
+ return HookExecutionResult(hook_name=self.name, result=HookResult.FAILURE,
438
+ message="Service name is required")
439
+ if not context.service_type:
440
+ return HookExecutionResult(hook_name=self.name, result=HookResult.FAILURE,
441
+ message="Service type is required")
442
+ if not context.instance_id:
443
+ return HookExecutionResult(hook_name=self.name, result=HookResult.FAILURE,
444
+ message="Instance ID is required")
445
+ return HookExecutionResult(hook_name=self.name, result=HookResult.SUCCESS, message="Validation passed")
446
+
447
+
448
+ class MetadataHook(BaseHook):
449
+ """
450
+ 元数据处理钩子。
451
+
452
+ 演示了 Hook 如何修改传入的上下文。
453
+ 这里它向服务的元数据中添加了注册时间戳和一个标记。
454
+ """
455
+
456
+ def __init__(self, name: str = "metadata_hook", priority: HookPriority = HookPriority.NORMAL):
457
+ super().__init__(name, priority)
458
+
459
+ async def execute(self, context: HookContext) -> HookExecutionResult:
460
+ context.metadata["registered_at"] = datetime.now().isoformat()
461
+ context.metadata["pre_hooks_executed"] = True
462
+ return HookExecutionResult(
463
+ hook_name=self.name,
464
+ result=HookResult.SUCCESS,
465
+ message="Metadata processed"
466
+ )
467
+
468
+
469
+ # 模块自测试/示例代码
470
+ async def example_usage():
471
+ """示例使用函数"""
472
+ from .hook_registry import get_hook_manager
473
+ from linglong_web.utils import logger
474
+ hook_manager = get_hook_manager()
475
+ hook_manager.register_hook(LoggingHook())
476
+ hook_manager.register_hook(ValidationHook())
477
+ hook_manager.register_hook(MetadataHook())
478
+ context = HookContext(
479
+ service_name="example-service",
480
+ service_type="web",
481
+ instance_id="example-123",
482
+ metadata={"version": "1.0.0"}
483
+ )
484
+ results = await hook_manager.execute_hooks(context)
485
+ for result in results:
486
+ logger.info("%s: %s - %s", result.hook_name, result.result.value, result.message)
487
+
488
+
489
+ if __name__ == "__main__":
490
+ asyncio.run(example_usage())