aury-boot 0.0.37__tar.gz → 0.0.39__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.
Files changed (218) hide show
  1. {aury_boot-0.0.37 → aury_boot-0.0.39}/PKG-INFO +1 -1
  2. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/_version.py +2 -2
  3. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/migrations/setup.py +14 -2
  4. aury_boot-0.0.39/aury/boot/infrastructure/cache/backends.py +14 -0
  5. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/cache/base.py +38 -0
  6. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/cache/manager.py +151 -1
  7. aury_boot-0.0.37/aury/boot/infrastructure/cache/backends.py → aury_boot-0.0.39/aury/boot/infrastructure/cache/memory.py +78 -204
  8. aury_boot-0.0.39/aury/boot/infrastructure/cache/redis.py +259 -0
  9. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/mq/backends/redis.py +1 -1
  10. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/mq/backends/redis_stream.py +9 -2
  11. {aury_boot-0.0.37 → aury_boot-0.0.39}/.gitignore +0 -0
  12. {aury_boot-0.0.37 → aury_boot-0.0.39}/README.md +0 -0
  13. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/__init__.py +0 -0
  14. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/__init__.py +0 -0
  15. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/adapter/__init__.py +0 -0
  16. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/adapter/base.py +0 -0
  17. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/adapter/config.py +0 -0
  18. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/adapter/decorators.py +0 -0
  19. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/adapter/exceptions.py +0 -0
  20. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/adapter/http.py +0 -0
  21. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/app/__init__.py +0 -0
  22. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/app/base.py +0 -0
  23. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/app/components.py +0 -0
  24. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/app/middlewares.py +0 -0
  25. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/app/startup.py +0 -0
  26. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/config/__init__.py +0 -0
  27. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/config/multi_instance.py +0 -0
  28. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/config/settings.py +0 -0
  29. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/constants/__init__.py +0 -0
  30. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/constants/components.py +0 -0
  31. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/constants/scheduler.py +0 -0
  32. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/constants/service.py +0 -0
  33. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/errors/__init__.py +0 -0
  34. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/errors/chain.py +0 -0
  35. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/errors/codes.py +0 -0
  36. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/errors/exceptions.py +0 -0
  37. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/errors/handlers.py +0 -0
  38. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/errors/response.py +0 -0
  39. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/interfaces/__init__.py +0 -0
  40. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/interfaces/egress.py +0 -0
  41. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/interfaces/ingress.py +0 -0
  42. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/middleware/__init__.py +0 -0
  43. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/middleware/logging.py +0 -0
  44. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/migrations/__init__.py +0 -0
  45. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/migrations/manager.py +0 -0
  46. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/rpc/__init__.py +0 -0
  47. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/rpc/base.py +0 -0
  48. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/rpc/client.py +0 -0
  49. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/rpc/discovery.py +0 -0
  50. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/scheduler/__init__.py +0 -0
  51. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/scheduler/runner.py +0 -0
  52. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/application/server/__init__.py +0 -0
  53. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/__init__.py +0 -0
  54. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/add.py +0 -0
  55. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/app.py +0 -0
  56. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/config.py +0 -0
  57. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/docker.py +0 -0
  58. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/docs.py +0 -0
  59. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/generate.py +0 -0
  60. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/init.py +0 -0
  61. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/migrate/__init__.py +0 -0
  62. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/migrate/app.py +0 -0
  63. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/migrate/commands.py +0 -0
  64. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/pkg.py +0 -0
  65. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/scheduler.py +0 -0
  66. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/server/__init__.py +0 -0
  67. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/server/app.py +0 -0
  68. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/generate/api.py.tpl +0 -0
  69. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/generate/model.py.tpl +0 -0
  70. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/generate/repository.py.tpl +0 -0
  71. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/generate/schema.py.tpl +0 -0
  72. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/generate/service.py.tpl +0 -0
  73. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/AGENTS.md.tpl +0 -0
  74. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/README.md.tpl +0 -0
  75. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/admin_console_init.py.tpl +0 -0
  76. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/alert_rules.example.yaml.tpl +0 -0
  77. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/00-overview.md.tpl +0 -0
  78. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/01-model.md.tpl +0 -0
  79. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/02-repository.md.tpl +0 -0
  80. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/03-service.md.tpl +0 -0
  81. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/04-schema.md.tpl +0 -0
  82. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/05-api.md.tpl +0 -0
  83. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/06-exception.md.tpl +0 -0
  84. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/07-cache.md.tpl +0 -0
  85. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/08-scheduler.md.tpl +0 -0
  86. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/09-tasks.md.tpl +0 -0
  87. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/10-storage.md.tpl +0 -0
  88. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/11-logging.md.tpl +0 -0
  89. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/12-admin.md.tpl +0 -0
  90. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/13-channel.md.tpl +0 -0
  91. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/14-mq.md.tpl +0 -0
  92. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/15-events.md.tpl +0 -0
  93. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/16-adapter.md.tpl +0 -0
  94. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/17-alerting.md.tpl +0 -0
  95. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/aury_docs/99-cli.md.tpl +0 -0
  96. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/config.py.tpl +0 -0
  97. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/conftest.py.tpl +0 -0
  98. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/env_templates/_header.tpl +0 -0
  99. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/env_templates/admin.tpl +0 -0
  100. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/env_templates/cache.tpl +0 -0
  101. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/env_templates/database.tpl +0 -0
  102. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/env_templates/log.tpl +0 -0
  103. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/env_templates/messaging.tpl +0 -0
  104. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/env_templates/monitoring.tpl +0 -0
  105. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/env_templates/rpc.tpl +0 -0
  106. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/env_templates/scheduler.tpl +0 -0
  107. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/env_templates/service.tpl +0 -0
  108. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/env_templates/storage.tpl +0 -0
  109. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/env_templates/third_party.tpl +0 -0
  110. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/gitignore.tpl +0 -0
  111. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/main.py.tpl +0 -0
  112. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/modules/api.py.tpl +0 -0
  113. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/modules/exceptions.py.tpl +0 -0
  114. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/modules/schedules.py.tpl +0 -0
  115. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/templates/project/modules/tasks.py.tpl +0 -0
  116. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/commands/worker.py +0 -0
  117. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/common/__init__.py +0 -0
  118. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/common/exceptions/__init__.py +0 -0
  119. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/common/i18n/__init__.py +0 -0
  120. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/common/i18n/translator.py +0 -0
  121. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/common/logging/__init__.py +0 -0
  122. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/common/logging/context.py +0 -0
  123. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/common/logging/decorators.py +0 -0
  124. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/common/logging/format.py +0 -0
  125. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/common/logging/setup.py +0 -0
  126. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/contrib/__init__.py +0 -0
  127. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/contrib/admin_console/__init__.py +0 -0
  128. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/contrib/admin_console/auth.py +0 -0
  129. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/contrib/admin_console/discovery.py +0 -0
  130. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/contrib/admin_console/install.py +0 -0
  131. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/contrib/admin_console/utils.py +0 -0
  132. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/__init__.py +0 -0
  133. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/exceptions/__init__.py +0 -0
  134. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/models/__init__.py +0 -0
  135. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/models/base.py +0 -0
  136. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/models/mixins.py +0 -0
  137. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/models/models.py +0 -0
  138. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/pagination/__init__.py +0 -0
  139. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/repository/__init__.py +0 -0
  140. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/repository/impl.py +0 -0
  141. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/repository/interceptors.py +0 -0
  142. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/repository/interface.py +0 -0
  143. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/repository/query_builder.py +0 -0
  144. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/service/__init__.py +0 -0
  145. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/service/base.py +0 -0
  146. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/domain/transaction/__init__.py +0 -0
  147. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/__init__.py +0 -0
  148. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/cache/__init__.py +0 -0
  149. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/cache/exceptions.py +0 -0
  150. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/cache/factory.py +0 -0
  151. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/channel/__init__.py +0 -0
  152. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/channel/backends/__init__.py +0 -0
  153. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/channel/backends/broadcaster.py +0 -0
  154. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/channel/base.py +0 -0
  155. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/channel/manager.py +0 -0
  156. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/clients/__init__.py +0 -0
  157. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/clients/rabbitmq/__init__.py +0 -0
  158. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/clients/rabbitmq/config.py +0 -0
  159. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/clients/rabbitmq/manager.py +0 -0
  160. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/clients/redis/__init__.py +0 -0
  161. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/clients/redis/config.py +0 -0
  162. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/clients/redis/manager.py +0 -0
  163. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/database/__init__.py +0 -0
  164. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/database/config.py +0 -0
  165. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/database/exceptions.py +0 -0
  166. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/database/manager.py +0 -0
  167. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/database/query_tools/__init__.py +0 -0
  168. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/database/strategies/__init__.py +0 -0
  169. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/di/__init__.py +0 -0
  170. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/di/container.py +0 -0
  171. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/events/__init__.py +0 -0
  172. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/events/backends/__init__.py +0 -0
  173. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/events/backends/broadcaster.py +0 -0
  174. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/events/backends/rabbitmq.py +0 -0
  175. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/events/base.py +0 -0
  176. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/events/manager.py +0 -0
  177. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/events/middleware.py +0 -0
  178. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/__init__.py +0 -0
  179. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/alerting/__init__.py +0 -0
  180. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/alerting/aggregator.py +0 -0
  181. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/alerting/events.py +0 -0
  182. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/alerting/manager.py +0 -0
  183. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/alerting/notifiers/__init__.py +0 -0
  184. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/alerting/notifiers/base.py +0 -0
  185. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/alerting/notifiers/feishu.py +0 -0
  186. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/alerting/notifiers/webhook.py +0 -0
  187. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/alerting/rules.py +0 -0
  188. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/health/__init__.py +0 -0
  189. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/tracing/__init__.py +0 -0
  190. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/tracing/context.py +0 -0
  191. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/tracing/logging.py +0 -0
  192. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/tracing/processor.py +0 -0
  193. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/tracing/provider.py +0 -0
  194. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/monitoring/tracing/tracing.py +0 -0
  195. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/mq/__init__.py +0 -0
  196. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/mq/backends/__init__.py +0 -0
  197. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/mq/backends/rabbitmq.py +0 -0
  198. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/mq/base.py +0 -0
  199. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/mq/manager.py +0 -0
  200. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/scheduler/__init__.py +0 -0
  201. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/scheduler/exceptions.py +0 -0
  202. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/scheduler/manager.py +0 -0
  203. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/storage/__init__.py +0 -0
  204. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/storage/base.py +0 -0
  205. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/storage/exceptions.py +0 -0
  206. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/storage/factory.py +0 -0
  207. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/tasks/__init__.py +0 -0
  208. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/tasks/config.py +0 -0
  209. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/tasks/constants.py +0 -0
  210. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/tasks/exceptions.py +0 -0
  211. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/infrastructure/tasks/manager.py +0 -0
  212. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/testing/__init__.py +0 -0
  213. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/testing/base.py +0 -0
  214. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/testing/client.py +0 -0
  215. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/testing/factory.py +0 -0
  216. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/toolkit/__init__.py +0 -0
  217. {aury_boot-0.0.37 → aury_boot-0.0.39}/aury/boot/toolkit/http/__init__.py +0 -0
  218. {aury_boot-0.0.37 → aury_boot-0.0.39}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aury-boot
