GeneralManager 0.51.0__tar.gz → 0.52.0__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 (202) hide show
  1. {generalmanager-0.51.0/src/GeneralManager.egg-info → generalmanager-0.52.0}/PKG-INFO +1 -1
  2. {generalmanager-0.51.0 → generalmanager-0.52.0}/pyproject.toml +1 -1
  3. {generalmanager-0.51.0 → generalmanager-0.52.0/src/GeneralManager.egg-info}/PKG-INFO +1 -1
  4. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/GeneralManager.egg-info/SOURCES.txt +2 -0
  5. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/cache/dependency_index.py +237 -220
  6. generalmanager-0.52.0/src/general_manager/cache/dependency_matching.py +242 -0
  7. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/cache/dependency_publish.py +9 -16
  8. generalmanager-0.52.0/src/general_manager/cache/dependency_shards.py +414 -0
  9. {generalmanager-0.51.0 → generalmanager-0.52.0}/LICENSE +0 -0
  10. {generalmanager-0.51.0 → generalmanager-0.52.0}/README.md +0 -0
  11. {generalmanager-0.51.0 → generalmanager-0.52.0}/setup.cfg +0 -0
  12. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
  13. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/GeneralManager.egg-info/requires.txt +0 -0
  14. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/GeneralManager.egg-info/top_level.txt +0 -0
  15. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/__init__.py +0 -0
  16. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/_types/__init__.py +0 -0
  17. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/_types/api.py +0 -0
  18. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/_types/bucket.py +0 -0
  19. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/_types/cache.py +0 -0
  20. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/_types/factory.py +0 -0
  21. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/_types/general_manager.py +0 -0
  22. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/_types/interface.py +0 -0
  23. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/_types/manager.py +0 -0
  24. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/_types/measurement.py +0 -0
  25. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/_types/permission.py +0 -0
  26. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/_types/rule.py +0 -0
  27. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/_types/search.py +0 -0
  28. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/_types/utils.py +0 -0
  29. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/__init__.py +0 -0
  30. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/graphql.py +0 -0
  31. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/graphql_errors.py +0 -0
  32. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/graphql_mutations.py +0 -0
  33. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/graphql_prefetch.py +0 -0
  34. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/graphql_resolvers.py +0 -0
  35. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/graphql_search.py +0 -0
  36. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
  37. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/graphql_subscriptions.py +0 -0
  38. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/graphql_view.py +0 -0
  39. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/mutation.py +0 -0
  40. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/property.py +0 -0
  41. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/registry.py +0 -0
  42. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/remote_api.py +0 -0
  43. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/remote_invalidation.py +0 -0
  44. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/api/remote_invalidation_client.py +0 -0
  45. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/apps.py +0 -0
  46. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/bootstrap.py +0 -0
  47. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/bucket/__init__.py +0 -0
  48. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/bucket/base_bucket.py +0 -0
  49. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/bucket/calculation_bucket.py +0 -0
  50. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/bucket/database_bucket.py +0 -0
  51. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/bucket/group_bucket.py +0 -0
  52. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/bucket/indexing.py +0 -0
  53. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/bucket/request_bucket.py +0 -0
  54. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/cache/__init__.py +0 -0
  55. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/cache/cache_decorator.py +0 -0
  56. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/cache/cache_tracker.py +0 -0
  57. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/cache/dependency_cache.py +0 -0
  58. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/cache/model_dependency_collector.py +0 -0
  59. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/cache/run_context.py +0 -0
  60. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/cache/signals.py +0 -0
  61. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/conf.py +0 -0
  62. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/factory/__init__.py +0 -0
  63. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/factory/auto_factory.py +0 -0
  64. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/factory/factories.py +0 -0
  65. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/factory/factory_methods.py +0 -0
  66. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/__init__.py +0 -0
  67. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/base_interface.py +0 -0
  68. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/bundles/__init__.py +0 -0
  69. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/bundles/calculation.py +0 -0
  70. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/bundles/database.py +0 -0
  71. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/bundles/remote_manager.py +0 -0
  72. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/bundles/request.py +0 -0
  73. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/__init__.py +0 -0
  74. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/base.py +0 -0
  75. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/builtin.py +0 -0
  76. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
  77. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
  78. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
  79. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/configuration.py +0 -0
  80. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/core/observability.py +0 -0
  81. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/core/utils.py +0 -0
  82. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/exceptions.py +0 -0
  83. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
  84. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
  85. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
  86. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/factory.py +0 -0
  87. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
  88. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
  89. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/orm/history.py +0 -0
  90. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
  91. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/orm/mutations.py +0 -0
  92. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/orm/support.py +0 -0
  93. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
  94. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
  95. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
  96. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
  97. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
  98. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
  99. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
  100. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
  101. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/registry.py +0 -0
  102. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
  103. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
  104. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/infrastructure/__init__.py +0 -0
  105. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
  106. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
  107. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/interfaces/__init__.py +0 -0
  108. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/interfaces/calculation.py +0 -0
  109. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/interfaces/database.py +0 -0
  110. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/interfaces/existing_model.py +0 -0
  111. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/interfaces/read_only.py +0 -0
  112. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
  113. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/interfaces/request.py +0 -0
  114. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/manifests/__init__.py +0 -0
  115. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/manifests/capability_builder.py +0 -0
  116. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
  117. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/manifests/capability_models.py +0 -0
  118. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/orm_interface.py +0 -0
  119. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/requests.py +0 -0
  120. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/utils/__init__.py +0 -0
  121. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
  122. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/utils/errors.py +0 -0
  123. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/interface/utils/models.py +0 -0
  124. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/logging.py +0 -0
  125. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/management/commands/search_index.py +0 -0
  126. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
  127. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/management/commands/shell.py +0 -0
  128. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
  129. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
  130. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/manager/__init__.py +0 -0
  131. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/manager/general_manager.py +0 -0
  132. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/manager/group_manager.py +0 -0
  133. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/manager/input.py +0 -0
  134. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/manager/meta.py +0 -0
  135. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/measurement/__init__.py +0 -0
  136. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/measurement/measurement.py +0 -0
  137. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/measurement/measurement_field.py +0 -0
  138. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/metrics/__init__.py +0 -0
  139. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/metrics/graphql.py +0 -0
  140. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/migrations/0001_initial.py +0 -0
  141. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
  142. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
  143. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/migrations/__init__.py +0 -0
  144. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/models.py +0 -0
  145. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/permission/__init__.py +0 -0
  146. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/permission/audit.py +0 -0
  147. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/permission/base_permission.py +0 -0
  148. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/permission/graphql_capabilities.py +0 -0
  149. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/permission/manager_based_permission.py +0 -0
  150. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/permission/mutation_permission.py +0 -0
  151. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/permission/permission_checks.py +0 -0
  152. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/permission/permission_data_manager.py +0 -0
  153. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/permission/utils.py +0 -0
  154. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/public_api_registry.py +0 -0
  155. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/py.typed +0 -0
  156. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/rule/__init__.py +0 -0
  157. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/rule/handler.py +0 -0
  158. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/rule/rule.py +0 -0
  159. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/search/__init__.py +0 -0
  160. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/search/async_tasks.py +0 -0
  161. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/search/backend.py +0 -0
  162. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/search/backend_registry.py +0 -0
  163. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/search/backends/__init__.py +0 -0
  164. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/search/backends/dev.py +0 -0
  165. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/search/backends/meilisearch.py +0 -0
  166. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/search/backends/opensearch.py +0 -0
  167. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/search/backends/typesense.py +0 -0
  168. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/search/config.py +0 -0
  169. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/search/indexer.py +0 -0
  170. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/search/registry.py +0 -0
  171. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/search/utils.py +0 -0
  172. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/seeding/__init__.py +0 -0
  173. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/seeding/manager_landscape.py +0 -0
  174. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/utils/__init__.py +0 -0
  175. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/utils/args_to_kwargs.py +0 -0
  176. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/utils/filter_parser.py +0 -0
  177. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/utils/format_string.py +0 -0
  178. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/utils/json_encoder.py +0 -0
  179. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/utils/make_cache_key.py +0 -0
  180. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/utils/none_to_zero.py +0 -0
  181. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/utils/path_mapping.py +0 -0
  182. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/utils/public_api.py +0 -0
  183. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/utils/testing.py +0 -0
  184. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/utils/type_checks.py +0 -0
  185. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/__init__.py +0 -0
  186. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/actions.py +0 -0
  187. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/backend_registry.py +0 -0
  188. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/backends/__init__.py +0 -0
  189. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/backends/celery.py +0 -0
  190. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/backends/local.py +0 -0
  191. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/backends/n8n.py +0 -0
  192. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/config.py +0 -0
  193. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/engine.py +0 -0
  194. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/event_registry.py +0 -0
  195. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/events.py +0 -0
  196. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/models.py +0 -0
  197. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/signal_bridge.py +0 -0
  198. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/tasks.py +0 -0
  199. {generalmanager-0.51.0 → generalmanager-0.52.0}/src/general_manager/workflow/telemetry.py +0 -0
  200. {generalmanager-0.51.0 → generalmanager-0.52.0}/tests/test_settings.py +0 -0
  201. {generalmanager-0.51.0 → generalmanager-0.52.0}/tests/test_urls.py +0 -0
  202. {generalmanager-0.51.0 → generalmanager-0.52.0}/tests/testing_asgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.51.0
