aegis-stack 0.2.0rc2__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 (392) hide show
  1. aegis/__init__.py +5 -0
  2. aegis/__main__.py +51 -0
  3. aegis/cli/__init__.py +6 -0
  4. aegis/cli/callbacks.py +114 -0
  5. aegis/cli/interactive.py +611 -0
  6. aegis/cli/utils.py +70 -0
  7. aegis/cli/validators.py +34 -0
  8. aegis/commands/__init__.py +6 -0
  9. aegis/commands/add.py +353 -0
  10. aegis/commands/add_service.py +332 -0
  11. aegis/commands/components.py +35 -0
  12. aegis/commands/init.py +370 -0
  13. aegis/commands/remove.py +227 -0
  14. aegis/commands/services.py +52 -0
  15. aegis/commands/update.py +252 -0
  16. aegis/commands/version.py +12 -0
  17. aegis/config/__init__.py +1 -0
  18. aegis/config/shared_files.py +136 -0
  19. aegis/core/CLAUDE.md +377 -0
  20. aegis/core/__init__.py +6 -0
  21. aegis/core/component_files.py +228 -0
  22. aegis/core/component_utils.py +220 -0
  23. aegis/core/components.py +127 -0
  24. aegis/core/copier_manager.py +315 -0
  25. aegis/core/copier_updater.py +475 -0
  26. aegis/core/dependency_resolver.py +119 -0
  27. aegis/core/manual_updater.py +554 -0
  28. aegis/core/post_gen_tasks.py +547 -0
  29. aegis/core/service_resolver.py +261 -0
  30. aegis/core/services.py +157 -0
  31. aegis/core/template_generator.py +266 -0
  32. aegis/core/version_compatibility.py +259 -0
  33. aegis/templates/CLAUDE.md +591 -0
  34. aegis/templates/cookiecutter-aegis-project/cookiecutter.json +39 -0
  35. aegis/templates/cookiecutter-aegis-project/hooks/post_gen_project.py +214 -0
  36. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.dockerignore +71 -0
  37. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.env.example.j2 +130 -0
  38. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.gitignore +131 -0
  39. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/Dockerfile +53 -0
  40. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/Makefile +236 -0
  41. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/README.md.j2 +196 -0
  42. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/alembic.ini.j2 +111 -0
  43. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/env.py.j2 +91 -0
  44. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/script.py.mako +25 -0
  45. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/versions/001_initial_auth.py.j2 +51 -0
  46. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/__init__.py +5 -0
  47. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/__init__.py +6 -0
  48. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/ai.py.j2 +700 -0
  49. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/ai_rendering.py +361 -0
  50. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/auth.py.j2 +253 -0
  51. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/health.py.j2 +419 -0
  52. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/load_test.py.j2 +656 -0
  53. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/main.py.j2 +65 -0
  54. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/marko_terminal_renderer.py +489 -0
  55. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/tasks.py.j2 +328 -0
  56. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/{% if cookiecutter.include_scheduler == /"yes/" %}tasks.py{% endif %}" +340 -0
  57. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/__init__.py +0 -0
  58. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/__init__.py +0 -0
  59. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/ai/__init__.py +8 -0
  60. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/ai/router.py +329 -0
  61. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/auth/__init__.py +1 -0
  62. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/auth/router.py +64 -0
  63. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/deps.py +58 -0
  64. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/health.py +163 -0
  65. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/models.py.j2 +280 -0
  66. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/routing.py.j2 +32 -0
  67. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/scheduler.py.j2 +121 -0
  68. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/worker.py.j2 +478 -0
  69. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/hooks.py +144 -0
  70. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/main.py +31 -0
  71. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/middleware/__init__.py +1 -0
  72. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/middleware/cors.py +20 -0
  73. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/shutdown/__init__.py +1 -0
  74. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/shutdown/cleanup.py +14 -0
  75. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/__init__.py +1 -0
  76. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/component_health.py.j2 +418 -0
  77. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/database_init.py.j2 +83 -0
  78. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/__init__.py +5 -0
  79. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/__init__.py +27 -0
  80. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/table.py +78 -0
  81. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/text.py +142 -0
  82. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/__init__.py.j2 +47 -0
  83. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/ai_card.py +287 -0
  84. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/auth_card.py +198 -0
  85. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/base_card.py +256 -0
  86. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/card_factory.py +227 -0
  87. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/card_utils.py +333 -0
  88. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/database_card.py +420 -0
  89. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/fastapi_card.py +328 -0
  90. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/flet_card.py +267 -0
  91. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/redis_card.py +322 -0
  92. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/scheduler_card.py +352 -0
  93. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/services_card.py +233 -0
  94. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/worker_card.py +684 -0
  95. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/main.py.j2 +653 -0
  96. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/theme.py +48 -0
  97. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/scheduler/__init__.py +1 -0
  98. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/scheduler/main.py.j2 +156 -0
  99. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/CLAUDE.md.j2 +213 -0
  100. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/__init__.py +6 -0
  101. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/constants.py.j2 +30 -0
  102. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/pools.py +97 -0
  103. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/__init__.py +1 -0
  104. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/load_test.py +55 -0
  105. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/media.py +49 -0
  106. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/system.py +44 -0
  107. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/registry.py +139 -0
  108. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/__init__.py +120 -0
  109. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/load_tasks.py +507 -0
  110. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/simple_system_tasks.py +33 -0
  111. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/system_tasks.py +281 -0
  112. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/config.py.j2 +178 -0
  113. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/constants.py +58 -0
  114. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/db.py.j2 +176 -0
  115. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/log.py +92 -0
  116. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/security.py +62 -0
  117. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/__init__.py +1 -0
  118. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/webserver.py +40 -0
  119. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/{% if cookiecutter.include_scheduler == /"yes/" %}scheduler.py{% endif %}" +21 -0
  120. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/integrations/__init__.py +0 -0
  121. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/integrations/main.py +62 -0
  122. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/models/__init__.py +1 -0
  123. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/models/user.py +44 -0
  124. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/py.typed +0 -0
  125. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/__init__.py +1 -0
  126. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/__init__.py +8 -0
  127. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/config.py +130 -0
  128. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/conversation.py +213 -0
  129. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/health.py +96 -0
  130. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/models.py +229 -0
  131. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/providers.py +370 -0
  132. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/service.py +388 -0
  133. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/__init__.py +1 -0
  134. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/auth_service.py +41 -0
  135. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/health.py +164 -0
  136. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/user_service.py +83 -0
  137. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/middleware_inspector.py.j2 +223 -0
  138. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/models.py.j2 +70 -0
  139. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/route_inspector.py.j2 +155 -0
  140. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/load_test.py +679 -0
  141. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/load_test_models.py +266 -0
  142. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/__init__.py.j2 +21 -0
  143. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/models.py.j2 +119 -0
  144. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/scheduled_task_manager.py.j2 +273 -0
  145. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/task_monitor.py.j2 +189 -0
  146. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/shared/__init__.py +15 -0
  147. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/shared/models.py +26 -0
  148. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/__init__.py +52 -0
  149. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/alerts.py +94 -0
  150. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/backup.py.j2 +119 -0
  151. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/health.py.j2 +1333 -0
  152. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/models.py +243 -0
  153. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/ui.py +52 -0
  154. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto-dark.png +0 -0
  155. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto-square-backup.png +0 -0
  156. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto.png +0 -0
  157. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.dockerignore +71 -0
  158. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.env.example.j2 +64 -0
  159. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.gitignore +131 -0
  160. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/Dockerfile +53 -0
  161. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/Makefile +211 -0
  162. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/README.md.j2 +172 -0
  163. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/docker-compose.yml.j2 +78 -0
  164. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/mkdocs.yml.j2 +62 -0
  165. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/pyproject.toml.j2 +120 -0
  166. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/uv.lock +1673 -0
  167. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docker-compose.yml.j2 +200 -0
  168. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/api.md +191 -0
  169. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/components/scheduler.md +0 -0
  170. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/components/scheduler.md.j2 +621 -0
  171. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/development.md +215 -0
  172. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/health.md +240 -0
  173. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/javascripts/mermaid-config.js +62 -0
  174. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/stylesheets/mermaid.css +95 -0
  175. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/mkdocs.yml.j2 +62 -0
  176. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/pyproject.toml.j2 +131 -0
  177. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/entrypoint.sh +87 -0
  178. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/entrypoint.sh.j2 +93 -0
  179. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/gen_docs.py +16 -0
  180. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/__init__.py +1 -0
  181. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_auth_endpoints.py.j2 +307 -0
  182. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_health_endpoints.py.j2 +262 -0
  183. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_scheduler_endpoints.py.j2 +214 -0
  184. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_worker_endpoints.py.j2 +165 -0
  185. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/cli/test_ai_rendering.py +427 -0
  186. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/cli/test_conversation_memory.py +465 -0
  187. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/components/test_scheduler.py +43 -0
  188. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/conftest.py.j2 +195 -0
  189. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/__init__.py +1 -0
  190. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/__init__.py +1 -0
  191. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/conftest.py +78 -0
  192. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_health.py +157 -0
  193. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_models.py +164 -0
  194. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_service.py +198 -0
  195. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_auth_integration.py.j2 +528 -0
  196. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_component_integration.py.j2 +387 -0
  197. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_conversation_persistence.py +342 -0
  198. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_health_logic.py.j2 +663 -0
  199. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_load_test_models.py +619 -0
  200. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_load_test_service.py +603 -0
  201. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_middleware_inspector.py.j2 +248 -0
  202. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_scheduled_task_manager.py.j2 +292 -0
  203. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_system_service.py +98 -0
  204. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_worker_health_registration.py.j2 +257 -0
  205. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/test_core.py +49 -0
  206. aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/uv.lock +1673 -0
  207. aegis/templates/copier-aegis-project/{{ project_slug }}/.copier-answers.yml.jinja +21 -0
  208. aegis/templates/copier-aegis-project/{{ project_slug }}/.dockerignore +71 -0
  209. aegis/templates/copier-aegis-project/{{ project_slug }}/.env.example.jinja +130 -0
  210. aegis/templates/copier-aegis-project/{{ project_slug }}/.gitignore +131 -0
  211. aegis/templates/copier-aegis-project/{{ project_slug }}/Dockerfile +53 -0
  212. aegis/templates/copier-aegis-project/{{ project_slug }}/Makefile.jinja +236 -0
  213. aegis/templates/copier-aegis-project/{{ project_slug }}/README.md.jinja +196 -0
  214. aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/alembic.ini.jinja +111 -0
  215. aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/env.py.jinja +91 -0
  216. aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/script.py.mako +25 -0
  217. aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/versions/001_initial_auth.py.jinja +51 -0
  218. aegis/templates/copier-aegis-project/{{ project_slug }}/app/__init__.py.jinja +5 -0
  219. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/__init__.py.jinja +6 -0
  220. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/ai.py.jinja +700 -0
  221. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/ai_rendering.py +360 -0
  222. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/auth.py.jinja +253 -0
  223. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/health.py.jinja +419 -0
  224. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/load_test.py.jinja +656 -0
  225. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/main.py.jinja +65 -0
  226. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/marko_terminal_renderer.py +489 -0
  227. aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/tasks.py.jinja +328 -0
  228. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/__init__.py +0 -0
  229. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/__init__.py +0 -0
  230. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/ai/__init__.py +8 -0
  231. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/ai/router.py +329 -0
  232. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/auth/__init__.py +1 -0
  233. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/auth/router.py +64 -0
  234. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/deps.py +58 -0
  235. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/health.py.jinja +163 -0
  236. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/models.py.jinja +280 -0
  237. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/routing.py.jinja +32 -0
  238. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/scheduler.py.jinja +121 -0
  239. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/worker.py.jinja +478 -0
  240. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/hooks.py +144 -0
  241. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/main.py +31 -0
  242. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/middleware/__init__.py +1 -0
  243. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/middleware/cors.py +20 -0
  244. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/shutdown/__init__.py +1 -0
  245. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/shutdown/cleanup.py +14 -0
  246. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/__init__.py +1 -0
  247. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/component_health.py.jinja +418 -0
  248. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/database_init.py.jinja +83 -0
  249. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/__init__.py +5 -0
  250. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/__init__.py +27 -0
  251. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/table.py +78 -0
  252. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/text.py +142 -0
  253. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/__init__.py.jinja +47 -0
  254. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/ai_card.py +287 -0
  255. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/auth_card.py +198 -0
  256. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/base_card.py +256 -0
  257. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/card_factory.py +227 -0
  258. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/card_utils.py +333 -0
  259. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/database_card.py +420 -0
  260. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/fastapi_card.py +328 -0
  261. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/flet_card.py +267 -0
  262. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/redis_card.py +322 -0
  263. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/scheduler_card.py +352 -0
  264. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/services_card.py +233 -0
  265. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/worker_card.py +684 -0
  266. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/main.py.jinja +653 -0
  267. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/theme.py +48 -0
  268. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/scheduler/__init__.py +1 -0
  269. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/scheduler/main.py.jinja +156 -0
  270. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/CLAUDE.md.jinja +213 -0
  271. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/__init__.py +6 -0
  272. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/constants.py.jinja +30 -0
  273. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/pools.py +97 -0
  274. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/__init__.py +1 -0
  275. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/load_test.py +55 -0
  276. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/media.py +49 -0
  277. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/system.py +44 -0
  278. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/registry.py +139 -0
  279. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/__init__.py +120 -0
  280. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/load_tasks.py +507 -0
  281. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/simple_system_tasks.py +33 -0
  282. aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/system_tasks.py +281 -0
  283. aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/config.py.jinja +178 -0
  284. aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/constants.py +58 -0
  285. aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/db.py.jinja +176 -0
  286. aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/log.py +92 -0
  287. aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/security.py +62 -0
  288. aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/__init__.py +1 -0
  289. aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/scheduler.py.jinja +21 -0
  290. aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/webserver.py +39 -0
  291. aegis/templates/copier-aegis-project/{{ project_slug }}/app/integrations/__init__.py +0 -0
  292. aegis/templates/copier-aegis-project/{{ project_slug }}/app/integrations/main.py +61 -0
  293. aegis/templates/copier-aegis-project/{{ project_slug }}/app/models/__init__.py +1 -0
  294. aegis/templates/copier-aegis-project/{{ project_slug }}/app/models/user.py +44 -0
  295. aegis/templates/copier-aegis-project/{{ project_slug }}/app/py.typed +0 -0
  296. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/__init__.py +1 -0
  297. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/__init__.py +8 -0
  298. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/config.py +130 -0
  299. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/conversation.py +213 -0
  300. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/health.py +96 -0
  301. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/models.py +229 -0
  302. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/providers.py.jinja +370 -0
  303. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/service.py +387 -0
  304. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/__init__.py +1 -0
  305. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/auth_service.py +40 -0
  306. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/health.py +162 -0
  307. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/user_service.py +82 -0
  308. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/middleware_inspector.py.jinja +223 -0
  309. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/models.py.jinja +70 -0
  310. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/route_inspector.py.jinja +155 -0
  311. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/load_test.py +678 -0
  312. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/load_test_models.py +265 -0
  313. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/__init__.py.jinja +21 -0
  314. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/models.py.jinja +119 -0
  315. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/scheduled_task_manager.py.jinja +273 -0
  316. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/task_monitor.py.jinja +189 -0
  317. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/shared/__init__.py +15 -0
  318. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/shared/models.py +26 -0
  319. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/__init__.py +52 -0
  320. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/alerts.py +94 -0
  321. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/backup.py.jinja +119 -0
  322. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/health.py.jinja +1333 -0
  323. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/models.py +243 -0
  324. aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/ui.py +52 -0
  325. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57223!aegis-manifesto.png +0 -0
  326. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57224!aegis-manifesto-dark.png +0 -0
  327. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57225!aegis-manifesto-square-backup.png +0 -0
  328. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57533!aegis-manifesto.png +0 -0
  329. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57534!aegis-manifesto-dark.png +0 -0
  330. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57538!aegis-manifesto-square-backup.png +0 -0
  331. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57897!aegis-manifesto.png +0 -0
  332. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57898!aegis-manifesto-dark.png +0 -0
  333. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57904!aegis-manifesto-square-backup.png +0 -0
  334. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58315!aegis-manifesto.png +0 -0
  335. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58316!aegis-manifesto-dark.png +0 -0
  336. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58324!aegis-manifesto-square-backup.png +0 -0
  337. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58837!aegis-manifesto.png +0 -0
  338. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58838!aegis-manifesto-dark.png +0 -0
  339. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58849!aegis-manifesto-square-backup.png +0 -0
  340. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto-dark.png +0 -0
  341. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto-square-backup.png +0 -0
  342. aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto.png +0 -0
  343. aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/.env.example.jinja +64 -0
  344. aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/README.md.jinja +172 -0
  345. aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/docker-compose.yml.jinja +78 -0
  346. aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/mkdocs.yml.jinja +62 -0
  347. aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/pyproject.toml.jinja +120 -0
  348. aegis/templates/copier-aegis-project/{{ project_slug }}/docker-compose.yml.jinja +200 -0
  349. aegis/templates/copier-aegis-project/{{ project_slug }}/docs/api.md.jinja +191 -0
  350. aegis/templates/copier-aegis-project/{{ project_slug }}/docs/components/scheduler.md +0 -0
  351. aegis/templates/copier-aegis-project/{{ project_slug }}/docs/components/scheduler.md.jinja +621 -0
  352. aegis/templates/copier-aegis-project/{{ project_slug }}/docs/development.md.jinja +215 -0
  353. aegis/templates/copier-aegis-project/{{ project_slug }}/docs/health.md.jinja +240 -0
  354. aegis/templates/copier-aegis-project/{{ project_slug }}/docs/javascripts/mermaid-config.js +62 -0
  355. aegis/templates/copier-aegis-project/{{ project_slug }}/docs/stylesheets/mermaid.css +95 -0
  356. aegis/templates/copier-aegis-project/{{ project_slug }}/mkdocs.yml.jinja +62 -0
  357. aegis/templates/copier-aegis-project/{{ project_slug }}/pyproject.toml.jinja +131 -0
  358. aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/entrypoint.sh +87 -0
  359. aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/entrypoint.sh.jinja +93 -0
  360. aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/gen_docs.py +16 -0
  361. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/__init__.py +1 -0
  362. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_auth_endpoints.py.jinja +307 -0
  363. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_health_endpoints.py.jinja +262 -0
  364. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_scheduler_endpoints.py.jinja +214 -0
  365. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_worker_endpoints.py.jinja +165 -0
  366. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/cli/test_ai_rendering.py +427 -0
  367. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/cli/test_conversation_memory.py +465 -0
  368. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/components/test_scheduler.py +43 -0
  369. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/conftest.py.jinja +195 -0
  370. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/__init__.py +1 -0
  371. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/__init__.py +1 -0
  372. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/conftest.py +78 -0
  373. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_health.py +157 -0
  374. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_models.py +164 -0
  375. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_service.py +198 -0
  376. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_auth_integration.py.jinja +528 -0
  377. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_component_integration.py.jinja +387 -0
  378. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_conversation_persistence.py +342 -0
  379. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_health_logic.py.jinja +663 -0
  380. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_load_test_models.py +619 -0
  381. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_load_test_service.py +603 -0
  382. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_middleware_inspector.py.jinja +248 -0
  383. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_scheduled_task_manager.py.jinja +292 -0
  384. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_system_service.py +98 -0
  385. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_worker_health_registration.py.jinja +257 -0
  386. aegis/templates/copier-aegis-project/{{ project_slug }}/tests/test_core.py +49 -0
  387. aegis/templates/copier-aegis-project/{{ project_slug }}/uv.lock +1673 -0
  388. aegis_stack-0.2.0rc2.dist-info/METADATA +165 -0
  389. aegis_stack-0.2.0rc2.dist-info/RECORD +392 -0
  390. aegis_stack-0.2.0rc2.dist-info/WHEEL +4 -0
  391. aegis_stack-0.2.0rc2.dist-info/entry_points.txt +3 -0
  392. aegis_stack-0.2.0rc2.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,507 @@