3
- Version: 0.0.37
3
+ Version: 0.0.39
4
4
  Summary: Aury Boot - 基于 FastAPI 生态的企业级 API 开发框架
5
5
  Requires-Python: >=3.13
6
6
  Requires-Dist: alembic>=1.17.2
@@ -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.37'
32
- __version_tuple__ = version_tuple = (0, 0, 37)
31
+ __version__ = version = '0.0.39'
32
+ __version_tuple__ = version_tuple = (0, 0, 39)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -102,6 +102,18 @@ load_all_models(_model_modules)
102
102
  target_metadata = Base.metadata
103
103
 
104
104
 
105
+ # === 兼容性处理 ===
106
+ # 过滤 PostgreSQL 15+ 特有的约束参数,确保生成的 migration 兼容旧版本 PG
107
+ _PG15_CONSTRAINT_KWARGS = {{"postgresql_nulls_not_distinct", "postgresql_include"}}
108
+
109
+ def _render_item(type_, obj, autogen_context):
110
+ """自定义渲染,过滤不兼容的约束参数。"""
111
+ if type_ == "unique_constraint" and hasattr(obj, "kwargs"):
112
+ for key in _PG15_CONSTRAINT_KWARGS:
113
+ obj.kwargs.pop(key, None)
114
+ return False # 使用默认渲染
115
+
116
+
105
117
  def get_url() -> str:
106
118
  """获取数据库 URL(优先环境变量,其次 alembic.ini)。"""
107
119
  return os.environ.get("DATABASE_URL") or config.get_main_option("sqlalchemy.url", "")
@@ -117,8 +129,8 @@ def run_migrations_offline() -> None:
117
129
  dialect_opts={{"paramstyle": "named"}},
118
130
  compare_type=True,
119
131
  compare_server_default=True,
120
- # 启用 batch 模式以更好地支持 SQLite 等不完整 DDL 的后端
121
132
  render_as_batch=True,
133
+ render_item=_render_item,
122
134
  )
123
135
  with context.begin_transaction():
124
136
  context.run_migrations()
@@ -131,8 +143,8 @@ def _do_run_migrations(connection) -> None:
131
143
  target_metadata=target_metadata,
132
144
  compare_type=True,
133
145
  compare_server_default=True,
134
- # 启用 batch 模式以更好地支持 SQLite 等不完整 DDL 的后端
135
146
  render_as_batch=True,
147
+ render_item=_render_item,
136
148
  )
137
149
  with context.begin_transaction():
138
150
  context.run_migrations()
@@ -0,0 +1,14 @@
1
+ """缓存后端实现(兼容层)。
2
+
3
+ 实际实现在 redis.py 和 memory.py 中。
4
+ """
5
+
6
+ from .memory import MemcachedCache, MemoryCache
7
+ from .redis import RedisCache
8
+
9
+ __all__ = [
10
+ "MemcachedCache",
11
+ "MemoryCache",
12
+ "RedisCache",
13
+ ]
14
+
@@ -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
- from typing import Any, TypeVar
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 "未初始化"
@@ -1,208 +1,18 @@
1
- """缓存后端实现。
2
-
3
- 提供 Redis、Memory、Memcached 等缓存后端的实现。
4
- """
1
+ """内存和 Memcached 缓存后端实现。"""
5
2
 