3
+ Version: 0.52.0
4
4
  Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
5
5
  Author-email: Tim Kleindick <tkleindick@yahoo.de>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "GeneralManager"
7
- version = "0.51.0"
7
+ version = "0.52.0"
8
8
  description = "Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching."
9
9
  readme = "README.md"
10
10
  authors = [{ name = "Tim Kleindick", email = "tkleindick@yahoo.de" }]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.51.0
3
+ Version: 0.52.0
4
4
  Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
5
5
  Author-email: Tim Kleindick <tkleindick@yahoo.de>
6
6
  License: MIT License
@@ -55,7 +55,9 @@ src/general_manager/cache/cache_decorator.py
55
55
  src/general_manager/cache/cache_tracker.py
56
56
  src/general_manager/cache/dependency_cache.py
57
57
  src/general_manager/cache/dependency_index.py
58
+ src/general_manager/cache/dependency_matching.py
58
59
  src/general_manager/cache/dependency_publish.py
60
+ src/general_manager/cache/dependency_shards.py
59
61
  src/general_manager/cache/model_dependency_collector.py
60
62
  src/general_manager/cache/run_context.py
61
63
  src/general_manager/cache/signals.py
@@ -4,7 +4,6 @@ from __future__ import annotations
4
4
 
5
5
  import json
