aury-boot 0.0.19__tar.gz → 0.0.21__tar.gz
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.
- {aury_boot-0.0.19 → aury_boot-0.0.21}/PKG-INFO +3 -8
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/_version.py +2 -2
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/app/base.py +8 -3
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/config/settings.py +1 -2
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/errors/handlers.py +23 -8
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/pkg.py +3 -3
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/08-scheduler.md.tpl +77 -24
- aury_boot-0.0.21/aury/boot/commands/templates/project/modules/schedules.py.tpl +38 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/scheduler/manager.py +198 -37
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/tasks/manager.py +37 -17
- {aury_boot-0.0.19 → aury_boot-0.0.21}/pyproject.toml +2 -7
- aury_boot-0.0.19/aury/boot/commands/templates/project/modules/schedules.py.tpl +0 -21
- {aury_boot-0.0.19 → aury_boot-0.0.21}/.gitignore +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/README.md +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/adapter/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/adapter/base.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/adapter/config.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/adapter/decorators.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/adapter/exceptions.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/adapter/http.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/app/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/app/components.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/app/middlewares.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/app/startup.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/config/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/config/multi_instance.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/constants/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/constants/components.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/constants/scheduler.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/constants/service.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/errors/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/errors/chain.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/errors/codes.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/errors/exceptions.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/errors/response.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/interfaces/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/interfaces/egress.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/interfaces/ingress.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/middleware/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/middleware/logging.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/migrations/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/migrations/manager.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/migrations/setup.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/rpc/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/rpc/base.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/rpc/client.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/rpc/discovery.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/scheduler/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/scheduler/runner.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/application/server/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/add.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/app.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/config.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/docker.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/docs.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/generate.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/init.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/migrate/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/migrate/app.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/migrate/commands.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/scheduler.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/server/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/server/app.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/generate/api.py.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/generate/model.py.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/generate/repository.py.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/generate/schema.py.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/generate/service.py.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/AGENTS.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/README.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/admin_console_init.py.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/00-overview.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/01-model.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/02-repository.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/03-service.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/04-schema.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/05-api.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/06-exception.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/07-cache.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/09-tasks.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/10-storage.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/11-logging.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/12-admin.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/13-channel.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/14-mq.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/15-events.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/16-adapter.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/aury_docs/99-cli.md.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/config.py.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/conftest.py.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/env_templates/_header.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/env_templates/admin.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/env_templates/cache.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/env_templates/database.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/env_templates/log.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/env_templates/messaging.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/env_templates/rpc.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/env_templates/scheduler.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/env_templates/service.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/env_templates/storage.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/env_templates/third_party.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/gitignore.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/main.py.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/modules/api.py.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/modules/exceptions.py.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/templates/project/modules/tasks.py.tpl +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/commands/worker.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/common/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/common/exceptions/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/common/i18n/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/common/i18n/translator.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/common/logging/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/common/logging/context.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/common/logging/decorators.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/common/logging/format.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/common/logging/setup.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/contrib/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/contrib/admin_console/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/contrib/admin_console/auth.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/contrib/admin_console/discovery.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/contrib/admin_console/install.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/contrib/admin_console/utils.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/exceptions/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/models/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/models/base.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/models/mixins.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/models/models.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/pagination/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/repository/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/repository/impl.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/repository/interceptors.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/repository/interface.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/repository/query_builder.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/service/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/service/base.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/domain/transaction/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/cache/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/cache/backends.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/cache/base.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/cache/exceptions.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/cache/factory.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/cache/manager.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/channel/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/channel/backends/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/channel/backends/memory.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/channel/backends/redis.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/channel/base.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/channel/manager.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/clients/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/clients/rabbitmq/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/clients/rabbitmq/config.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/clients/rabbitmq/manager.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/clients/redis/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/clients/redis/config.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/clients/redis/manager.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/database/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/database/config.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/database/exceptions.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/database/manager.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/database/query_tools/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/database/strategies/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/di/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/di/container.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/events/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/events/backends/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/events/backends/memory.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/events/backends/rabbitmq.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/events/backends/redis.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/events/base.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/events/manager.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/events/middleware.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/monitoring/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/mq/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/mq/backends/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/mq/backends/rabbitmq.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/mq/backends/redis.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/mq/base.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/mq/manager.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/scheduler/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/scheduler/exceptions.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/storage/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/storage/base.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/storage/exceptions.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/storage/factory.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/tasks/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/tasks/config.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/tasks/constants.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/infrastructure/tasks/exceptions.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/testing/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/testing/base.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/testing/client.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/testing/factory.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/toolkit/__init__.py +0 -0
- {aury_boot-0.0.19 → aury_boot-0.0.21}/aury/boot/toolkit/http/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aury-boot
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.21
|
|
4
4
|
Summary: Aury Boot - 基于 FastAPI 生态的企业级 API 开发框架
|
|
5
5
|
Requires-Python: >=3.13
|
|
6
6
|
Requires-Dist: alembic>=1.17.2
|
|
@@ -24,13 +24,11 @@ Requires-Dist: sqladmin>=0.16.0; extra == 'admin'
|
|
|
24
24
|
Provides-Extra: all
|
|
25
25
|
Requires-Dist: aiomysql>=0.3.2; extra == 'all'
|
|
26
26
|
Requires-Dist: aiosqlite>=0.21.0; extra == 'all'
|
|
27
|
-
Requires-Dist: amqp>=5.3.1; extra == 'all'
|
|
28
27
|
Requires-Dist: apscheduler>=3.11.1; extra == 'all'
|
|
29
28
|
Requires-Dist: asyncpg>=0.31.0; extra == 'all'
|
|
30
29
|
Requires-Dist: aury-sdk-storage[aws]>=0.0.1; extra == 'all'
|
|
31
|
-
Requires-Dist: dramatiq-kombu-broker>=0.2.2; extra == 'all'
|
|
32
30
|
Requires-Dist: dramatiq>=1.18.0; extra == 'all'
|
|
33
|
-
Requires-Dist:
|
|
31
|
+
Requires-Dist: pika>=1.3.2; extra == 'all'
|
|
34
32
|
Requires-Dist: redis>=7.1.0; extra == 'all'
|
|
35
33
|
Provides-Extra: dev
|
|
36
34
|
Requires-Dist: mypy>=1.19.0; extra == 'dev'
|
|
@@ -53,9 +51,7 @@ Requires-Dist: aiosqlite>=0.21.0; extra == 'recommended'
|
|
|
53
51
|
Requires-Dist: apscheduler>=3.11.1; extra == 'recommended'
|
|
54
52
|
Requires-Dist: asyncpg>=0.31.0; extra == 'recommended'
|
|
55
53
|
Requires-Dist: aury-sdk-storage[aws]>=0.0.1; extra == 'recommended'
|
|
56
|
-
Requires-Dist: dramatiq-kombu-broker>=0.2.2; extra == 'recommended'
|
|
57
54
|
Requires-Dist: dramatiq>=1.18.0; extra == 'recommended'
|
|
58
|
-
Requires-Dist: kombu>=5.6.1; extra == 'recommended'
|
|
59
55
|
Requires-Dist: redis>=7.1.0; extra == 'recommended'
|
|
60
56
|
Provides-Extra: redis
|
|
61
57
|
Requires-Dist: redis>=7.1.0; extra == 'redis'
|
|
@@ -66,9 +62,8 @@ Requires-Dist: apscheduler>=3.11.1; extra == 'scheduler'
|
|
|
66
62
|
Provides-Extra: sqlite
|
|
67
63
|
Requires-Dist: aiosqlite>=0.21.0; extra == 'sqlite'
|
|
68
64
|
Provides-Extra: tasks
|
|
69
|
-
Requires-Dist: dramatiq-kombu-broker>=0.2.2; extra == 'tasks'
|
|
70
65
|
Requires-Dist: dramatiq>=1.18.0; extra == 'tasks'
|
|
71
|
-
Requires-Dist:
|
|
66
|
+
Requires-Dist: redis>=7.1.0; extra == 'tasks'
|
|
72
67
|
Description-Content-Type: text/markdown
|
|
73
68
|
|
|
74
69
|
# Aury Boot
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.0.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 0,
|
|
31
|
+
__version__ = version = '0.0.21'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 0, 21)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -11,8 +11,10 @@ from contextlib import asynccontextmanager
|
|
|
11
11
|
import sys
|
|
12
12
|
from typing import Any, ClassVar
|
|
13
13
|
|
|
14
|
-
from fastapi import FastAPI, Request, status
|
|
14
|
+
from fastapi import FastAPI, HTTPException, Request, status
|
|
15
|
+
from fastapi.exceptions import RequestValidationError
|
|
15
16
|
from fastapi.responses import JSONResponse
|
|
17
|
+
from starlette.exceptions import HTTPException as StarletteHTTPException
|
|
16
18
|
from starlette.middleware import Middleware as StarletteMiddleware
|
|
17
19
|
|
|
18
20
|
from aury.boot.application.config import BaseConfig
|
|
@@ -279,8 +281,11 @@ class FoundationApp(FastAPI):
|
|
|
279
281
|
**kwargs,
|
|
280
282
|
)
|
|
281
283
|
|
|
282
|
-
#
|
|
283
|
-
self.add_exception_handler(
|
|
284
|
+
# 异常处理:显式注册以覆盖 FastAPI/Starlette 默认处理器,确保统一响应格式
|
|
285
|
+
self.add_exception_handler(RequestValidationError, global_exception_handler) # 422
|
|
286
|
+
self.add_exception_handler(HTTPException, global_exception_handler) # 4xx/5xx
|
|
287
|
+
self.add_exception_handler(StarletteHTTPException, global_exception_handler) # Starlette 异常
|
|
288
|
+
self.add_exception_handler(Exception, global_exception_handler) # 其他未处理异常
|
|
284
289
|
|
|
285
290
|
# 设置路由
|
|
286
291
|
self.setup_routes()
|
|
@@ -507,10 +507,9 @@ class MessageQueueSettings(BaseModel):
|
|
|
507
507
|
- Task: 基于 Dramatiq,用于异步任务处理(API + Worker 模式)
|
|
508
508
|
- MQ: 通用消息队列,用于服务间通信、事件驱动架构
|
|
509
509
|
|
|
510
|
-
|
|
510
|
+
支持的后端:
|
|
511
511
|
- Redis: redis://localhost:6379/0
|
|
512
512
|
- RabbitMQ: amqp://guest:guest@localhost:5672//
|
|
513
|
-
- Amazon SQS: sqs://
|
|
514
513
|
"""
|
|
515
514
|
|
|
516
515
|
enabled: bool = Field(
|
|
@@ -174,6 +174,7 @@ class ValidationErrorHandler(ErrorHandler):
|
|
|
174
174
|
"""验证异常处理器。
|
|
175
175
|
|
|
176
176
|
处理 Pydantic ValidationError 和 FastAPI RequestValidationError。
|
|
177
|
+
返回 422 Unprocessable Entity(符合 FastAPI 规范)。
|
|
177
178
|
"""
|
|
178
179
|
|
|
179
180
|
def can_handle(self, exception: Exception) -> bool:
|
|
@@ -182,24 +183,38 @@ class ValidationErrorHandler(ErrorHandler):
|
|
|
182
183
|
|
|
183
184
|
async def handle(self, exception: Exception, request: Request) -> JSONResponse:
|
|
184
185
|
"""处理验证异常。"""
|
|
185
|
-
logger.warning(f"数据验证失败: {exception}")
|
|
186
|
-
|
|
187
186
|
errors = []
|
|
188
187
|
for error in exception.errors():
|
|
188
|
+
# 构建友好的字段路径:跳过 body 前缀
|
|
189
|
+
loc = error.get("loc", ())
|
|
190
|
+
# FastAPI 会在 loc 前加 'body'/'query'/'path' 等,保留第一个作为来源
|
|
191
|
+
source = str(loc[0]) if loc else ""
|
|
192
|
+
field_path = ".".join(str(part) for part in loc[1:]) if len(loc) > 1 else str(loc[0]) if loc else ""
|
|
193
|
+
|
|
189
194
|
errors.append({
|
|
190
|
-
"field":
|
|
191
|
-
"
|
|
192
|
-
"
|
|
195
|
+
"field": field_path,
|
|
196
|
+
"source": source, # body / query / path / header
|
|
197
|
+
"message": error.get("msg", ""),
|
|
198
|
+
"type": error.get("type", ""),
|
|
199
|
+
"input": error.get("input"), # 实际输入值(便于调试)
|
|
193
200
|
})
|
|
194
201
|
|
|
202
|
+
# 详细日志:方便开发调试
|
|
203
|
+
error_summary = "; ".join(
|
|
204
|
+
f"{e['source']}.{e['field']}({e['type']}): {e['message']}" for e in errors
|
|
205
|
+
)
|
|
206
|
+
logger.warning(
|
|
207
|
+
f"参数校验失败 [{request.method} {request.url.path}]: {error_summary}"
|
|
208
|
+
)
|
|
209
|
+
|
|
195
210
|
response = ResponseBuilder.fail(
|
|
196
|
-
message="
|
|
197
|
-
code=
|
|
211
|
+
message="参数校验失败",
|
|
212
|
+
code=422,
|
|
198
213
|
errors=errors,
|
|
199
214
|
)
|
|
200
215
|
|
|
201
216
|
return JSONResponse(
|
|
202
|
-
status_code=status.
|
|
217
|
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
203
218
|
content=response.model_dump(mode="json"),
|
|
204
219
|
)
|
|
205
220
|
|
|
@@ -97,16 +97,16 @@ MODULES: dict[str, ModuleInfo] = {
|
|
|
97
97
|
"tasks": ModuleInfo(
|
|
98
98
|
name="tasks",
|
|
99
99
|
desc="Dramatiq 任务队列",
|
|
100
|
-
usage="TaskManager
|
|
100
|
+
usage="TaskManager 异步任务时需要(默认使用 Redis Broker)",
|
|
101
101
|
category=Category.TASK,
|
|
102
|
-
deps=["dramatiq", "
|
|
102
|
+
deps=["dramatiq", "redis"],
|
|
103
103
|
),
|
|
104
104
|
"rabbitmq": ModuleInfo(
|
|
105
105
|
name="rabbitmq",
|
|
106
106
|
desc="RabbitMQ 消息队列后端",
|
|
107
107
|
usage="TaskManager/EventBus 使用 RabbitMQ 时需要(需配合 tasks)",
|
|
108
108
|
category=Category.TASK,
|
|
109
|
-
deps=["
|
|
109
|
+
deps=["pika"],
|
|
110
110
|
),
|
|
111
111
|
# 调度器
|
|
112
112
|
"scheduler": ModuleInfo(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 定时任务(Scheduler)
|
|
2
2
|
|
|
3
|
-
基于 APScheduler
|
|
3
|
+
基于 APScheduler,支持两种触发器语法:字符串模式和原生对象模式。
|
|
4
4
|
|
|
5
5
|
## 基本用法
|
|
6
6
|
|
|
@@ -9,31 +9,38 @@
|
|
|
9
9
|
```python
|
|
10
10
|
"""定时任务模块。"""
|
|
11
11
|
|
|
12
|
-
from apscheduler.triggers.cron import CronTrigger
|
|
13
|
-
from apscheduler.triggers.interval import IntervalTrigger
|
|
14
|
-
|
|
15
12
|
from aury.boot.common.logging import logger
|
|
16
13
|
from aury.boot.infrastructure.scheduler import SchedulerManager
|
|
17
14
|
|
|
18
15
|
scheduler = SchedulerManager.get_instance()
|
|
19
16
|
|
|
20
17
|
|
|
21
|
-
|
|
18
|
+
# === 字符串模式(推荐,简洁)===
|
|
19
|
+
@scheduler.scheduled_job("interval", seconds=60)
|
|
22
20
|
async def every_minute():
|
|
23
21
|
"""每 60 秒执行。"""
|
|
24
22
|
logger.info("定时任务执行中...")
|
|
25
23
|
|
|
26
24
|
|
|
27
|
-
@scheduler.scheduled_job(
|
|
25
|
+
@scheduler.scheduled_job("cron", hour=0, minute=0)
|
|
28
26
|
async def daily_task():
|
|
29
27
|
"""每天凌晨执行。"""
|
|
30
28
|
logger.info("每日任务执行中...")
|
|
31
29
|
|
|
32
30
|
|
|
33
|
-
@scheduler.scheduled_job(
|
|
31
|
+
@scheduler.scheduled_job("cron", day_of_week="mon", hour=9)
|
|
34
32
|
async def weekly_report():
|
|
35
33
|
"""每周一 9 点执行。"""
|
|
36
34
|
logger.info("周报任务执行中...")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# === 原生对象模式(完整功能)===
|
|
38
|
+
from apscheduler.triggers.cron import CronTrigger
|
|
39
|
+
|
|
40
|
+
@scheduler.scheduled_job(CronTrigger.from_crontab("0 2 * * *"))
|
|
41
|
+
async def crontab_task():
|
|
42
|
+
"""每天凌晨 2 点执行(使用 crontab 表达式)。"""
|
|
43
|
+
logger.info("每日任务执行中...")
|
|
37
44
|
```
|
|
38
45
|
|
|
39
46
|
启用方式:配置 `SCHEDULER__ENABLED=true`,框架自动加载 `{package_name}/schedules/` 模块。
|
|
@@ -50,40 +57,57 @@ SCHEDULER__MISFIRE_GRACE_TIME=60 # 错过容忍时间(秒)
|
|
|
50
57
|
SCHEDULER__JOBSTORE_URL=redis://localhost:6379/0 # 分布式存储(可选)
|
|
51
58
|
```
|
|
52
59
|
|
|
53
|
-
##
|
|
60
|
+
## 触发器语法
|
|
54
61
|
|
|
55
|
-
|
|
62
|
+
支持两种语法:
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
|
|
64
|
+
| 语法 | 适用场景 | 示例 |
|
|
65
|
+
|------|---------|------|
|
|
66
|
+
| 字符串模式 | 日常使用,简洁 | `"cron", hour="*", minute=0` |
|
|
67
|
+
| 原生对象 | crontab 表达式、复杂配置 | `CronTrigger.from_crontab("0 * * * *")` |
|
|
59
68
|
|
|
69
|
+
### cron - 定时触发
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
# === 字符串模式 ===
|
|
60
73
|
# 每天凌晨 2:30
|
|
61
|
-
|
|
74
|
+
@scheduler.scheduled_job("cron", hour=2, minute=30)
|
|
62
75
|
|
|
63
76
|
# 每小时整点
|
|
64
|
-
|
|
77
|
+
@scheduler.scheduled_job("cron", hour="*", minute=0)
|
|
65
78
|
|
|
66
79
|
# 工作日 9:00
|
|
67
|
-
|
|
80
|
+
@scheduler.scheduled_job("cron", day_of_week="mon-fri", hour=9)
|
|
68
81
|
|
|
69
82
|
# 每月 1 号
|
|
70
|
-
|
|
83
|
+
@scheduler.scheduled_job("cron", day=1, hour=0)
|
|
84
|
+
|
|
85
|
+
# === 原生对象模式 ===
|
|
86
|
+
from apscheduler.triggers.cron import CronTrigger
|
|
71
87
|
|
|
72
88
|
# 使用 crontab 表达式
|
|
73
|
-
CronTrigger.from_crontab("0 2 * * *") # 每天 2:00
|
|
89
|
+
@scheduler.scheduled_job(CronTrigger.from_crontab("0 2 * * *")) # 每天 2:00
|
|
74
90
|
```
|
|
75
91
|
|
|
76
|
-
|
|
92
|
+
**cron 参数**:`year`, `month`, `day`, `week`, `day_of_week`, `hour`, `minute`, `second`, `start_date`, `end_date`, `timezone`, `jitter`
|
|
93
|
+
|
|
94
|
+
### interval - 间隔触发
|
|
77
95
|
|
|
78
96
|
```python
|
|
97
|
+
# === 字符串模式 ===
|
|
98
|
+
@scheduler.scheduled_job("interval", seconds=30) # 每 30 秒
|
|
99
|
+
@scheduler.scheduled_job("interval", minutes=5) # 每 5 分钟
|
|
100
|
+
@scheduler.scheduled_job("interval", hours=1) # 每小时
|
|
101
|
+
@scheduler.scheduled_job("interval", days=1) # 每天
|
|
102
|
+
|
|
103
|
+
# === 原生对象模式 ===
|
|
79
104
|
from apscheduler.triggers.interval import IntervalTrigger
|
|
80
105
|
|
|
81
|
-
IntervalTrigger(
|
|
82
|
-
IntervalTrigger(minutes=5) # 每 5 分钟
|
|
83
|
-
IntervalTrigger(hours=1) # 每小时
|
|
84
|
-
IntervalTrigger(days=1) # 每天
|
|
106
|
+
@scheduler.scheduled_job(IntervalTrigger(hours=1, jitter=60)) # 每小时,随机抖动 60 秒
|
|
85
107
|
```
|
|
86
108
|
|
|
109
|
+
**interval 参数**:`weeks`, `days`, `hours`, `minutes`, `seconds`, `start_date`, `end_date`, `timezone`, `jitter`
|
|
110
|
+
|
|
87
111
|
### DateTrigger - 一次性触发
|
|
88
112
|
|
|
89
113
|
```python
|
|
@@ -91,9 +115,31 @@ from apscheduler.triggers.date import DateTrigger
|
|
|
91
115
|
from datetime import datetime, timedelta
|
|
92
116
|
|
|
93
117
|
# 10 秒后执行
|
|
94
|
-
DateTrigger(run_date=datetime.now() + timedelta(seconds=10))
|
|
118
|
+
scheduler.add_job(my_task, DateTrigger(run_date=datetime.now() + timedelta(seconds=10)))
|
|
95
119
|
```
|
|
96
120
|
|
|
121
|
+
## 条件加载
|
|
122
|
+
|
|
123
|
+
通过 `enabled` 参数控制任务是否注册:
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from config import settings
|
|
127
|
+
|
|
128
|
+
# 根据配置开关决定是否启用
|
|
129
|
+
@scheduler.scheduled_job("cron", hour=2, enabled=settings.ENABLE_REPORT)
|
|
130
|
+
async def daily_report():
|
|
131
|
+
"""仅在 ENABLE_REPORT=true 时注册。"""
|
|
132
|
+
...
|
|
133
|
+
|
|
134
|
+
# 区分环境
|
|
135
|
+
@scheduler.scheduled_job("interval", minutes=5, enabled=settings.ENV == "production")
|
|
136
|
+
async def prod_only_task():
|
|
137
|
+
"""仅生产环境执行。"""
|
|
138
|
+
...
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`enabled=False` 时任务不会注册,日志记录:`任务已禁用,跳过注册: xxx`
|
|
142
|
+
|
|
97
143
|
## 多实例支持
|
|
98
144
|
|
|
99
145
|
支持不同业务线使用独立的调度器实例:
|
|
@@ -136,7 +182,11 @@ scheduler = SchedulerManager.get_instance(
|
|
|
136
182
|
## 任务管理
|
|
137
183
|
|
|
138
184
|
```python
|
|
139
|
-
#
|
|
185
|
+
# 添加任务(字符串模式)
|
|
186
|
+
scheduler.add_job(my_task, "cron", hour=2, minute=0, id="my_task")
|
|
187
|
+
|
|
188
|
+
# 添加任务(原生对象模式)
|
|
189
|
+
from apscheduler.triggers.cron import CronTrigger
|
|
140
190
|
scheduler.add_job(my_task, CronTrigger(hour=2), id="my_task")
|
|
141
191
|
|
|
142
192
|
# 获取任务
|
|
@@ -150,7 +200,10 @@ scheduler.resume_job("my_task")
|
|
|
150
200
|
# 移除
|
|
151
201
|
scheduler.remove_job("my_task")
|
|
152
202
|
|
|
153
|
-
#
|
|
203
|
+
# 重新调度(字符串模式)
|
|
204
|
+
scheduler.reschedule_job("my_task", "cron", hour=3)
|
|
205
|
+
|
|
206
|
+
# 重新调度(原生对象模式)
|
|
154
207
|
scheduler.reschedule_job("my_task", CronTrigger(hour=3))
|
|
155
208
|
```
|
|
156
209
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""定时任务模块(Scheduler)。
|
|
2
|
+
|
|
3
|
+
在此文件中定义定时任务,使用 @scheduler.scheduled_job() 装饰器。
|
|
4
|
+
|
|
5
|
+
框架会自动发现并加载本模块,无需在 main.py 中手动导入。
|
|
6
|
+
也可通过 SCHEDULER_SCHEDULE_MODULES 环境变量指定自定义模块。
|
|
7
|
+
|
|
8
|
+
触发器支持两种语法:
|
|
9
|
+
- 字符串模式(推荐):@scheduler.scheduled_job("cron", hour="*", minute=0)
|
|
10
|
+
- 原生对象模式:@scheduler.scheduled_job(CronTrigger(hour="*"))
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# from aury.boot.common.logging import logger
|
|
14
|
+
# from aury.boot.infrastructure.scheduler import SchedulerManager
|
|
15
|
+
#
|
|
16
|
+
# scheduler = SchedulerManager.get_instance()
|
|
17
|
+
#
|
|
18
|
+
#
|
|
19
|
+
# # === 字符串模式(推荐,简洁)===
|
|
20
|
+
# @scheduler.scheduled_job("interval", seconds=60)
|
|
21
|
+
# async def example_job():
|
|
22
|
+
# """示例定时任务,每 60 秒执行一次。"""
|
|
23
|
+
# logger.info("定时任务执行中...")
|
|
24
|
+
#
|
|
25
|
+
#
|
|
26
|
+
# @scheduler.scheduled_job("cron", hour="*", minute=0)
|
|
27
|
+
# async def hourly_job():
|
|
28
|
+
# """每小时整点执行。"""
|
|
29
|
+
# logger.info("整点任务执行")
|
|
30
|
+
#
|
|
31
|
+
#
|
|
32
|
+
# # === 原生对象模式(完整功能)===
|
|
33
|
+
# # from apscheduler.triggers.cron import CronTrigger
|
|
34
|
+
# #
|
|
35
|
+
# # @scheduler.scheduled_job(CronTrigger.from_crontab("0 2 * * *"))
|
|
36
|
+
# # async def daily_job():
|
|
37
|
+
# # """每天凌晨 2 点执行(使用 crontab 表达式)。"""
|
|
38
|
+
# # logger.info("每日任务执行")
|