6
3
  from __future__ import annotations
7
4
 
8
5
  import asyncio
9
- from collections.abc import Callable
10
- from datetime import timedelta
6
+ import fnmatch
11
7
  import json
12
- import pickle
13
- from typing import TYPE_CHECKING, Any
14
-
15
- from redis.asyncio import Redis
8
+ import time
9
+ from datetime import timedelta
10
+ from typing import Any
16
11
 
17
12
  from aury.boot.common.logging import logger
18
13
 
19
14
  from .base import ICache
20
15
 
21
- if TYPE_CHECKING:
22
- from aury.boot.infrastructure.clients.redis import RedisClient
23
-
24
-
25
- class RedisCache(ICache):
26
- """Redis缓存实现。
27
-
28
- 支持两种初始化方式:
29
- 1. 传入 URL 自行创建连接
30
- 2. 传入 RedisClient 实例(推荐)
31
- """
32
-
33
- def __init__(
34
- self,
35
- url: str | None = None,
36
- *,
37
- redis_client: RedisClient | None = None,
38
- serializer: str = "json",
39
- ):
40
- """初始化Redis缓存。
41
-
42
- Args:
43
- url: Redis连接URL
44
- redis_client: RedisClient 实例(推荐)
45
- serializer: 序列化方式(json/pickle)
46
- """
47
- self._url = url
48
- self._redis_client = redis_client
49
- self._serializer = serializer
50
- self._redis: Redis | None = None
51
- self._owns_connection = False # 是否自己拥有连接(需要自己关闭)
52
-
53
- async def initialize(self) -> None:
54
- """初始化连接。"""
55
- # 优先使用 RedisClient
56
- if self._redis_client is not None:
57
- self._redis = self._redis_client.connection
58
- self._owns_connection = False
59
- logger.info("Redis缓存初始化成功(使用 RedisClient)")
60
- return
61
-
62
- # 使用 URL 创建连接
63
- if self._url:
64
- try:
65
- self._redis = Redis.from_url(
66
- self._url,
67
- encoding="utf-8",
68
- decode_responses=False,
69
- socket_connect_timeout=5,
70
- socket_timeout=5,
71
- )
72
- await self._redis.ping()
73
- self._owns_connection = True
74
- logger.info("Redis缓存初始化成功")
75
- except Exception as exc:
76
- logger.error(f"Redis连接失败: {exc}")
77
- raise
78
- else:
79
- raise ValueError("Redis缓存需要提供 url 或 redis_client 参数")
80
-
81
- async def get(self, key: str, default: Any = None) -> Any:
82
- """获取缓存。"""
83
- if not self._redis:
84
- return default
85
-
86
- try:
87
- data = await self._redis.get(key)
88
- if data is None:
89
- return default
90
-
91
- # 使用函数式编程处理序列化器
92
- deserializers: dict[str, Callable[[bytes], Any]] = {
93
- "json": lambda d: json.loads(d.decode()),
94
- "pickle": pickle.loads,
95
- }
96
-
97
- deserializer = deserializers.get(self._serializer)
98
- if deserializer:
99
- return deserializer(data)
100
- return data.decode()
101
- except Exception as exc:
102
- logger.error(f"Redis获取失败: {key}, {exc}")
103
- return default
104
-
105
- async def set(
106
- self,
107
- key: str,
108
- value: Any,
109
- expire: int | timedelta | None = None,
110
- ) -> bool:
111
- """设置缓存。"""
112
- if not self._redis:
113
- return False
114
-
115
- try:
116
- # 使用函数式编程处理序列化器
117
- serializers: dict[str, Callable[[Any], bytes]] = {
118
- "json": lambda v: json.dumps(v).encode(),
119
- "pickle": pickle.dumps,
120
- }
121
-
122
- serializer = serializers.get(self._serializer)
123
- if serializer:
124
- data = serializer(value)
125
- else:
126
- data = str(value).encode()
127
-
128
- # 转换过期时间
129
- if isinstance(expire, timedelta):
130
- expire = int(expire.total_seconds())
131
-
132
- await self._redis.set(key, data, ex=expire)
133
- return True
134
- except Exception as exc:
135
- logger.error(f"Redis设置失败: {key}, {exc}")
136
- return False
137
-
138
- async def delete(self, *keys: str) -> int:
139
- """删除缓存。"""
140
- if not self._redis or not keys:
141
- return 0
142
-
143
- try:
144
- return await self._redis.delete(*keys)
145
- except Exception as exc:
146
- logger.error(f"Redis删除失败: {keys}, {exc}")
147
- return 0
148
-
149
- async def exists(self, *keys: str) -> int:
150
- """检查缓存是否存在。"""
151
- if not self._redis or not keys:
152
- return 0
153
-
154
- try:
155
- return await self._redis.exists(*keys)
156
- except Exception as exc:
157
- logger.error(f"Redis检查失败: {keys}, {exc}")
158
- return 0
159
-
160
- async def clear(self) -> None:
161
- """清空所有缓存。"""
162
- if self._redis:
163
- await self._redis.flushdb()
164
- logger.info("Redis缓存已清空")
165
-
166
- async def delete_pattern(self, pattern: str) -> int:
167
- """按模式删除缓存。
168
-
169
- Args:
170
- pattern: 通配符模式,如 "todo:*"
171
-
172
- Returns:
173
- int: 删除的键数量
174
- """
175
- if not self._redis:
176
- return 0
177
-
178
- try:
179
- # 使用 SCAN 遍历匹配的键(比 KEYS 更安全,不会阻塞)
180
- count = 0
181
- cursor = 0
182
- while True:
183
- cursor, keys = await self._redis.scan(cursor, match=pattern, count=100)
184
- if keys:
185
- count += await self._redis.delete(*keys)
186
- if cursor == 0:
187
- break
188
- logger.debug(f"按模式删除缓存: {pattern}, 删除 {count} 个键")
189
- return count
190
- except Exception as exc:
191
- logger.error(f"Redis模式删除失败: {pattern}, {exc}")
192
- return 0
193
-
194
- async def close(self) -> None:
195
- """关闭连接(仅当自己拥有连接时)。"""
196
- if self._redis and self._owns_connection:
197
- await self._redis.close()
198
- logger.info("Redis连接已关闭")
199
- self._redis = None
200
-
201
- @property
202
- def redis(self) -> Redis | None:
203
- """获取Redis客户端。"""
204
- return self._redis
205
-
206
16
 