6
6
  import random
7
- import re
8
7
  import time
9
8
  from datetime import date, datetime
10
9
  from typing import TYPE_CHECKING, Any, Iterable, Literal, Tuple, Type, cast
@@ -12,6 +11,26 @@ from typing import TYPE_CHECKING, Any, Iterable, Literal, Tuple, Type, cast
12
11
  from django.core.cache import cache
13
12
  from django.dispatch import receiver
14
13
 
14
+ from general_manager.cache.dependency_matching import (
15
+ current_value_for_path as resolve_current_value_for_path,
16
+ lookup_spec_from_key,
17
+ matches_lookup_value,
18
+ normalize_dependency_value,
19
+ parse_dependency_identifier,
20
+ serialize_normalized_value,
21
+ )
22
+ from general_manager.cache.dependency_shards import (
23
+ ReverseDependencyMembership,
24
+ all_records_cache_keys,
25
+ candidate_cache_keys_for_lookup,
26
+ record_cache_dependencies,
27
+ record_many_cache_dependencies,
28
+ remove_cache_key_from_shards,
29
+ request_query_cache_keys,
30
+ reverse_membership_key,
31
+ reverse_memberships,
32
+ tracked_lookup_names,
33
+ )
15
34
  from general_manager.cache.signals import post_data_change, pre_data_change
16
35
  from general_manager.logging import get_logger
17
36
 
@@ -222,7 +241,10 @@ def get_full_index() -> dependency_index:
222
241
  "request_query": {},
223
242
  "all": {},
224
243
  }
