GeneralManager 0.81.2__tar.gz → 0.81.4__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 (338) hide show
  1. {generalmanager-0.81.2/src/GeneralManager.egg-info → generalmanager-0.81.4}/PKG-INFO +1 -1
  2. {generalmanager-0.81.2 → generalmanager-0.81.4}/pyproject.toml +1 -1
  3. {generalmanager-0.81.2 → generalmanager-0.81.4/src/GeneralManager.egg-info}/PKG-INFO +1 -1
  4. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/dependency_index.py +163 -23
  5. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/signals.py +6 -6
  6. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/utils/testing.py +2 -0
  7. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/backends/celery.py +5 -3
  8. {generalmanager-0.81.2 → generalmanager-0.81.4}/LICENSE +0 -0
  9. {generalmanager-0.81.2 → generalmanager-0.81.4}/README.md +0 -0
  10. {generalmanager-0.81.2 → generalmanager-0.81.4}/setup.cfg +0 -0
  11. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/GeneralManager.egg-info/SOURCES.txt +0 -0
  12. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
  13. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/GeneralManager.egg-info/requires.txt +0 -0
  14. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/GeneralManager.egg-info/top_level.txt +0 -0
  15. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/__init__.py +0 -0
  16. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/_types/__init__.py +0 -0
  17. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/_types/api.py +0 -0
  18. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/_types/bucket.py +0 -0
  19. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/_types/cache.py +0 -0
  20. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/_types/dataframes.py +0 -0
  21. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/_types/factory.py +0 -0
  22. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/_types/general_manager.py +0 -0
  23. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/_types/interface.py +0 -0
  24. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/_types/manager.py +0 -0
  25. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/_types/measurement.py +0 -0
  26. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/_types/permission.py +0 -0
  27. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/_types/rule.py +0 -0
  28. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/_types/search.py +0 -0
  29. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/_types/utils.py +0 -0
  30. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/__init__.py +0 -0
  31. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql.py +0 -0
  32. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_as_of.py +0 -0
  33. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_errors.py +0 -0
  34. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_groups.py +0 -0
  35. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_mutations.py +0 -0
  36. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_ordering.py +0 -0
  37. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_output.py +0 -0
  38. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_prefetch.py +0 -0
  39. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_relations.py +0 -0
  40. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_resolvers.py +0 -0
  41. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_search.py +0 -0
  42. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
  43. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_subscriptions.py +0 -0
  44. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_type.py +0 -0
  45. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_view.py +0 -0
  46. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_warmup.py +0 -0
  47. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_warmup_registry.py +0 -0
  48. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
  49. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/mutation.py +0 -0
  50. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/notification_batching.py +0 -0
  51. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/property.py +0 -0
  52. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/registry.py +0 -0
  53. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/remote_api.py +0 -0
  54. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/remote_invalidation.py +0 -0
  55. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/api/remote_invalidation_client.py +0 -0
  56. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/apps.py +0 -0
  57. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/as_of.py +0 -0
  58. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/bootstrap.py +0 -0
  59. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/bucket/__init__.py +0 -0
  60. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/bucket/_materialized_bucket.py +0 -0
  61. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/bucket/_ordering.py +0 -0
  62. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/bucket/base_bucket.py +0 -0
  63. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/bucket/calculation_bucket.py +0 -0
  64. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/bucket/database_bucket.py +0 -0
  65. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/bucket/excel_bucket.py +0 -0
  66. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/bucket/group_bucket.py +0 -0
  67. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/bucket/indexing.py +0 -0
  68. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/bucket/projection.py +0 -0
  69. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/bucket/request_bucket.py +0 -0
  70. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/__init__.py +0 -0
  71. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/_dependency_graph.py +0 -0
  72. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/batch_refresh.py +0 -0
  73. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/cache_decorator.py +0 -0
  74. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/cache_tracker.py +0 -0
  75. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/data_change_context.py +0 -0
  76. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/dependency_cache.py +0 -0
  77. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/dependency_matching.py +0 -0
  78. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/dependency_publish.py +0 -0
  79. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/dependency_shards.py +0 -0
  80. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/model_dependency_collector.py +0 -0
  81. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/run_context.py +0 -0
  82. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/cache/run_context_lru.py +0 -0
  83. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/__init__.py +0 -0
  84. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/audit.py +0 -0
  85. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/bootstrap.py +0 -0
  86. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/checks.py +0 -0
  87. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/consumer.py +0 -0
  88. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/context.py +0 -0
  89. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/errors.py +0 -0
  90. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/__init__.py +0 -0
  91. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/__main__.py +0 -0
  92. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/baseline.py +0 -0
  93. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/datasets/basic_queries.yaml +0 -0
  94. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/datasets/demo_readiness.yaml +0 -0
  95. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/datasets/edge_cases.yaml +0 -0
  96. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/datasets/follow_ups.yaml +0 -0
  97. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/datasets/large_schema.yaml +0 -0
  98. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/datasets/multi_hop.yaml +0 -0
  99. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/datasets/planned_orchestration.yaml +0 -0
  100. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/diagnostics.py +0 -0
  101. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/fingerprints.py +0 -0
  102. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/fixtures.py +0 -0
  103. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/judges/__init__.py +0 -0
  104. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
  105. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/judges/contract.py +0 -0
  106. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
  107. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
  108. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/readiness.py +0 -0
  109. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/runner.py +0 -0
  110. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/evals/traces.py +0 -0
  111. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/grounding.py +0 -0
  112. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/models.py +0 -0
  113. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/__init__.py +0 -0
  114. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/budget.py +0 -0
  115. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/calculations.py +0 -0
  116. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/catalog.py +0 -0
  117. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/config.py +0 -0
  118. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/events.py +0 -0
  119. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/evidence.py +0 -0
  120. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/models.py +0 -0
  121. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/planner.py +0 -0
  122. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/provider_calls.py +0 -0
  123. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/resolver.py +0 -0
  124. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/routing.py +0 -0
  125. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/scheduler.py +0 -0
  126. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/synthesis.py +0 -0
  127. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/planned/validation.py +0 -0
  128. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/providers/__init__.py +0 -0
  129. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/providers/_shared.py +0 -0
  130. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/providers/anthropic.py +0 -0
  131. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/providers/base.py +0 -0
  132. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/providers/google.py +0 -0
  133. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/providers/ollama.py +0 -0
  134. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/providers/openai.py +0 -0
  135. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/rate_limits.py +0 -0
  136. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/routing.py +0 -0
  137. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/schema_index.py +0 -0
  138. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/settings.py +0 -0
  139. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/signals.py +0 -0
  140. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/system_prompt.py +0 -0
  141. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/tool_metadata.py +0 -0
  142. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/tools.py +0 -0
  143. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/turns.py +0 -0
  144. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/chat/views.py +0 -0
  145. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/conf.py +0 -0
  146. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/dataframes/__init__.py +0 -0
  147. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/dataframes/measurements.py +0 -0
  148. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/factory/__init__.py +0 -0
  149. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/factory/auto_factory.py +0 -0
  150. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/factory/factories.py +0 -0
  151. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/factory/factory_methods.py +0 -0
  152. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/__init__.py +0 -0
  153. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/base_interface.py +0 -0
  154. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/bundles/__init__.py +0 -0
  155. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/bundles/calculation.py +0 -0
  156. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/bundles/database.py +0 -0
  157. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/bundles/excel.py +0 -0
  158. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/bundles/remote_manager.py +0 -0
  159. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/bundles/request.py +0 -0
  160. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/__init__.py +0 -0
  161. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/base.py +0 -0
  162. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/builtin.py +0 -0
  163. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
  164. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
  165. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/calculation/input_resolution.py +0 -0
  166. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
  167. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/configuration.py +0 -0
  168. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/core/observability.py +0 -0
  169. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/core/utils.py +0 -0
  170. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/excel/__init__.py +0 -0
  171. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/exceptions.py +0 -0
  172. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
  173. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
  174. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
  175. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/factory.py +0 -0
  176. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
  177. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
  178. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/orm/bulk.py +0 -0
  179. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/orm/create_many.py +0 -0
  180. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/orm/history.py +0 -0
  181. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
  182. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/orm/mutations.py +0 -0
  183. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/orm/support.py +0 -0
  184. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
  185. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
  186. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
  187. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
  188. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/orm_utils/update_state.py +0 -0
  189. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
  190. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
  191. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
  192. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
  193. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
  194. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/registry.py +0 -0
  195. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
  196. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
  197. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/excel.py +0 -0
  198. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/excel_store.py +0 -0
  199. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/excel_workbook.py +0 -0
  200. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/infrastructure/__init__.py +0 -0
  201. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
  202. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
  203. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/interfaces/__init__.py +0 -0
  204. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/interfaces/calculation.py +0 -0
  205. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/interfaces/database.py +0 -0
  206. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/interfaces/excel.py +0 -0
  207. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/interfaces/existing_model.py +0 -0
  208. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/interfaces/read_only.py +0 -0
  209. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
  210. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/interfaces/request.py +0 -0
  211. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/manifests/__init__.py +0 -0
  212. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/manifests/capability_builder.py +0 -0
  213. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
  214. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/manifests/capability_models.py +0 -0
  215. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/orm_interface.py +0 -0
  216. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/requests.py +0 -0
  217. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/utils/__init__.py +0 -0
  218. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
  219. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/utils/errors.py +0 -0
  220. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/utils/history.py +0 -0
  221. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/interface/utils/models.py +0 -0
  222. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/logging.py +0 -0
  223. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/management/commands/chat_cleanup.py +0 -0
  224. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/management/commands/cleanup_upload_intents.py +0 -0
  225. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/management/commands/graphql_warmup.py +0 -0
  226. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
  227. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/management/commands/search_index.py +0 -0
  228. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/management/commands/search_reconcile.py +0 -0
  229. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
  230. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/management/commands/shell.py +0 -0
  231. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
  232. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
  233. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/manager/__init__.py +0 -0
  234. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/manager/bulk_create.py +0 -0
  235. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/manager/general_manager.py +0 -0
  236. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/manager/group_manager.py +0 -0
  237. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/manager/input.py +0 -0
  238. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/manager/meta.py +0 -0
  239. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/measurement/__init__.py +0 -0
  240. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/measurement/measurement.py +0 -0
  241. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/measurement/measurement_field.py +0 -0
  242. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/metrics/__init__.py +0 -0
  243. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/metrics/graphql.py +0 -0
  244. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/migrations/0001_initial.py +0 -0
  245. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
  246. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
  247. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
  248. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/migrations/0004_search_index_state.py +0 -0
  249. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
  250. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
  251. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/migrations/0007_upload_intent.py +0 -0
  252. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/migrations/0008_upload_finalization_versions.py +0 -0
  253. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/migrations/0009_upload_cleanup_state.py +0 -0
  254. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/migrations/0010_chat_pending_confirmation_portable_uniqueness.py +0 -0
  255. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/migrations/0011_search_index_state_dirty_generation.py +0 -0
  256. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/migrations/0012_chat_context_watermarks.py +0 -0
  257. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/migrations/__init__.py +0 -0
  258. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/models.py +0 -0
  259. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/permission/__init__.py +0 -0
  260. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/permission/audit.py +0 -0
  261. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/permission/base_permission.py +0 -0
  262. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/permission/graphql_capabilities.py +0 -0
  263. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/permission/manager_based_permission.py +0 -0
  264. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/permission/mutation_permission.py +0 -0
  265. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/permission/permission_checks.py +0 -0
  266. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/permission/permission_data_manager.py +0 -0
  267. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/permission/utils.py +0 -0
  268. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/public_api_registry.py +0 -0
  269. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/py.typed +0 -0
  270. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/rule/__init__.py +0 -0
  271. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/rule/handler.py +0 -0
  272. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/rule/rule.py +0 -0
  273. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/__init__.py +0 -0
  274. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/async_tasks.py +0 -0
  275. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/backend.py +0 -0
  276. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/backend_registry.py +0 -0
  277. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/backends/__init__.py +0 -0
  278. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/backends/dev.py +0 -0
  279. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/backends/meilisearch.py +0 -0
  280. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/backends/opensearch.py +0 -0
  281. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/backends/typesense.py +0 -0
  282. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/checks.py +0 -0
  283. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/config.py +0 -0
  284. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/indexer.py +0 -0
  285. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/invalidation.py +0 -0
  286. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/m2m_invalidation.py +0 -0
  287. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/models.py +0 -0
  288. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/reconciliation.py +0 -0
  289. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/registry.py +0 -0
  290. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/tasks.py +0 -0
  291. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/search/utils.py +0 -0
  292. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/seeding/__init__.py +0 -0
  293. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/seeding/manager_landscape.py +0 -0
  294. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/__init__.py +0 -0
  295. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/adapters.py +0 -0
  296. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/checks.py +0 -0
  297. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/config.py +0 -0
  298. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/errors.py +0 -0
  299. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/finalization.py +0 -0
  300. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/graphql.py +0 -0
  301. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/graphql_types.py +0 -0
  302. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/metrics.py +0 -0
  303. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/models.py +0 -0
  304. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/public.py +0 -0
  305. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/s3.py +0 -0
  306. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/services.py +0 -0
  307. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/tokens.py +0 -0
  308. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/types.py +0 -0
  309. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/urls.py +0 -0
  310. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/uploads/views.py +0 -0
  311. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/utils/__init__.py +0 -0
  312. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/utils/_args_to_kwargs.py +0 -0
  313. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/utils/_cache_key_encoder.py +0 -0
  314. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/utils/_make_cache_key.py +0 -0
  315. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/utils/_none_to_zero.py +0 -0
  316. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/utils/filter_parser.py +0 -0
  317. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/utils/format_string.py +0 -0
  318. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/utils/json_encoder.py +0 -0
  319. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/utils/path_mapping.py +0 -0
  320. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/utils/public_api.py +0 -0
  321. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/utils/type_checks.py +0 -0
  322. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/__init__.py +0 -0
  323. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/actions.py +0 -0
  324. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/backend_registry.py +0 -0
  325. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/backends/__init__.py +0 -0
  326. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/backends/local.py +0 -0
  327. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/backends/n8n.py +0 -0
  328. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/config.py +0 -0
  329. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/engine.py +0 -0
  330. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/event_registry.py +0 -0
  331. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/events.py +0 -0
  332. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/models.py +0 -0
  333. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/signal_bridge.py +0 -0
  334. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/tasks.py +0 -0
  335. {generalmanager-0.81.2 → generalmanager-0.81.4}/src/general_manager/workflow/telemetry.py +0 -0
  336. {generalmanager-0.81.2 → generalmanager-0.81.4}/tests/test_settings.py +0 -0
  337. {generalmanager-0.81.2 → generalmanager-0.81.4}/tests/test_urls.py +0 -0
  338. {generalmanager-0.81.2 → generalmanager-0.81.4}/tests/testing_asgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.81.2