207
17
  class MemoryCache(ICache):
208
18
  """内存缓存实现。"""
@@ -295,8 +105,6 @@ class MemoryCache(ICache):
295
105
  Returns:
296
106
  int: 删除的键数量
297
107
  """
298
- import fnmatch
299
-
300
108
  async with self._lock:
301
109
  keys_to_delete = [
302
110
  key for key in self._cache
@@ -314,6 +122,60 @@ class MemoryCache(ICache):
314
122
  async def size(self) -> int:
315
123
  """获取缓存大小。"""
316
124
  return len(self._cache)
125
+
126
+ # ==================== 内存锁 ====================
127
+
128
+ async def acquire_lock(
129
+ self,
130
+ key: str,
131
+ token: str,
132
+ timeout: int,
133
+ blocking: bool,
134
+ blocking_timeout: float | None,
135
+ ) -> bool:
136
+ """获取内存锁(单进程)。"""
137
+ start_time = time.monotonic()
138
+
139
+ while True:
140
+ async with self._lock:
141
+ # 检查锁是否存在
142
+ if key not in self._cache:
143
+ # 设置锁
144
+ expire_at = asyncio.get_event_loop().time() + timeout
145
+ self._cache[key] = (token, expire_at)
146
+ return True
147
+
148
+ # 检查锁是否过期
149
+ existing_token, expire_at = self._cache[key]
150
+ if expire_at is not None and asyncio.get_event_loop().time() > expire_at:
151
+ # 锁已过期,重新获取
152
+ new_expire_at = asyncio.get_event_loop().time() + timeout
153
+ self._cache[key] = (token, new_expire_at)
154
+ return True
155
+
156
+ if not blocking:
157
+ return False
158
+
159
+ # 检查是否超时
160
+ if blocking_timeout is not None:
161
+ elapsed = time.monotonic() - start_time
162
+ if elapsed >= blocking_timeout:
163
+ return False
164
+
165
+ # 短暂等待后重试
166
+ await asyncio.sleep(0.05)
167
+
168
+ async def release_lock(self, key: str, token: str) -> bool:
169
+ """释放内存锁。"""
170
+ async with self._lock:
171
+ if key not in self._cache:
172
+ return False
173
+
174
+ existing_token, _ = self._cache[key]
175
+ if existing_token == token:
176
+ del self._cache[key]
177
+ return True
178
+ return False
317
179
 
318
180
 
319
181
  class MemcachedCache(ICache):
@@ -323,7 +185,7 @@ class MemcachedCache(ICache):
323
185
  """初始化Memcached缓存。