1
+ """
2
+ Lightweight worker tasks for load testing.
3
+
4
+ These tasks are designed to be spawned in large numbers to test queue throughput
5
+ and worker performance. Each task does minimal work to focus on testing the
6
+ infrastructure rather than computational complexity.
7
+ """
8
+
9
+ import asyncio
10
+ import random
11
+ from datetime import datetime
12
+ from typing import Any, cast
13
+
14
+ from app.core.log import logger
15
+
16
+
17
+ async def cpu_intensive_task(ctx: dict[str, Any], **kwargs: Any) -> dict[str, Any]:
18
+ """
19
+ CPU-intensive load testing task.
20
+
21
+ Performs realistic computational work including hash calculations, sorting,
22
+ and mathematical operations to test worker CPU processing capabilities.
23
+ Designed to actually use CPU cycles and test computational throughput.
24
+
25
+ Returns:
26
+ Task completion data with CPU-specific metrics and verification data
27
+ """
28
+ start_time = datetime.now()
29
+ task_id = ctx.get("job_id", "unknown")
30
+
31
+ # CPU work 1: Fibonacci calculation (larger numbers for real work)
32
+ n = random.randint(500, 1500) # Much larger range for actual CPU work
33
+ a, b = 0, 1
34
+ operations_count = 0
35
+
36
+ for _i in range(n):
37
+ a, b = b, a + b
38
+ operations_count += 1
39
+
40
+ # CPU work 2: Sorting random data (CPU intensive)
41
+ data_size = random.randint(1000, 3000)
42
+ random_data = [random.randint(1, 10000) for _ in range(data_size)]
43
+ sorted_data = sorted(random_data)
44
+ operations_count += data_size # Approximate operations for sorting
45
+
46
+ # CPU work 3: Hash calculations (CPU intensive)
47
+ import hashlib
48
+
49
+ hash_operations = random.randint(50, 150)
50
+ hash_results = []
51
+ for i in range(hash_operations):
52
+ data_to_hash = f"load_test_data_{i}_{random.randint(1, 100000)}"
53
+ hash_result = hashlib.sha256(data_to_hash.encode()).hexdigest()
54
+ hash_results.append(hash_result[:8]) # Store first 8 chars
55
+ operations_count += 1
56
+
57
+ # CPU work 4: Mathematical computations
58
+ math_iterations = random.randint(5000, 15000)
59
+ math_result = 0
60
+ for i in range(math_iterations):
61
+ # More complex math operations
62
+ math_result += (i**2 + i**0.5) * 0.1
63
+ operations_count += 1
64
+
65
+ # CPU work 5: Prime number generation (CPU bound)
66
+ prime_start = random.randint(1000, 2000)
67
+ primes_found: list[int] = []
68
+ num = prime_start
69
+ while len(primes_found) < 20: # Find 20 primes
70
+ is_prime = True
71
+ if num > 1:
72
+ for i in range(2, int(num**0.5) + 1):
73
+ operations_count += 1
74
+ if num % i == 0:
75
+ is_prime = False
76
+ break
77
+ else:
78
+ is_prime = False
79
+
80
+ if is_prime:
81
+ primes_found.append(num)
82
+ num += 1
83
+
84
+ # CPU work 6: Simulate encoding/image processing (realistic CPU-heavy work)
85
+ encoding_operations = 0
86
+ # Simulate image/video encoding by doing intensive matrix operations
87
+ for _frame in range(random.randint(10, 30)): # Process "frames"
88
+ # Simulate encoding a frame with matrix multiplication
89
+ matrix_size = random.randint(50, 100)
90
+ matrix_a = [
91
+ [random.random() for _ in range(matrix_size)] for _ in range(matrix_size)
92
+ ]
93
+ matrix_b = [
94
+ [random.random() for _ in range(matrix_size)] for _ in range(matrix_size)
95
+ ]
96
+
97
+ # Matrix multiplication (very CPU intensive)
98
+ result_matrix = [[0.0 for _ in range(matrix_size)] for _ in range(matrix_size)]
99
+ for i in range(matrix_size):
100
+ for j in range(matrix_size):
101
+ for k in range(matrix_size):
102
+ result_matrix[i][j] += matrix_a[i][k] * matrix_b[k][j]
103
+ encoding_operations += 1
104
+
105
+ # WARNING: This blocks the entire async event loop!
106
+ # In real systems, this would prevent other async tasks from running
107
+ event_loop_warning = "CPU work blocks async event loop - other tasks must wait!"
108
+
109
+ end_time = datetime.now()
110
+ duration_ms = (end_time - start_time).total_seconds() * 1000
111
+
112
+ return {
113
+ "task_type": "cpu_intensive",
114
+ "task_id": task_id,
115
+ # CPU work proof
116
+ "fibonacci_n": n,
117
+ "fibonacci_result": (str(b)[:10] + "..." if len(str(b)) > 10 else str(b)),
118
+ "sorted_data_size": len(sorted_data),
119
+ "hash_operations": hash_operations,
120
+ "hash_sample": hash_results[:3], # First 3 hashes as proof
121
+ "math_iterations": math_iterations,
122
+ "math_result": round(math_result, 2),
123
+ "primes_found": primes_found,
124
+ "encoding_operations": encoding_operations,
125
+ "total_cpu_operations": operations_count + encoding_operations,
126
+ # Performance metrics
127
+ "duration_ms": round(duration_ms, 2),
128
+ "operations_per_ms": round(
129
+ (operations_count + encoding_operations) / max(duration_ms, 0.001), 2
130
+ ),
131
+ "cpu_intensive_score": round(
132
+ (operations_count + encoding_operations) / max(duration_ms / 1000, 0.001), 0
133
+ ),
134
+ "start_time": start_time.isoformat(),
135
+ "end_time": end_time.isoformat(),
136
+ # Async event loop impact
137
+ "async_event_loop_blocked_ms": round(duration_ms, 2),
138
+ "event_loop_warning": event_loop_warning,
139
+ "concurrency_impact": ("HIGH - Blocks entire event loop during execution"),
140
+ # Verification signature
141
+ "work_type": "CPU_COMPUTATION_WITH_ENCODING",
142
+ "verification": (
143
+ f"fib({n}), sort({data_size}), hash({hash_operations}), "
144
+ f"math({math_iterations}), primes({len(primes_found)}), "
145
+ f"encoding({encoding_operations}ops)"
146
+ ),
147
+ "status": "completed",
148
+ }
149
+
150
+
151
+ async def io_simulation_task(ctx: dict[str, Any], **kwargs: Any) -> dict[str, Any]:
152
+ """
153
+ I/O-intensive load testing task optimized for high throughput.
154
+
155
+ Simulates realistic async I/O patterns with minimal delays to avoid queue
156
+ saturation while still demonstrating async concurrency benefits. Focuses on
157
+ async pattern demonstration rather than realistic I/O timing.
158
+
159
+ Returns:
160
+ Task completion data with I/O-specific metrics and concurrency analysis
161
+ """
162
+ start_time = datetime.now()
163
+ task_id = ctx.get("job_id", "unknown")
164
+
165
+ # Ultra-lightweight I/O simulation to prevent queue saturation
166
+ # Focus on async patterns with minimal actual delays
167
+
168
+ async def simulate_database_read(read_id: int) -> dict[str, Any]:
169
+ """Simulate a database read with ultra-minimal delay."""
170
+ op_start = datetime.now()
171
+ # Extremely short delay to show async pattern without queue buildup
172
+ await asyncio.sleep(0.001) # 1ms max
173
+ op_end = datetime.now()
174
+ return {
175
+ "operation_id": read_id,
176
+ "operation_type": "database_read",
177
+ "table": f"users_{read_id}",
178
+ "simulated_delay_ms": 1,
179
+ "actual_duration_ms": round((op_end - op_start).total_seconds() * 1000, 3),
180
+ "rows_returned": random.randint(10, 100),
181
+ }
182
+
183
+ async def simulate_api_call(api_id: int) -> dict[str, Any]:
184
+ """Simulate an external API call with ultra-minimal delay."""
185
+ op_start = datetime.now()
186
+ # Minimal async yield to demonstrate concurrency
187
+ await asyncio.sleep(0.001) # 1ms max
188
+ op_end = datetime.now()
189
+ return {
190
+ "operation_id": api_id,
191
+ "operation_type": "api_call",
192
+ "endpoint": f"/api/data/{api_id}",
193
+ "simulated_delay_ms": 1,
194
+ "actual_duration_ms": round((op_end - op_start).total_seconds() * 1000, 3),
195
+ "status_code": random.choice([200, 200, 200, 201, 404]),
196
+ }
197
+
198
+ async def simulate_cache_read(cache_id: int) -> dict[str, Any]:
199
+ """Simulate a cache read operation (very fast)."""
200
+ op_start = datetime.now()
201
+ # Cache should be fastest - just yield control
202
+ await asyncio.sleep(0.0005) # 0.5ms max
203
+ op_end = datetime.now()
204
+ return {
205
+ "operation_id": cache_id,
206
+ "operation_type": "cache_read",
207
+ "cache_key": f"user_session_{cache_id}",
208
+ "simulated_delay_ms": 0.5,
209
+ "actual_duration_ms": round((op_end - op_start).total_seconds() * 1000, 3),
210
+ "cache_hit": random.choice([True, True, True, False]),
211
+ }
212
+
213
+ # Fewer concurrent operations to reduce total time
214
+ db_tasks = [simulate_database_read(i) for i in range(2)]
215
+ api_tasks = [simulate_api_call(i) for i in range(2)]
216
+ cache_tasks = [simulate_cache_read(i) for i in range(3)]
217
+
218
+ # Execute all I/O operations concurrently (key async benefit)
219
+ concurrent_ops_start = datetime.now()
220
+ all_operations = await asyncio.gather(*db_tasks, *api_tasks, *cache_tasks)
221
+ concurrent_ops_end = datetime.now()
222
+ concurrent_duration = (
223
+ concurrent_ops_end - concurrent_ops_start
224
+ ).total_seconds() * 1000
225
+
226
+ # Light data processing (realistic for I/O workloads)
227
+ processing_start = datetime.now()
228
+
229
+ # Aggregate results (typical I/O task post-processing)
230
+ success_count = 0
231
+ error_count = 0
232
+ total_rows = 0
233
+ cache_hits = 0
234
+
235
+ for op in all_operations:
236
+ if op["operation_type"] == "database_read":
237
+ total_rows += op["rows_returned"]
238
+ success_count += 1
239
+ elif op["operation_type"] == "api_call":
240
+ if op["status_code"] in [200, 201]:
241
+ success_count += 1
242
+ else:
243
+ error_count += 1
244
+ elif op["operation_type"] == "cache_read":
245
+ if op["cache_hit"]:
246
+ cache_hits += 1
247
+ success_count += 1
248
+
249
+ processing_end = datetime.now()
250
+ processing_duration = (processing_end - processing_start).total_seconds() * 1000
251
+
252
+ end_time = datetime.now()
253
+ total_duration_ms = (end_time - start_time).total_seconds() * 1000
254
+
255
+ # Calculate async concurrency benefits
256
+ total_simulated_delay = sum(op["simulated_delay_ms"] for op in all_operations)
257
+ actual_concurrent_time = concurrent_duration
258
+ concurrency_factor = total_simulated_delay / max(actual_concurrent_time, 0.001)
259
+ time_saved_ms = total_simulated_delay - actual_concurrent_time
260
+
261
+ # Categorize operations by type
262
+ db_operations = [
263
+ op for op in all_operations if op["operation_type"] == "database_read"
264
+ ]
265
+ api_operations = [op for op in all_operations if op["operation_type"] == "api_call"]
266
+ cache_operations = [
267
+ op for op in all_operations if op["operation_type"] == "cache_read"
268
+ ]
269
+
270
+ return {
271
+ "task_type": "io_simulation",
272
+ "task_id": task_id,
273
+ # I/O work proof and results
274
+ "database_operations": len(db_operations),
275
+ "api_operations": len(api_operations),
276
+ "cache_operations": len(cache_operations),
277
+ "total_concurrent_operations": len(all_operations),
278
+ "processing_results": {
279
+ "total_rows_processed": total_rows,
280
+ "success_operations": success_count,
281
+ "error_operations": error_count,
282
+ "cache_hits": cache_hits,
283
+ },
284
+ # Performance and concurrency metrics
285
+ "total_duration_ms": round(total_duration_ms, 3),
286
+ "concurrent_io_duration_ms": round(concurrent_duration, 3),
287
+ "processing_duration_ms": round(processing_duration, 3),
288
+ "total_simulated_delay_ms": total_simulated_delay,
289
+ "concurrency_time_saved_ms": round(time_saved_ms, 3),
290
+ "concurrency_factor": round(concurrency_factor, 2),
291
+ "io_throughput_ops_per_sec": round(
292
+ len(all_operations) / max(total_duration_ms / 1000, 0.001), 1
293
+ ),
294
+ "start_time": start_time.isoformat(),
295
+ "end_time": end_time.isoformat(),
296
+ # Async pattern demonstration
297
+ "async_pattern_demo": {
298
+ "sequential_would_take_ms": total_simulated_delay,
299
+ "concurrent_actual_ms": round(concurrent_duration, 3),
300
+ "efficiency_improvement": (
301
+ f"{round((time_saved_ms / total_simulated_delay) * 100, 1)}%"
302
+ if total_simulated_delay > 0
303
+ else "0%"
304
+ ),
305
+ },
306
+ # Verification signature
307
+ "work_type": "OPTIMIZED_ASYNC_IO",
308
+ "verification": (
309
+ f"concurrent({len(all_operations)}ops, "
310
+ f"{total_simulated_delay}ms→{round(concurrent_duration, 1)}ms, "
311
+ f"{round(concurrency_factor, 1)}x speedup)"
312
+ ),
313
+ "status": "completed",
314
+ }
315
+
316
+
317
+ async def memory_operations_task(ctx: dict[str, Any], **kwargs: Any) -> dict[str, Any]:
318
+ """
319
+ Memory-intensive load testing task with allocation patterns.
320
+
321
+ Performs realistic memory allocation, manipulation, and deallocation
322
+ patterns to test worker memory handling, garbage collection impact,
323
+ and memory bandwidth utilization.
324
+
325
+ Returns:
326
+ Task completion data with memory-specific metrics and allocation details
327
+ """
328
+ start_time = datetime.now()
329
+ task_id = ctx.get("job_id", "unknown")
330
+
331
+ # Memory allocation pattern 1: Sequential data structures
332
+ list_size = random.randint(500, 2000) # Larger for better measurement
333
+ data_list = list(range(list_size))
334
+
335
+ # Memory allocation pattern 2: Dictionary with string values
336
+ dict_size = list_size // 4
337
+ data_dict = {i: f"memory_test_value_{i}_{'x' * 10}" for i in range(dict_size)}
338
+
339
+ # Memory allocation pattern 3: Nested structures
340
+ nested_data: list[dict[str, Any]] = []
341
+ for i in range(50):
342
+ nested_item = {
343
+ "id": i,
344
+ "data": [j * 2 for j in range(20)],
345
+ "metadata": {"created": datetime.now().isoformat(), "size": 20},
346
+ }
347
+ nested_data.append(nested_item)
348
+
349
+ # Memory operations: processing that causes memory access patterns
350
+ # List operations
351
+ list_sum = sum(data_list)
352
+ list_squares = [x**2 for x in data_list[:100]]
353
+ max_value = max(data_list) if data_list else 0
354
+ min_value = min(data_list) if data_list else 0
355
+
356
+ # Dictionary operations
357
+ dict_keys_count = len(data_dict)
358
+ dict_values_total_len = sum(len(v) for v in data_dict.values())
359
+
360
+ # Nested data processing
361
+ nested_sum = sum(sum(cast(list[int], item["data"])) for item in nested_data)
362
+ nested_items_count = len(nested_data)
363
+
364
+ # Memory churn: create and destroy temporary objects
365
+ temp_objects = []
366
+ for i in range(100):
367
+ temp_obj = {"temp_id": i, "temp_data": list(range(10))}
368
+ temp_objects.append(temp_obj)
369
+
370
+ # Process temp objects then clean up
371
+ temp_sum = sum(sum(cast(list[int], obj["temp_data"])) for obj in temp_objects)
372
+ del temp_objects # Explicit cleanup
373
+
374
+ # Calculate memory usage estimates (approximate)
375
+ estimated_list_bytes = list_size * 8 # Rough estimate for integers
376
+ estimated_dict_bytes = dict_size * (8 + 30)
377
+ estimated_nested_bytes = len(nested_data) * 200
378
+ total_estimated_bytes = (
379
+ estimated_list_bytes + estimated_dict_bytes + estimated_nested_bytes
380
+ )
381
+
382
+ # Clean up main data structures
383
+ del data_list
384
+ del data_dict
385
+ del nested_data
386
+
387
+ end_time = datetime.now()
388
+ duration_ms = (end_time - start_time).total_seconds() * 1000
389
+
390
+ return {
391
+ "task_type": "memory_operations",
392
+ "task_id": task_id,
393
+ # Memory work proof
394
+ "list_allocation_size": list_size,
395
+ "dict_allocation_size": dict_size,
396
+ "nested_structures_count": nested_items_count,
397
+ "temp_objects_processed": 100,
398
+ # Memory operation results
399
+ "list_sum": list_sum,
400
+ "list_squares_sample": len(list_squares),
401
+ "max_value": max_value,
402
+ "min_value": min_value,
403
+ "dict_keys_count": dict_keys_count,
404
+ "dict_values_total_length": dict_values_total_len,
405
+ "nested_sum": nested_sum,
406
+ "temp_sum": temp_sum,
407
+ # Memory metrics
408
+ "estimated_peak_memory_bytes": total_estimated_bytes,
409
+ "estimated_peak_memory_mb": round(total_estimated_bytes / (1024 * 1024), 2),
410
+ "memory_operations_count": 8, # Major allocation/processing operations
411
+ "duration_ms": round(duration_ms, 2),
412
+ "memory_throughput_mb_per_sec": round(
413
+ (total_estimated_bytes / (1024 * 1024)) / max(duration_ms / 1000, 0.001), 2
414
+ ),
415
+ "start_time": start_time.isoformat(),
416
+ "end_time": end_time.isoformat(),
417
+ # Verification signature
418
+ "work_type": "MEMORY_ALLOCATION",
419
+ "verification": (
420
+ f"list({list_size}) + dict({dict_size}) + "
421
+ f"nested({nested_items_count}) + temp(100) = {total_estimated_bytes}bytes"
422
+ ),
423
+ "status": "completed",
424
+ }
425
+
426
+
427
+ async def failure_testing_task(ctx: dict[str, Any], **kwargs: Any) -> dict[str, Any]:
428
+ """
429
+ Failure testing task for error handling validation.
430
+
431
+ Randomly fails ~20% of the time to test worker resilience,
432
+ error handling, and failure recovery patterns. When successful,
433
+ provides minimal work to focus on failure testing.
434
+
435
+ Returns:
436
+ Task completion data with failure testing metrics
437
+ """
438
+ start_time = datetime.now()
439
+ task_id = ctx.get("job_id", "unknown")
440
+
441
+ # Random failure probability (20%)
442
+ failure_roll = random.random()
443
+ failure_threshold = 0.2
444
+
445
+ # Generate different types of failures for testing
446
+ if failure_roll < failure_threshold:
447
+ failure_types = [
448
+ "simulated_network_timeout",
449
+ "simulated_database_error",
450
+ "simulated_validation_error",
451
+ "simulated_resource_exhaustion",
452
+ "simulated_permission_error",
453
+ ]
454
+
455
+ failure_type = random.choice(failure_types)
456
+ error_message = (
457
+ f"Simulated {failure_type} for resilience testing "
458
+ f"(task {task_id}, roll={failure_roll:.3f})"
459
+ )
460
+
461
+ # Log failure details before raising
462
+ logger.warning(f"🧪 Intentional test failure: {error_message}")
463
+
464
+ raise Exception(error_message)
465
+
466
+ # Success path: minimal work with timing
467
+ work_type = random.choice(["quick_sleep", "light_calculation", "simple_operation"])
468
+
469
+ if work_type == "quick_sleep":
470
+ delay_ms = random.randint(5, 15)
471
+ await asyncio.sleep(delay_ms / 1000)
472
+ work_detail = f"sleep({delay_ms}ms)"
473
+
474
+ elif work_type == "light_calculation":
475
+ n = random.randint(5, 15)
476
+ result = sum(i**2 for i in range(n))
477
+ work_detail = f"sum_squares({n})={result}"
478
+
479
+ else: # simple_operation
480
+ data = list(range(10))
481
+ result = len(data) + sum(data)
482
+ work_detail = f"list_ops({len(data)})={result}"
483
+
484
+ end_time = datetime.now()
485
+ duration_ms = (end_time - start_time).total_seconds() * 1000
486
+
487
+ return {
488
+ "task_type": "failure_testing",
489
+ "task_id": task_id,
490
+ # Failure testing proof
491
+ "failure_roll": round(failure_roll, 3),
492
+ "failure_threshold": failure_threshold,
493
+ "would_have_failed": failure_roll < failure_threshold,
494
+ "success_work_type": work_type,
495
+ "work_detail": work_detail,
496
+ # Performance metrics
497
+ "duration_ms": round(duration_ms, 2),
498
+ "start_time": start_time.isoformat(),
499
+ "end_time": end_time.isoformat(),
500
+ # Verification signature
501
+ "work_type": "FAILURE_TESTING",
502
+ "verification": (
503
+ f"roll={failure_roll:.3f} < {failure_threshold} = "
504
+ f"{failure_roll < failure_threshold}, work={work_detail}"
505
+ ),
506
+ "status": "completed",
507
+ }
@@ -0,0 +1,33 @@
1
+ """Simple system maintenance tasks for the system worker."""
2
+
3
+ import asyncio
4
+ from datetime import UTC, datetime
5
+ from typing import Any
6
+
7
+ from app.core.log import logger
8
+
9
+
10
+ async def system_health_check(ctx: dict[str, Any]) -> dict[str, str]:
11
+ """Simple system health check task."""
12
+ logger.info("🩺 Running system health check task")
13
+
14
+ # Simple health check - just return current timestamp
15
+ return {
16
+ "status": "healthy",
17
+ "timestamp": datetime.now(UTC).isoformat(),
18
+ "task": "system_health_check",
19
+ }
20
+
21
+
22
+ async def cleanup_temp_files(ctx: dict[str, Any]) -> dict[str, str]:
23
+ """Simple temp file cleanup task placeholder."""
24
+ logger.info("🧹 Running temp file cleanup task")
25
+
26
+ # Placeholder for actual cleanup logic
27
+ await asyncio.sleep(0.1) # Simulate some work
28
+
29
+ return {
30
+ "status": "completed",
31
+ "timestamp": datetime.now(UTC).isoformat(),
32
+ "task": "cleanup_temp_files",
33
+ }