3
+ Version: 0.81.4
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.81.2"
7
+ version = "0.81.4"
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.81.2
3
+ Version: 0.81.4
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
@@ -14,6 +14,7 @@ from time import perf_counter
14
14
  from typing import TYPE_CHECKING, Any, Callable, Iterable, Literal, Tuple, Type, cast
15
15
 
16
16
  from django.core.cache import cache, caches
17
+ from django.core.cache.backends.dummy import DummyCache
17
18
  from django.db import DEFAULT_DB_ALIAS
18
19
  from django.dispatch import receiver
19
20
 
@@ -116,6 +117,7 @@ LOCK_KEY = "dependency_index_lock" # Cache key used for the dependency lock
116
117
  DEPENDENCY_GENERATION_KEY = "dependency_index_generation"
117
118
  DATA_CHANGE_LOCK_KEY = "dependency_index_data_change_lock"
118
119
  DATA_CHANGE_COUNT_KEY = "dependency_index_data_change_count"
120
+ DATA_CHANGE_RECOVERY_KEY = "dependency_index_data_change_recovery"
119
121
  LOCK_TIMEOUT = 5 # Lock TTL in seconds
120
122
  UNDEFINED = object() # Sentinel for undefined values
121
123
  ACTIONS: tuple[Literal["filter"], Literal["exclude"]] = ("filter", "exclude")