324
186
 
325
187
  Args:
326
- servers: Memcached服务器列表,如 ["127.0.0.1:11211"]
188
+ servers: Memcached服务器列表,如 ["*********:11211"]
327
189
  """
328
190
  self._servers = servers
329
191
  self._client = None
@@ -422,11 +284,23 @@ class MemcachedCache(ICache):
422
284
  if self._client:
423
285
  self._client.close()
424
286
  logger.info("Memcached连接已关闭")
287
+
288
+ # Memcached 不支持分布式锁
289
+ async def acquire_lock(
290
+ self,
291
+ key: str,
292
+ token: str,
293
+ timeout: int,
294
+ blocking: bool,
295
+ blocking_timeout: float | None,
296
+ ) -> bool:
297
+ """获取锁(Memcached 不支持)。"""
298
+ logger.warning("Memcached 不支持分布式锁,请使用 Redis 或 Memory 后端")
299
+ return False
300
+
301
+ async def release_lock(self, key: str, token: str) -> bool:
302
+ """释放锁(Memcached 不支持)。"""
303
+ return False
425
304
 
426
305
 
427
- __all__ = [
428
- "MemcachedCache",
429
- "MemoryCache",
430
- "RedisCache",
431
- ]
432
-
306
+ __all__ = ["MemcachedCache", "MemoryCache"]