225
- cache.set(INDEX_KEY, idx, None)
244
+ for reverse in reverse_memberships():
245
+ dependencies: set[Dependency] = set(reverse.simple_dependencies)
246
+ dependencies.update(reverse.composite_dependencies)
247
+ _record_dependencies_locked(idx, reverse.cache_key, dependencies)
226
248
  return idx
227
249
  idx = cast(dependency_index, cached_index)
228
250
  changed = False
@@ -253,37 +275,12 @@ def set_full_index(idx: dependency_index) -> None:
253
275
 
254
276
  def _normalize_dependency_identifier(value: Any) -> Any:
255
277
  """Return a JSON-serializable representation for dependency tracking."""
256
- if isinstance(value, dict):
257
- return {
258
- str(key): _normalize_dependency_identifier(val)
259
- for key, val in value.items()
260
- }
261
- if isinstance(value, (list, tuple)):
262
- return [_normalize_dependency_identifier(item) for item in value]
263
- if isinstance(value, set):
264
- return [
265
- _normalize_dependency_identifier(item) for item in sorted(value, key=str)
266
- ]
267
- if isinstance(value, datetime):
268
- return value.isoformat()
269
- if isinstance(value, date):
270
- return value.isoformat()
271
- if isinstance(value, (str, int, float, bool)) or value is None:
272
- return value
273
- return {"__repr__": repr(value)}
278
+ return normalize_dependency_value(value)
274
279
 
275
280
 
276
281
  def serialize_dependency_identifier(value: Any) -> str:
277
282
  """Serialize dependency payloads using a deterministic literal-safe format."""
278
- return json.dumps(_normalize_dependency_identifier(value), sort_keys=True)
279
-
280
-
281
- def parse_dependency_identifier(identifier: str) -> Any:
282
- """Parse a JSON-serialized dependency identifier, returning None on failure."""
283
- try:
284
- return json.loads(identifier)
285
- except (json.JSONDecodeError, ValueError):
286
- return None
283
+ return serialize_normalized_value(value)
287
284
 
288
285
 
289
286
  # -----------------------------------------------------------------------------