@@ -247,49 +249,187 @@ def _discard_active_context_dependency_cache_state() -> None:
247
249
  context.discard_dependency_cache_state()
248
250
 
249
251
 
252
+ class DependencyBarrierStateError(RuntimeError):
253
+ """Raised when a cache barrier write or mutex ownership cannot be verified."""
254
+
255
+ def __init__(self, reason: Literal["ownership", "write", "journal"]) -> None:
256
+ detail = {
257
+ "ownership": "mutex ownership lost",
258
+ "write": "cache write failed",
259
+ "journal": "invalid recovery journal",
260
+ }[reason]
261
+ super().__init__(
262
+ f"Dependency data-change state could not be verified: {detail}."
263
+ )
264
+
265
+
266
+ def _require_data_change_lock_owner(token: DependencyLockToken) -> None:
267
+ if cache.get(LOCK_KEY) != token:
268
+ raise DependencyBarrierStateError("ownership")
269
+
270
+
271
+ def _verify_data_change_cache_value(key: str, value: object) -> None:
272
+ # Django backends return None, True or False from set(); read the stored
273
+ # value rather than mistaking a valid None return for a failed write.
274
+ if cache.get(key) != value:
275
+ raise DependencyBarrierStateError("write")
276
+
277
+
278
+ def _clear_data_change_recovery(
279
+ token: DependencyLockToken, recovery: dict[str, object]
280
+ ) -> None:
281
+ _require_data_change_lock_owner(token)
282
+ _verify_data_change_cache_value(DATA_CHANGE_RECOVERY_KEY, recovery)
283
+ _require_data_change_lock_owner(token)
284
+ # django-types currently annotates delete() as None, whereas Django
285
+ # documents and implements a boolean acknowledgement.
286
+ cache_delete = cast(Callable[[str], bool], cache.delete)
287
+ try:
288
+ deleted = cache_delete(DATA_CHANGE_RECOVERY_KEY)
289
+ except Exception as primary:
290
+ # A transport error can follow an applied delete. A verified commit
291
+ # must still return success so the caller owns and eventually ends it.
292
+ try:
293
+ remaining = cache.get(DATA_CHANGE_RECOVERY_KEY)
294
+ except Exception as readback_error:
295
+ raise primary from readback_error
296
+ if remaining is not None:
297
+ raise
298
+ logger.exception("dependency data-change recovery deletion acknowledged late")
299
+ else:
300
+ # Django delete() acknowledges removal with True. Do not turn an
301
+ # acknowledged commit into a failed begin via another fallible read.
302
+ if not deleted:
303
+ _verify_data_change_cache_value(DATA_CHANGE_RECOVERY_KEY, None)
304
+
305
+
306
+ def _prepare_data_change_recovery(
307
+ token: DependencyLockToken, count: int, flag: object
308
+ ) -> dict[str, object]:
309
+ _require_data_change_lock_owner(token)
310
+ recovery: dict[str, object] = {"owner": token, "count": count, "flag": flag}
311
+ cache.set(DATA_CHANGE_RECOVERY_KEY, recovery, None)
312
+ _verify_data_change_cache_value(DATA_CHANGE_RECOVERY_KEY, recovery)
313
+ return recovery
314
+
315
+
316
+ def _recover_data_change_barrier(token: DependencyLockToken) -> None:
317
+ recovery = cache.get(DATA_CHANGE_RECOVERY_KEY)
318
+ if recovery is None:
319
+ return
320
+ # Every count change first completes this journal under the mutex. Thus a
321
+ # previous snapshot never overwrites a later operation's active barrier.
322
+ if not isinstance(recovery, dict) or not isinstance(recovery.get("count"), int):
323
+ raise DependencyBarrierStateError("journal")
324
+ _require_data_change_lock_owner(token)
325
+ count = recovery["count"]
326
+ _set_dependency_data_change_count(count)
327
+ _verify_data_change_cache_value(DATA_CHANGE_COUNT_KEY, count)
328
+ _require_data_change_lock_owner(token)
329
+ flag = recovery.get("flag")
330
+ if flag is None:
331
+ cache.delete(DATA_CHANGE_LOCK_KEY)
332
+ else:
333
+ cache.set(DATA_CHANGE_LOCK_KEY, flag, None)
334
+ _verify_data_change_cache_value(DATA_CHANGE_LOCK_KEY, flag)
335
+ _clear_data_change_recovery(token, recovery)
336
+
337
+
338
+ def _retry_data_change_recovery(
339
+ token: DependencyLockToken, recovery: dict[str, object]
340
+ ) -> None:
341
+ """Retain the locally known target if journal preparation/finalization failed."""
342
+ _require_data_change_lock_owner(token)
343
+ stored = cache.get(DATA_CHANGE_RECOVERY_KEY)
344
+ if stored is None:
345
+ _require_data_change_lock_owner(token)
346
+ cache.set(DATA_CHANGE_RECOVERY_KEY, recovery, None)
347
+ _verify_data_change_cache_value(DATA_CHANGE_RECOVERY_KEY, recovery)
348
+ elif stored != recovery:
349
+ raise DependencyBarrierStateError("journal")
350
+ _recover_data_change_barrier(token)
351
+
352
+
353
+ def _release_data_change_lock(token: DependencyLockToken) -> None:
354
+ try:
355
+ release_lock(token)
356
+ except Exception:
357
+ # An already committed begin must not become an unowned failed begin;
358
+ # a failed begin must retain its original exception. The mutex has a TTL.
359
+ logger.exception("dependency data-change mutex release failed")
360
+
361
+
250
362
  def begin_dependency_data_change() -> int:
251
- """
252
- Mark a data change as active and bump the dependency generation.
363
+ """Open a publish barrier, preserving a recoverable pre-begin snapshot.
253
364
 
254
- The generation bump happens before the underlying mutation, so computations
255
- that started before the mutation cannot publish dependency-scoped values.
365
+ Failed starts restore only their own count/flag under the mutex. If cleanup
366
+ fails, a later begin/end completes the stored recovery before changing any
367
+ count. The generation is never rolled back, so stale computations stay fenced.
256
368
  """
369
+ if isinstance(caches["default"], DummyCache):
370
+ _discard_active_context_dependency_cache_state()
371
+ return 0
257
372
  lock_token = acquire_lock_with_retry("begin_dependency_data_change")
373
+ recovery: dict[str, object] | None = None
258
374
  try:
375
+ _recover_data_change_barrier(lock_token)
376
+ count = _get_dependency_data_change_count()
377
+ flag = cache.get(DATA_CHANGE_LOCK_KEY)
378
+ recovery = {"owner": lock_token, "count": count, "flag": flag}
379
+ _prepare_data_change_recovery(lock_token, count, flag)
380
+ _require_data_change_lock_owner(lock_token)
259
381
  generation = _set_dependency_generation(get_dependency_generation() + 1)
260
- _set_dependency_data_change_count(_get_dependency_data_change_count() + 1)
382
+ _verify_data_change_cache_value(DEPENDENCY_GENERATION_KEY, generation)
383
+ _require_data_change_lock_owner(lock_token)
384
+ _set_dependency_data_change_count(count + 1)
385
+ _verify_data_change_cache_value(DATA_CHANGE_COUNT_KEY, count + 1)
386
+ _require_data_change_lock_owner(lock_token)
261
387
  cache.set(DATA_CHANGE_LOCK_KEY, "1", None)
262
- finally:
263
- release_lock(lock_token)
264
- try:
388
+ _verify_data_change_cache_value(DATA_CHANGE_LOCK_KEY, "1")
265
389
  _discard_active_context_dependency_cache_state()
390
+ _clear_data_change_recovery(lock_token, recovery)
266
391
  except Exception:
267
- try:
268
- end_dependency_data_change()
269
- except Exception:
270
- logger.exception("dependency data-change cleanup rollback failed")
392
+ if recovery is not None:
393
+ try:
394
+ _retry_data_change_recovery(lock_token, recovery)
395
+ except Exception:
396
+ logger.exception("dependency data-change cleanup rollback failed")
271
397
  raise
398
+ finally:
399
+ _release_data_change_lock(lock_token)
272
400
  return generation
273
401
 
274
402
 
275
403
  def end_dependency_data_change() -> None:
276
- """Release the publish barrier for a completed data change."""
404
+ """Close one barrier, journaling its completed operation for forward recovery."""
405
+ if isinstance(caches["default"], DummyCache):
406
+ return
277
407
  lock_token = acquire_lock_with_retry("end_dependency_data_change")
408
+ recovery: dict[str, object] | None = None
278
409
  try:
279
- count = _set_dependency_data_change_count(
280
- max(_get_dependency_data_change_count() - 1, 0)
281
- )
282
- if count == 0:
283
- cache.delete(DATA_CHANGE_LOCK_KEY)
284
- else:
285
- cache.set(DATA_CHANGE_LOCK_KEY, "1", None)
410
+ _recover_data_change_barrier(lock_token)
411
+ count = max(_get_dependency_data_change_count() - 1, 0)
412
+ flag = "1" if count else None
413
+ recovery = {"owner": lock_token, "count": count, "flag": flag}
414
+ _prepare_data_change_recovery(lock_token, count, flag)
415
+ _recover_data_change_barrier(lock_token)
416
+ except Exception:
417
+ if recovery is not None:
418
+ try:
419
+ _retry_data_change_recovery(lock_token, recovery)
420
+ except Exception:
421
+ logger.exception("dependency data-change end recovery failed")
422
+ raise
286
423
  finally:
287
- release_lock(lock_token)
424
+ _release_data_change_lock(lock_token)
288
425
 
289
426
 
290
427
  def is_dependency_data_change_active() -> bool:
291
- """Return whether dependency-scoped cache publishing should pause."""
292
- return cache.get(DATA_CHANGE_LOCK_KEY) is not None
428
+ """Pause publishing while a mutation or incomplete recovery is present."""
429
+ return (
430
+ cache.get(DATA_CHANGE_RECOVERY_KEY) is not None
431
+ or cache.get(DATA_CHANGE_LOCK_KEY) is not None
432
+ )
293
433
 
294
434
 
295
435
  def record_invalidated_cache_keys_for_graphql_rewarm(
@@ -178,13 +178,13 @@ def data_change(
178
178
  transaction_scope: DataChangeTransactionScope | None = None
179
179
  transaction_outcome = "rolled_back"
180
180
  begin_dependency_data_change()
181
- context = current_calculation_run_context()
182
- if context is not None:
183
- context.clear_orm_bucket_results()
184
- context.clear_bucket_indexes()
185
- context.clear_bucket_projections()
186
- context.clear_trusted_orm_managers()
187
181
  try:
182
+ context = current_calculation_run_context()
183
+ if context is not None:
184
+ context.clear_orm_bucket_results()
185
+ context.clear_bucket_indexes()
186
+ context.clear_bucket_projections()
187
+ context.clear_trusted_orm_managers()
188
188
  transaction_context: AbstractContextManager[None]
189
189
  if not is_orm_backed:
190
190
  transaction_context = nullcontext()
@@ -25,6 +25,7 @@ from general_manager.cache.cache_decorator import _SENTINEL
25
25
  from general_manager.cache.dependency_index import (
26
26
  DATA_CHANGE_COUNT_KEY,
27
27
  DATA_CHANGE_LOCK_KEY,
28
+ DATA_CHANGE_RECOVERY_KEY,
28
29
  DEPENDENCY_GENERATION_KEY,
29
30
  INDEX_KEY,
30
31
  LOCK_KEY,
@@ -49,6 +50,7 @@ _original_get_app: Callable[[str], AppConfig | None] = (
49
50
  _DEPENDENCY_COORDINATION_KEYS = {
50
51
  DATA_CHANGE_COUNT_KEY,
51
52
  DATA_CHANGE_LOCK_KEY,
53
+ DATA_CHANGE_RECOVERY_KEY,
52
54
  DEPENDENCY_GENERATION_KEY,
53
55
  INDEX_KEY,
54
56
  LOCK_KEY,
@@ -137,7 +137,8 @@ class CeleryWorkflowEngine:
137
137
 
138
138
  Parameters:
139
139
  workflow: Workflow definition to execute.
140
- input_data: Optional JSON-like payload copied with `dict(...)`.
140
+ input_data: Optional JSON-like payload shallow-copied with `dict(...)`
141
+ before persistence and reused for async handler dispatch.
141
142
  correlation_id: Optional durable dedupe key scoped to
142
143
  `workflow.workflow_id`.
143
144
  metadata: Optional metadata copied with `dict(...)`.
@@ -224,13 +225,14 @@ class CeleryWorkflowEngine:
224
225
  except Exception as exc: # noqa: BLE001
225
226
  state = "failed"
226
227
  error = f"Failed to resolve workflow handler path '{handler_path}': {exc}"
228
+ execution_input = dict(input_data or {})
227
229
  try:
228
230
  with transaction.atomic():
229
231
  record = WorkflowExecutionRecord.objects.create(
230
232
  execution_id=execution_id,
231
233
  workflow_id=workflow.workflow_id,
232
234
  state=state,
233
- input_data=dict(input_data or {}),
235
+ input_data=execution_input,
234
236
  output_data=output_data,
235
237
  correlation_id=correlation_id,
236
238
  started_at=started_at,
@@ -263,7 +265,7 @@ class CeleryWorkflowEngine:
263
265
  lambda: execute_workflow_handler.delay(
264
266
  execution_id,
265
267
  dispatch_handler_path,
266
- dict(input_data or {}),
268
+ dict(execution_input),
267
269
  )
268
270
  )
269
271
  elif not async_mode:
File without changes