aury-boot 0.0.36__tar.gz → 0.0.38__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.36 → aury_boot-0.0.38}/PKG-INFO +1 -1
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/_version.py +2 -2
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/config/settings.py +4 -4
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/init.py +2 -2
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/AGENTS.md.tpl +1 -1
- aury_boot-0.0.38/aury/boot/commands/templates/project/aury_docs/14-mq.md.tpl +152 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/env_templates/messaging.tpl +15 -7
- aury_boot-0.0.38/aury/boot/infrastructure/cache/backends.py +14 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/cache/base.py +38 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/cache/manager.py +151 -1
- aury_boot-0.0.36/aury/boot/infrastructure/cache/backends.py → aury_boot-0.0.38/aury/boot/infrastructure/cache/memory.py +78 -204
- aury_boot-0.0.38/aury/boot/infrastructure/cache/redis.py +259 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/mq/backends/redis.py +1 -1
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/mq/backends/redis_stream.py +1 -1
- aury_boot-0.0.36/aury/boot/commands/templates/project/aury_docs/14-mq.md.tpl +0 -102
- {aury_boot-0.0.36 → aury_boot-0.0.38}/.gitignore +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/README.md +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/adapter/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/adapter/base.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/adapter/config.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/adapter/decorators.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/adapter/exceptions.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/adapter/http.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/app/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/app/base.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/app/components.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/app/middlewares.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/app/startup.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/config/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/config/multi_instance.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/constants/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/constants/components.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/constants/scheduler.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/constants/service.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/errors/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/errors/chain.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/errors/codes.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/errors/exceptions.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/errors/handlers.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/errors/response.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/interfaces/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/interfaces/egress.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/interfaces/ingress.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/middleware/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/middleware/logging.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/migrations/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/migrations/manager.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/migrations/setup.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/rpc/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/rpc/base.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/rpc/client.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/rpc/discovery.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/scheduler/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/scheduler/runner.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/application/server/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/add.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/app.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/config.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/docker.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/docs.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/generate.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/migrate/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/migrate/app.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/migrate/commands.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/pkg.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/scheduler.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/server/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/server/app.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/generate/api.py.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/generate/model.py.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/generate/repository.py.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/generate/schema.py.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/generate/service.py.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/README.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/admin_console_init.py.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/alert_rules.example.yaml.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/00-overview.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/01-model.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/02-repository.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/03-service.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/04-schema.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/05-api.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/06-exception.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/07-cache.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/08-scheduler.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/09-tasks.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/10-storage.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/11-logging.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/12-admin.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/13-channel.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/15-events.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/16-adapter.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/17-alerting.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/aury_docs/99-cli.md.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/config.py.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/conftest.py.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/env_templates/_header.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/env_templates/admin.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/env_templates/cache.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/env_templates/database.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/env_templates/log.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/env_templates/monitoring.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/env_templates/rpc.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/env_templates/scheduler.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/env_templates/service.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/env_templates/storage.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/env_templates/third_party.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/gitignore.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/main.py.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/modules/api.py.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/modules/exceptions.py.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/modules/schedules.py.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/templates/project/modules/tasks.py.tpl +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/commands/worker.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/common/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/common/exceptions/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/common/i18n/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/common/i18n/translator.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/common/logging/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/common/logging/context.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/common/logging/decorators.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/common/logging/format.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/common/logging/setup.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/contrib/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/contrib/admin_console/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/contrib/admin_console/auth.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/contrib/admin_console/discovery.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/contrib/admin_console/install.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/contrib/admin_console/utils.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/exceptions/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/models/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/models/base.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/models/mixins.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/models/models.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/pagination/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/repository/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/repository/impl.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/repository/interceptors.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/repository/interface.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/repository/query_builder.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/service/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/service/base.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/domain/transaction/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/cache/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/cache/exceptions.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/cache/factory.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/channel/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/channel/backends/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/channel/backends/broadcaster.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/channel/base.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/channel/manager.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/clients/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/clients/rabbitmq/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/clients/rabbitmq/config.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/clients/rabbitmq/manager.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/clients/redis/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/clients/redis/config.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/clients/redis/manager.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/database/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/database/config.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/database/exceptions.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/database/manager.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/database/query_tools/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/database/strategies/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/di/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/di/container.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/events/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/events/backends/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/events/backends/broadcaster.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/events/backends/rabbitmq.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/events/base.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/events/manager.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/events/middleware.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/alerting/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/alerting/aggregator.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/alerting/events.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/alerting/manager.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/alerting/notifiers/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/alerting/notifiers/base.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/alerting/notifiers/feishu.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/alerting/notifiers/webhook.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/alerting/rules.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/health/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/tracing/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/tracing/context.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/tracing/logging.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/tracing/processor.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/tracing/provider.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/monitoring/tracing/tracing.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/mq/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/mq/backends/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/mq/backends/rabbitmq.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/mq/base.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/mq/manager.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/scheduler/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/scheduler/exceptions.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/scheduler/manager.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/storage/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/storage/base.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/storage/exceptions.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/storage/factory.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/tasks/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/tasks/config.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/tasks/constants.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/tasks/exceptions.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/infrastructure/tasks/manager.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/testing/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/testing/base.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/testing/client.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/testing/factory.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/toolkit/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/aury/boot/toolkit/http/__init__.py +0 -0
- {aury_boot-0.0.36 → aury_boot-0.0.38}/pyproject.toml +0 -0
|
@@ -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.38'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 0, 38)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -147,13 +147,13 @@ class MQInstanceConfig(MultiInstanceSettings):
|
|
|
147
147
|
|
|
148
148
|
环境变量格式: MQ__{INSTANCE}__{FIELD}
|
|
149
149
|
示例:
|
|
150
|
-
MQ__DEFAULT__BACKEND=
|
|
150
|
+
MQ__DEFAULT__BACKEND=redis_stream
|
|
151
151
|
MQ__DEFAULT__URL=redis://localhost:6379/4
|
|
152
152
|
"""
|
|
153
153
|
|
|
154
154
|
backend: str = Field(
|
|
155
|
-
default="
|
|
156
|
-
description="消息队列后端 (redis/rabbitmq)"
|
|
155
|
+
default="redis_stream",
|
|
156
|
+
description="消息队列后端 (redis/redis_stream/rabbitmq)"
|
|
157
157
|
)
|
|
158
158
|
url: str | None = Field(
|
|
159
159
|
default=None,
|
|
@@ -715,7 +715,7 @@ class AlertSettings(BaseModel):
|
|
|
715
715
|
|
|
716
716
|
# 抑制配置
|
|
717
717
|
suppress_seconds: int = Field(
|
|
718
|
-
default=
|
|
718
|
+
default=300,
|
|
719
719
|
description="告警抑制时间(秒),相同告警在此时间内不重复发送"
|
|
720
720
|
)
|
|
721
721
|
|
|
@@ -707,8 +707,8 @@ def init(
|
|
|
707
707
|
console.print(f" [cyan]uv add \"{deps[0]}\"[/cyan]")
|
|
708
708
|
console.print()
|
|
709
709
|
else:
|
|
710
|
-
#
|
|
711
|
-
with_admin_console =
|
|
710
|
+
# 非交互模式:默认禁用 Admin Console
|
|
711
|
+
with_admin_console = False
|
|
712
712
|
if package_name == ".":
|
|
713
713
|
package_name_snake = None
|
|
714
714
|
elif package_name:
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# 消息队列(MQ)
|
|
2
|
+
|
|
3
|
+
支持 `redis`、`redis_stream` 和 `rabbitmq` 后端的消息队列,用于异步任务解耦。
|
|
4
|
+
|
|
5
|
+
## 14.1 基本用法
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from aury.boot.infrastructure.mq import MQManager
|
|
9
|
+
|
|
10
|
+
# 获取实例
|
|
11
|
+
mq = MQManager.get_instance()
|
|
12
|
+
|
|
13
|
+
# Redis List 后端(简单队列)
|
|
14
|
+
await mq.initialize(backend="redis", url="redis://localhost:6379/0")
|
|
15
|
+
|
|
16
|
+
# Redis Stream 后端(推荐,支持消费者组)
|
|
17
|
+
await mq.initialize(backend="redis_stream", url="redis://localhost:6379/0")
|
|
18
|
+
|
|
19
|
+
# RabbitMQ 后端
|
|
20
|
+
await mq.initialize(backend="rabbitmq", url="amqp://guest:guest@localhost:5672/")
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 14.2 后端对比
|
|
24
|
+
|
|
25
|
+
**Redis List (redis)**:
|
|
26
|
+
- 简单的 FIFO 队列(LPUSH/BRPOP)
|
|
27
|
+
- 适合单消费者场景
|
|
28
|
+
- 消息不持久化(除非开启 AOF)
|
|
29
|
+
|
|
30
|
+
**Redis Stream (redis_stream)** ⭐ 推荐:
|
|
31
|
+
- 支持消费者组,多实例可并行消费
|
|
32
|
+
- 消息持久化(配合 AOF)
|
|
33
|
+
- 支持消息确认(ACK)和重试
|
|
34
|
+
- 支持消息回放和历史查询
|
|
35
|
+
|
|
36
|
+
**RabbitMQ (rabbitmq)**:
|
|
37
|
+
- 功能最完整的消息队列
|
|
38
|
+
- 支持多种交换机类型
|
|
39
|
+
- 适合复杂的消息路由场景
|
|
40
|
+
|
|
41
|
+
## 14.3 生产者
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from aury.boot.infrastructure.mq import MQMessage
|
|
45
|
+
|
|
46
|
+
# 发送消息
|
|
47
|
+
await mq.send(
|
|
48
|
+
queue="orders",
|
|
49
|
+
message={{"order_id": "123", "action": "created"}}
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# 使用 MQMessage 对象(可设置 headers)
|
|
53
|
+
msg = MQMessage(
|
|
54
|
+
body={{"order_id": "123"}},
|
|
55
|
+
headers={{"priority": "high"}}
|
|
56
|
+
)
|
|
57
|
+
await mq.send("orders", msg)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 14.4 消费者
|
|
61
|
+
|
|
62
|
+
**文件**: `{package_name}/workers/order_worker.py`
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from aury.boot.infrastructure.mq import MQManager, MQMessage
|
|
66
|
+
from aury.boot.common.logging import logger
|
|
67
|
+
|
|
68
|
+
mq = MQManager.get_instance()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
async def process_order(message: MQMessage):
|
|
72
|
+
\"\"\"处理订单消息。\"\"\"
|
|
73
|
+
logger.info(f"处理订单: {{message.body}}")
|
|
74
|
+
# 业务逻辑...
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
async def start_consumer():
|
|
78
|
+
\"\"\"启动消费者。\"\"\"
|
|
79
|
+
# consume 会自动处理 ACK/NACK
|
|
80
|
+
await mq.consume("orders", process_order)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## 14.5 Redis Stream 特性
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from aury.boot.infrastructure.mq.backends.redis_stream import RedisStreamMQ
|
|
87
|
+
|
|
88
|
+
# 初始化时指定消费者组
|
|
89
|
+
mq = MQManager.get_instance()
|
|
90
|
+
await mq.initialize(
|
|
91
|
+
backend="redis_stream",
|
|
92
|
+
url="redis://localhost:6379/0"
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# 获取底层 RedisStreamMQ 实例使用高级特性
|
|
96
|
+
stream_mq: RedisStreamMQ = mq.backend
|
|
97
|
+
|
|
98
|
+
# 读取所有历史消息(用于重放)
|
|
99
|
+
messages = await stream_mq.read_all("orders", count=100)
|
|
100
|
+
|
|
101
|
+
# 阻塞读取新消息(用于 SSE/实时推送)
|
|
102
|
+
messages = await stream_mq.read_blocking(
|
|
103
|
+
"orders",
|
|
104
|
+
last_id="$", # 从最新消息开始
|
|
105
|
+
count=10,
|
|
106
|
+
block_ms=5000 # 阻塞 5 秒
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# 裁剪 Stream(保留最新 1000 条)
|
|
110
|
+
await stream_mq.trim("orders", maxlen=1000)
|
|
111
|
+
|
|
112
|
+
# 获取 Stream 信息
|
|
113
|
+
info = await stream_mq.stream_info("orders")
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## 14.6 多实例配置
|
|
117
|
+
|
|
118
|
+
框架支持命名多实例,适合不同业务场景使用不同的 MQ:
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
# 代码中使用命名实例
|
|
122
|
+
orders_mq = MQManager.get_instance("orders")
|
|
123
|
+
notifications_mq = MQManager.get_instance("notifications")
|
|
124
|
+
|
|
125
|
+
# 分别初始化
|
|
126
|
+
await orders_mq.initialize(backend="redis_stream", url="redis://localhost:6379/1")
|
|
127
|
+
await notifications_mq.initialize(backend="redis", url="redis://localhost:6379/2")
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**环境变量配置**(自动初始化):
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# 单实例配置
|
|
134
|
+
MQ__BACKEND=redis_stream
|
|
135
|
+
MQ__URL=redis://localhost:6379/0
|
|
136
|
+
|
|
137
|
+
# 多实例配置(格式:MQ__{{INSTANCE}}__{{FIELD}})
|
|
138
|
+
MQ__DEFAULT__BACKEND=redis_stream
|
|
139
|
+
MQ__DEFAULT__URL=redis://localhost:6379/4
|
|
140
|
+
MQ__ORDERS__BACKEND=rabbitmq
|
|
141
|
+
MQ__ORDERS__URL=amqp://guest:guest@localhost:5672/
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## 14.7 与异步任务(Dramatiq)的区别
|
|
145
|
+
|
|
146
|
+
- **MQ**:轻量级消息传递,适合简单的生产者-消费者模式、实时通知、多实例消费
|
|
147
|
+
- **Dramatiq(TaskManager)**:功能更丰富,支持重试、延迟、优先级、Actor 模式
|
|
148
|
+
|
|
149
|
+
选择建议:
|
|
150
|
+
- 简单的异步解耦 → MQ (redis_stream)
|
|
151
|
+
- 需要重试/延迟/优先级 → Dramatiq
|
|
152
|
+
- 多服务实例并行消费 → MQ (redis_stream) 或 RabbitMQ
|
|
@@ -19,19 +19,27 @@
|
|
|
19
19
|
# =============================================================================
|
|
20
20
|
# 消息队列配置 (MQ__)
|
|
21
21
|
# =============================================================================
|
|
22
|
+
# 支持后端: redis | redis_stream (推荐) | rabbitmq
|
|
23
|
+
#
|
|
22
24
|
# 单实例配置:
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
|
|
25
|
+
# MQ__BACKEND=redis_stream
|
|
26
|
+
# MQ__URL=redis://localhost:6379/4
|
|
27
|
+
#
|
|
26
28
|
# 多实例配置 (格式: MQ__{{INSTANCE}}__{{FIELD}}):
|
|
27
|
-
# MQ__DEFAULT__BACKEND=
|
|
29
|
+
# MQ__DEFAULT__BACKEND=redis_stream
|
|
28
30
|
# MQ__DEFAULT__URL=redis://localhost:6379/4
|
|
29
|
-
# MQ__DEFAULT__MAX_CONNECTIONS=10
|
|
30
31
|
#
|
|
31
|
-
#
|
|
32
|
+
# Redis List 后端 (简单 FIFO 队列):
|
|
33
|
+
# MQ__SIMPLE__BACKEND=redis
|
|
34
|
+
# MQ__SIMPLE__URL=redis://localhost:6379/4
|
|
35
|
+
#
|
|
36
|
+
# Redis Stream 后端 (推荐,支持消费者组/多实例消费):
|
|
37
|
+
# MQ__TASKS__BACKEND=redis_stream
|
|
38
|
+
# MQ__TASKS__URL=redis://localhost:6379/4
|
|
39
|
+
#
|
|
40
|
+
# RabbitMQ 后端 (复杂消息路由):
|
|
32
41
|
# MQ__ORDERS__BACKEND=rabbitmq
|
|
33
42
|
# MQ__ORDERS__URL=amqp://guest:guest@localhost:5672/orders
|
|
34
|
-
# MQ__ORDERS__PREFETCH_COUNT=10
|
|
35
43
|
|
|
36
44
|
# =============================================================================
|
|
37
45
|
# 事件总线配置 (EVENT__)
|
|
@@ -71,6 +71,44 @@ class ICache(ABC):
|
|
|
71
71
|
async def close(self) -> None:
|
|
72
72
|
"""关闭连接。"""
|
|
73
73
|
pass
|
|
74
|
+
|
|
75
|
+
# ==================== 分布式锁 ====================
|
|
76
|
+
|
|
77
|
+
@abstractmethod
|
|
78
|
+
async def acquire_lock(
|
|
79
|
+
self,
|
|
80
|
+
key: str,
|
|
81
|
+
token: str,
|
|
82
|
+
timeout: int,
|
|
83
|
+
blocking: bool,
|
|
84
|
+
blocking_timeout: float | None,
|
|
85
|
+
) -> bool:
|
|
86
|
+
"""获取分布式锁。
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
key: 锁的键名(已加 lock: 前缀)
|
|
90
|
+
token: 锁的 token
|
|
91
|
+
timeout: 锁的超时时间(秒)
|
|
92
|
+
blocking: 是否阻塞等待
|
|
93
|
+
blocking_timeout: 阻塞等待的最大时间(秒)
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
bool: 是否获取成功
|
|
97
|
+
"""
|
|
98
|
+
pass
|
|
99
|
+
|
|
100
|
+
@abstractmethod
|
|
101
|
+
async def release_lock(self, key: str, token: str) -> bool:
|
|
102
|
+
"""释放分布式锁。
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
key: 锁的键名(已加 lock: 前缀)
|
|
106
|
+
token: 获取锁时的 token
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
bool: 是否成功释放
|
|
110
|
+
"""
|
|
111
|
+
pass
|
|
74
112
|
|
|
75
113
|
|
|
76
114
|
__all__ = [
|
|
@@ -5,11 +5,15 @@
|
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
|
+
import asyncio
|
|
8
9
|
from collections.abc import Callable
|
|
10
|
+
from contextlib import asynccontextmanager
|
|
9
11
|
from datetime import timedelta
|
|
10
12
|
from functools import wraps
|
|
11
13
|
import hashlib
|
|
12
|
-
|
|
14
|
+
import time
|
|
15
|
+
from typing import Any, AsyncIterator, TypeVar
|
|
16
|
+
import uuid
|
|
13
17
|
|
|
14
18
|
from aury.boot.common.logging import logger
|
|
15
19
|
|
|
@@ -328,6 +332,152 @@ class CacheManager:
|
|
|
328
332
|
self._backend = None
|
|
329
333
|
logger.info("缓存管理器已清理")
|
|
330
334
|
|
|
335
|
+
# ==================== 分布式锁 ====================
|
|
336
|
+
|
|
337
|
+
async def acquire_lock(
|
|
338
|
+
self,
|
|
339
|
+
key: str,
|
|
340
|
+
*,
|
|
341
|
+
timeout: int = 30,
|
|
342
|
+
blocking: bool = True,
|
|
343
|
+
blocking_timeout: float | None = None,
|
|
344
|
+
) -> str | None:
|
|
345
|
+
"""获取分布式锁。
|
|
346
|
+
|
|
347
|
+
Args:
|
|
348
|
+
key: 锁的键名
|
|
349
|
+
timeout: 锁的超时时间(秒),防止死锁
|
|
350
|
+
blocking: 是否阻塞等待
|
|
351
|
+
blocking_timeout: 阻塞等待的最大时间(秒)
|
|
352
|
+
|
|
353
|
+
Returns:
|
|
354
|
+
str | None: 锁的 token(用于释放),获取失败返回 None
|
|
355
|
+
"""
|
|
356
|
+
lock_key = f"lock:{key}"
|
|
357
|
+
token = str(uuid.uuid4())
|
|
358
|
+
|
|
359
|
+
acquired = await self.backend.acquire_lock(
|
|
360
|
+
lock_key, token, timeout, blocking, blocking_timeout
|
|
361
|
+
)
|
|
362
|
+
return token if acquired else None
|
|
363
|
+
|
|
364
|
+
async def release_lock(self, key: str, token: str) -> bool:
|
|
365
|
+
"""释放分布式锁。
|
|
366
|
+
|
|
367
|
+
Args:
|
|
368
|
+
key: 锁的键名
|
|
369
|
+
token: acquire_lock 返回的 token
|
|
370
|
+
|
|
371
|
+
Returns:
|
|
372
|
+
bool: 是否成功释放
|
|
373
|
+
"""
|
|
374
|
+
lock_key = f"lock:{key}"
|
|
375
|
+
return await self.backend.release_lock(lock_key, token)
|
|
376
|
+
|
|
377
|
+
@asynccontextmanager
|
|
378
|
+
async def lock(
|
|
379
|
+
self,
|
|
380
|
+
key: str,
|
|
381
|
+
*,
|
|
382
|
+
timeout: int = 30,
|
|
383
|
+
blocking: bool = True,
|
|
384
|
+
blocking_timeout: float | None = None,
|
|
385
|
+
) -> AsyncIterator[bool]:
|
|
386
|
+
"""分布式锁上下文管理器。
|
|
387
|
+
|
|
388
|
+
Args:
|
|
389
|
+
key: 锁的键名
|
|
390
|
+
timeout: 锁的超时时间(秒)
|
|
391
|
+
blocking: 是否阻塞等待
|
|
392
|
+
blocking_timeout: 阻塞等待的最大时间(秒)
|
|
393
|
+
|
|
394
|
+
Yields:
|
|
395
|
+
bool: 是否成功获取锁
|
|
396
|
+
|
|
397
|
+
示例:
|
|
398
|
+
async with cache.lock("my_resource") as acquired:
|
|
399
|
+
if acquired:
|
|
400
|
+
# 执行需要互斥的操作
|
|
401
|
+
pass
|
|
402
|
+
"""
|
|
403
|
+
token = await self.acquire_lock(
|
|
404
|
+
key,
|
|
405
|
+
timeout=timeout,
|
|
406
|
+
blocking=blocking,
|
|
407
|
+
blocking_timeout=blocking_timeout,
|
|
408
|
+
)
|
|
409
|
+
try:
|
|
410
|
+
yield token is not None
|
|
411
|
+
finally:
|
|
412
|
+
if token:
|
|
413
|
+
await self.release_lock(key, token)
|
|
414
|
+
|
|
415
|
+
@asynccontextmanager
|
|
416
|
+
async def semaphore(
|
|
417
|
+
self,
|
|
418
|
+
key: str,
|
|
419
|
+
max_concurrency: int,
|
|
420
|
+
*,
|
|
421
|
+
timeout: int = 300,
|
|
422
|
+
blocking: bool = True,
|
|
423
|
+
blocking_timeout: float | None = None,
|
|
424
|
+
) -> AsyncIterator[bool]:
|
|
425
|
+
"""分布式信号量(限制并发数)。
|
|
426
|
+
|
|
427
|
+
Args:
|
|
428
|
+
key: 信号量的键名
|
|
429
|
+
max_concurrency: 最大并发数
|
|
430
|
+
timeout: 单个槽位的超时时间(秒)
|
|
431
|
+
blocking: 是否阻塞等待
|
|
432
|
+
blocking_timeout: 阻塞等待的最大时间(秒)
|
|
433
|
+
|
|
434
|
+
Yields:
|
|
435
|
+
bool: 是否成功获取槽位
|
|
436
|
+
|
|
437
|
+
示例:
|
|
438
|
+
async with cache.semaphore("pdf_ocr", max_concurrency=2) as acquired:
|
|
439
|
+
if acquired:
|
|
440
|
+
# 执行受并发限制的操作
|
|
441
|
+
pass
|
|
442
|
+
"""
|
|
443
|
+
slot_token: str | None = None
|
|
444
|
+
acquired_slot: int | None = None
|
|
445
|
+
start_time = time.monotonic()
|
|
446
|
+
|
|
447
|
+
try:
|
|
448
|
+
while True:
|
|
449
|
+
# 尝试获取任意一个槽位
|
|
450
|
+
for slot in range(max_concurrency):
|
|
451
|
+
slot_key = f"{key}:slot:{slot}"
|
|
452
|
+
token = await self.acquire_lock(
|
|
453
|
+
slot_key,
|
|
454
|
+
timeout=timeout,
|
|
455
|
+
blocking=False,
|
|
456
|
+
)
|
|
457
|
+
if token:
|
|
458
|
+
slot_token = token
|
|
459
|
+
acquired_slot = slot
|
|
460
|
+
yield True
|
|
461
|
+
return
|
|
462
|
+
|
|
463
|
+
if not blocking:
|
|
464
|
+
yield False
|
|
465
|
+
return
|
|
466
|
+
|
|
467
|
+
# 检查是否超时
|
|
468
|
+
if blocking_timeout is not None:
|
|
469
|
+
elapsed = time.monotonic() - start_time
|
|
470
|
+
if elapsed >= blocking_timeout:
|
|
471
|
+
yield False
|
|
472
|
+
return
|
|
473
|
+
|
|
474
|
+
# 等待后重试
|
|
475
|
+
await asyncio.sleep(0.1)
|
|
476
|
+
finally:
|
|
477
|
+
if slot_token and acquired_slot is not None:
|
|
478
|
+
slot_key = f"{key}:slot:{acquired_slot}"
|
|
479
|
+
await self.release_lock(slot_key, slot_token)
|
|
480
|
+
|
|
331
481
|
def __repr__(self) -> str:
|
|
332
482
|
"""字符串表示。"""
|
|
333
483
|
backend_name = self.backend_type if self._backend else "未初始化"
|