@@ -364,9 +361,7 @@ def record_dependencies(
364
361
  """
365
362
  acquire_lock_with_retry("record_dependencies")
366
363
  try:
367
- idx = get_full_index()
368
- _record_dependencies_locked(idx, cache_key, dependencies)
369
- set_full_index(idx)
364
+ record_cache_dependencies(cache_key, dependencies)
370
365
  finally:
371
366
  release_lock()
372
367
 
@@ -387,10 +382,7 @@ def record_many_dependencies(
387
382
 
388
383
  acquire_lock_with_retry("record_many_dependencies")
389
384
  try:
390
- idx = get_full_index()
391
- for cache_key, dependencies in normalized.items():
392
- _record_dependencies_locked(idx, cache_key, dependencies)
393
- set_full_index(idx)
385
+ record_many_cache_dependencies(normalized.items())
394
386
  finally:
395
387
  release_lock()
396
388
 
@@ -412,50 +404,12 @@ def remove_cache_key_from_index(cache_key: str) -> None:
412
404
  """
413
405
  acquire_lock_with_retry("remove_cache_key_from_index")
414
406
  try:
415
- idx = get_full_index()
416
- all_section = cast(dict[str, set[str]], idx.get("all", {}))
417
- for mname, key_set in list(all_section.items()):
418
- if cache_key in key_set:
419
- key_set.remove(cache_key)
420
- if not key_set:
421
- del all_section[mname]
422
- for action in ACTIONS:
423
- action_section = cast(
424
- dict[general_manager_name, manager_dependency_section],
425
- idx[action],
426
- )
427
- for mname, model_section in list(action_section.items()):
428
- cache_dependencies = model_section.get("__cache_dependencies__", {})
429
- for lookup, lookup_map in list(model_section.items()):
430
- if lookup == "__cache_dependencies__":
431
- continue
432
- lookup_map = cast(lookup_dependency_map, lookup_map)
433
- for val_key, key_set in list(lookup_map.items()):
434
- if cache_key in key_set:
435
- key_set.remove(cache_key)
436
- if not key_set:
437
- del lookup_map[val_key]
438
- if not lookup_map:
439
- del model_section[lookup]
440
- if cache_dependencies:
441
- cache_dependencies.pop(cache_key, None)
442
- if not cache_dependencies:
443
- model_section.pop("__cache_dependencies__", None)
444
- if not model_section:
445
- del action_section[mname]
446
- request_query_section = cast(
447
- dict[str, dict[str, set[str]]],
448
- idx.get("request_query", {}),
449
- )
450
- for mname, query_section in list(request_query_section.items()):
451
- for identifier, key_set in list(query_section.items()):
452
- if cache_key in key_set:
453
- key_set.remove(cache_key)
454
- if not key_set:
455
- del query_section[identifier]
456
- if not query_section:
457
- del request_query_section[mname]
458
- set_full_index(idx)
407
+ if cache.get(INDEX_KEY, None) is not None and not reverse_memberships():
408
+ idx = get_full_index()
409
+ _remove_cache_keys_from_index_locked(idx, (cache_key,))
410
+ set_full_index(idx)
411
+ return
412
+ remove_cache_key_from_shards(cache_key)
459
413
  finally:
460
414
  release_lock()
461
415
 
@@ -541,11 +495,16 @@ def invalidate_and_remove_cache_keys(cache_keys: Iterable[str]) -> None:
541
495
  return
542
496
  acquire_lock_with_retry("invalidate_and_remove_cache_keys")
543
497
  try:
544
- idx = get_full_index()
498
+ if cache.get(INDEX_KEY, None) is not None and not reverse_memberships():
499
+ idx = get_full_index()
500
+ for cache_key in keys:
501
+ cache.delete(cache_key)
502
+ _remove_cache_keys_from_index_locked(idx, keys)
503
+ set_full_index(idx)
504
+ return
545
505
  for cache_key in keys:
546
506
  cache.delete(cache_key)
547
- _remove_cache_keys_from_index_locked(idx, keys)
548
- set_full_index(idx)
507
+ remove_cache_key_from_shards(cache_key)
549
508
  finally:
550
509
  release_lock()
551
510
 
@@ -578,12 +537,19 @@ def invalidate_request_query_dependencies(manager_name: str) -> tuple[str, ...]:
578
537
  """
579
538
  acquire_lock_with_retry("invalidate_request_query_dependencies")
580
539
  try:
581
- idx = get_full_index()
582
- invalidated_keys = _invalidate_request_query_dependencies_locked(
583
- idx, manager_name
584
- )
585
- if invalidated_keys:
586
- set_full_index(idx)
540
+ if cache.get(INDEX_KEY, None) is not None and not reverse_memberships():
541
+ idx = get_full_index()
542
+ invalidated_keys = _invalidate_request_query_dependencies_locked(
543
+ idx,
544
+ manager_name,
545
+ )
546
+ if invalidated_keys:
547
+ set_full_index(idx)
548
+ return invalidated_keys
549
+ invalidated_keys = tuple(dict.fromkeys(request_query_cache_keys(manager_name)))
550
+ for cache_key in invalidated_keys:
551
+ cache.delete(cache_key)
552
+ remove_cache_key_from_shards(cache_key)
587
553
  return invalidated_keys
588
554
  finally:
589
555
  release_lock()
@@ -604,23 +570,23 @@ def capture_old_values(
604
570
  if instance is None:
605
571
  return
606
572
  manager_name = sender.__name__
607
- idx = get_full_index()
608
- # get all lookups for this model
609
- lookups = set()
610
- for action in ACTIONS:
611
- model_section = idx[action].get(manager_name)
612
- if isinstance(model_section, dict):
613
- for lookup in model_section.keys():
614
- if not isinstance(lookup, str):
615
- continue
616
- if lookup.startswith("__sort__"):
617
- lookups.add(lookup.removeprefix("__sort__"))
618
- continue
619
- if lookup.startswith("__"):
620
- continue
621
- lookups.add(lookup)
622
- elif isinstance(model_section, list):
623
- lookups |= set(model_section)
573
+ lookups = tracked_lookup_names(manager_name)
574
+ if not lookups and not reverse_memberships():
575
+ idx = get_full_index()
576
+ for action in ACTIONS:
577
+ model_section = idx[action].get(manager_name)
578
+ if isinstance(model_section, dict):
579
+ for lookup in model_section.keys():
580
+ if not isinstance(lookup, str):
581
+ continue
582
+ if lookup.startswith("__sort__"):
583
+ lookups.add(lookup.removeprefix("__sort__"))
584
+ continue
585
+ if lookup.startswith("__"):
586
+ continue
587
+ lookups.add(lookup)
588
+ elif isinstance(model_section, list):
589
+ lookups |= set(model_section)
624
590
  if lookups and instance.identification:
625
591
  # save old values for later comparison
626
592
  vals: dict[str, object] = {}
@@ -764,116 +730,8 @@ def _generic_cache_invalidation_locked(
764
730
  return None
765
731
 
766
732
  def matches(op: str, value: Any, val_key: Any) -> bool:
767
- """
768
- Evaluate whether a given value satisfies a lookup operation described by `op` and `val_key`.
769
-
770
- Supports operators:
771
- - "eq": equality; attempts to interpret `val_key` as a literal and coerce it to `value`'s type before comparing.
772
- - "in": membership; expects `val_key` to be a literal iterable and checks if any coerced element equals `value`.
773
- - "gt", "gte", "lt", "lte": numeric/date comparisons; `val_key` is interpreted as a literal and coerced to `value`'s type.
774
- - "contains", "startswith", "endswith": string containment/prefix/suffix checks; both sides are compared as strings.
775
- - "regex": treats `val_key` as a regular expression pattern and tests it against the string form of `value`.
776
-
777
- Behavior notes:
778
- - If `value` is None the function only matches explicit null equality
779
- or membership checks.
780
- - ``val_key`` is a JSON-serialised string produced by
781
- :func:`json.dumps`. Parsing is done with :func:`json.loads`; if
782
- JSON parsing or type coercion fails, the function falls back to
783
- conservative comparisons or returns ``False`` where appropriate.
784
- - Regex patterns that fail to compile are treated as non-matching.
785
-
786
- Parameters:
787
- op (str): The lookup operator name (one of the supported operators above).
788
- value (Any): The runtime value to test.
789
- val_key (Any): The stored comparison key (often a string representation) to interpret for the comparison.
790
-
791
- Returns:
792
- bool: `True` if the comparison defined by `op` and `val_key` matches `value`, `False` otherwise.
793
- """
794
- # eq
795
- if op == "eq":
796
- literal_val = _json_loads_val_key(val_key)
797
- if literal_val is None:
798
- return value is None
799
- repr_marker = _repr_marker(literal_val)
800
- if repr_marker is not None:
801
- return repr(value) == repr_marker
802
- comparable = _coerce_to_type(value, literal_val)
803
- if comparable is None:
804
- return repr(value) == val_key
805
- return value == comparable
806
-
807
- # in
808
- if op == "in":
809
- try:
810
- seq = json.loads(val_key)
811
- except (json.JSONDecodeError, ValueError):
812
- return False
813
- for item in seq:
814
- if item is None:
815
- if value is None:
816
- return True
817
- continue
818
- repr_marker = _repr_marker(item)
819
- if repr_marker is not None:
820
- if repr(value) == repr_marker:
821
- return True
822
- continue
823
- comparable = _coerce_to_type(value, item)
824
- if comparable is not None:
825
- if value == comparable:
826
- return True
827
- elif repr(value) == repr(item):
828
- return True
829
- return False
830
-
831
- # range comparisons
832
- if op in ("gt", "gte", "lt", "lte"):
833
- if value is None:
834
- return False
835
- literal_val = _json_loads_val_key(val_key)
836
- thr = _coerce_to_type(value, literal_val)
837
- if thr is None:
838
- return False
839
- if op == "gt":
840
- return value > thr
841
- if op == "gte":
842
- return value >= thr
843
- if op == "lt":
844
- return value < thr
845
- if op == "lte":
846
- return value <= thr
847
-
848
- # wildcard / regex comparisons
849
- if op in ("contains", "startswith", "endswith", "regex"):
850
- if value is None:
851
- return False
852
- try:
853
- literal = json.loads(val_key)
854
- except (json.JSONDecodeError, ValueError):
855
- literal = val_key
856
-
857
- # ensure we always work with strings to avoid TypeErrors
858
- text = "" if value is None else str(value)
859
- if op == "contains":
860
- return literal in text
861
- if op == "startswith":
862
- return text.startswith(literal)
863
- if op == "endswith":
864
- return text.endswith(literal)
865
- # regex: treat the stored key as the regex pattern
866
- if op == "regex":
867
- try:
868
- pattern_source = (
869
- literal if isinstance(literal, str) else str(literal)
870
- )
871
- pattern = re.compile(pattern_source)
872
- except re.error:
873
- return False
874
- return bool(pattern.search(text))
875
-
876
- return False
733
+ """Evaluate whether a runtime value matches a stored lookup value."""
734
+ return matches_lookup_value(op, value, val_key)
877
735
 
878
736
  def current_value_for_path(path: list[str]) -> Any:
879
737
  """
@@ -1184,6 +1042,155 @@ def _generic_cache_invalidation_locked(
1184
1042
  _remove_cache_keys_from_index_locked(idx, (ck,))
1185
1043
 
1186
1044
 
1045
+ def _generic_cache_invalidation_from_shards(
1046
+ manager_name: str,
1047
+ instance: GeneralManager,
1048
+ old_relevant_values: dict[str, Any],
1049
+ ) -> None:
1050
+ def value_for_lookup(lookup: str, *, use_old_values: bool) -> Any:
1051
+ spec = lookup_spec_from_key(lookup)
1052
+ lookup_name = "__".join(spec.attr_path)
1053
+ if use_old_values:
1054
+ return old_relevant_values.get(lookup_name)
1055
+ return resolve_current_value_for_path(instance, spec.attr_path)
1056
+
1057
+ def params_match(params: dict[str, Any], *, use_old_values: bool) -> bool:
1058
+ for lookup, expected in params.items():
1059
+ spec = lookup_spec_from_key(str(lookup))
1060
+ expected_key = serialize_dependency_identifier(expected)
1061
+ if not matches_lookup_value(
1062
+ spec.operator,
1063
+ value_for_lookup(spec.lookup, use_old_values=use_old_values),
1064
+ expected_key,
1065
+ ):
1066
+ return False
1067
+ return True
1068
+
1069
+ def dependency_matches(
1070
+ action: str,
1071
+ identifier: str,
1072
+ *,
1073
+ changed_lookup: str | None,
1074
+ ) -> bool:
1075
+ if action in {"all", "request_query"}:
1076
+ return True
1077
+ if action == "identification":
1078
+ identification = getattr(instance, "identification", None)
1079
+ return bool(
1080
+ identification
1081
+ and serialize_dependency_identifier(identification) == identifier
1082
+ )
1083
+ if action not in ACTIONS:
1084
+ return False
1085
+ params = parse_dependency_identifier(identifier)
1086
+ if not isinstance(params, dict):
1087
+ return False
1088
+ if not params:
1089
+ return True
1090
+
1091
+ sort_payloads = [
1092
+ payload
1093
+ for lookup, payload in params.items()
1094
+ if str(lookup).startswith("__sort__")
1095
+ and (
1096
+ changed_lookup is None
1097
+ or str(lookup).removeprefix("__sort__") == changed_lookup
1098
+ )
1099
+ ]
1100
+ if sort_payloads:
1101
+ for payload in sort_payloads:
1102
+ if not isinstance(payload, dict):
1103
+ continue
1104
+ filters = payload.get("filters", {})
1105
+ excludes = payload.get("excludes", {})
1106
+ if not isinstance(filters, dict) or not isinstance(excludes, dict):
1107
+ continue
1108
+ old_in_bucket = params_match(filters, use_old_values=True) and not (
1109
+ params_match(excludes, use_old_values=True) if excludes else False
1110
+ )
1111
+ new_in_bucket = params_match(filters, use_old_values=False) and not (
1112
+ params_match(excludes, use_old_values=False) if excludes else False
1113
+ )
1114
+ if old_in_bucket or new_in_bucket:
1115
+ return True
1116
+ return False
1117
+
1118
+ old_match = params_match(params, use_old_values=True)
1119
+ new_match = params_match(params, use_old_values=False)
1120
+ if action == "filter":
1121
+ return old_match or new_match
1122
+ return old_match != new_match
1123
+
1124
+ def candidate_should_invalidate(
1125
+ cache_key: str,
1126
+ action: str,
1127
+ changed_lookup: str | None,
1128
+ ) -> bool:
1129
+ reverse = cache.get(reverse_membership_key(cache_key))
1130
+ if not isinstance(reverse, ReverseDependencyMembership):
1131
+ return True
1132
+ for manager, dependency_action, identifier in reverse.simple_dependencies:
1133
+ if manager == manager_name and dependency_matches(
1134
+ dependency_action,
1135
+ identifier,
1136
+ changed_lookup=changed_lookup,
1137
+ ):
1138
+ return True
1139
+ for manager, dependency_action, identifier in reverse.composite_dependencies:
1140
+ if (
1141
+ manager == manager_name
1142
+ and dependency_action == action
1143
+ and dependency_matches(
1144
+ dependency_action,
1145
+ identifier,
1146
+ changed_lookup=changed_lookup,
1147
+ )
1148
+ ):
1149
+ return True
1150
+ return False
1151
+
1152
+ invalidation_candidates: set[str] = set()
1153
+
1154
+ invalidation_candidates.update(request_query_cache_keys(manager_name))
1155
+ invalidation_candidates.update(all_records_cache_keys(manager_name))
1156
+ identification = getattr(instance, "identification", None)
1157
+ if identification:
1158
+ invalidation_candidates.update(
1159
+ candidate_cache_keys_for_lookup(
1160
+ manager_name,
1161
+ "filter",
1162
+ "identification",
1163
+ old_value=serialize_dependency_identifier(identification),
1164
+ new_value=serialize_dependency_identifier(identification),
1165
+ )
1166
+ )
1167
+
1168
+ for lookup in tracked_lookup_names(manager_name):
1169
+ old_value = old_relevant_values.get(lookup)
1170
+ new_value = resolve_current_value_for_path(instance, tuple(lookup.split("__")))
1171
+ for action in ACTIONS:
1172
+ for cache_key in candidate_cache_keys_for_lookup(
1173
+ manager_name,
1174
+ action,
1175
+ lookup,
1176
+ old_value=old_value,
1177
+ new_value=new_value,
1178
+ ):
1179
+ if candidate_should_invalidate(cache_key, action, lookup):
1180
+ invalidation_candidates.add(cache_key)
1181
+
1182
+ for cache_key in tuple(dict.fromkeys(invalidation_candidates)):
1183
+ logger.info(
1184
+ "invalidating cache key",
1185
+ context={
1186
+ "manager": manager_name,
1187
+ "key": cache_key,
1188
+ },
1189
+ )
1190
+ cache.delete(cache_key)
1191
+ remove_cache_key_from_shards(cache_key)
1192
+
1193
+
1187
1194
  @receiver(post_data_change)
1188
1195
  def generic_cache_invalidation(
1189
1196
  sender: type[GeneralManager],
@@ -1204,13 +1211,23 @@ def generic_cache_invalidation(
1204
1211
  manager_name = sender.__name__
1205
1212
  acquire_lock_with_retry("generic_cache_invalidation")
1206
1213
  try:
1207
- idx = get_full_index()
1208
- _generic_cache_invalidation_locked(
1209
- idx,
1214
+ if not reverse_memberships():
1215
+ idx = get_full_index()
1216
+ sections: tuple[Literal["filter", "exclude", "all", "request_query"], ...]
1217
+ sections = ("filter", "exclude", "all", "request_query")
1218
+ if any(idx.get(section) for section in sections):
1219
+ _generic_cache_invalidation_locked(
1220
+ idx,
1221
+ manager_name,
1222
+ instance,
1223
+ old_relevant_values,
1224
+ )
1225
+ set_full_index(idx)
1226
+ return
1227
+ _generic_cache_invalidation_from_shards(
1210
1228
  manager_name,
1211
1229
  instance,
1212
1230
  old_relevant_values,
1213
1231
  )
1214
- set_full_index(idx)
1215
1232
  finally:
1216
1233
  release_lock()