GeneralManager 0.64.4__tar.gz → 0.65.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.
- {generalmanager-0.64.4/src/GeneralManager.egg-info → generalmanager-0.65.0}/PKG-INFO +1 -1
- {generalmanager-0.64.4 → generalmanager-0.65.0}/pyproject.toml +1 -1
- {generalmanager-0.64.4 → generalmanager-0.65.0/src/GeneralManager.egg-info}/PKG-INFO +1 -1
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/GeneralManager.egg-info/SOURCES.txt +5 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/general_manager.py +4 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/search.py +4 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/apps.py +9 -2
- generalmanager-0.65.0/src/general_manager/cache/data_change_context.py +93 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/cache/signals.py +110 -52
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/orm/mutations.py +27 -30
- generalmanager-0.65.0/src/general_manager/migrations/0011_search_index_state_dirty_generation.py +20 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/public_api_registry.py +10 -0
- generalmanager-0.65.0/src/general_manager/search/async_tasks.py +507 -0
- generalmanager-0.65.0/src/general_manager/search/checks.py +259 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/config.py +41 -7
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/indexer.py +164 -119
- generalmanager-0.65.0/src/general_manager/search/invalidation.py +1231 -0
- generalmanager-0.65.0/src/general_manager/search/m2m_invalidation.py +372 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/models.py +55 -37
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/reconciliation.py +221 -53
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/finalization.py +51 -2
- generalmanager-0.64.4/src/general_manager/search/async_tasks.py +0 -217
- {generalmanager-0.64.4 → generalmanager-0.65.0}/LICENSE +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/README.md +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/setup.cfg +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/GeneralManager.egg-info/dependency_links.txt +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/GeneralManager.egg-info/requires.txt +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/GeneralManager.egg-info/top_level.txt +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/api.py +3 -3
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/bucket.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/cache.py +2 -2
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/dataframes.py +2 -2
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/factory.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/interface.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/manager.py +2 -2
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/measurement.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/permission.py +2 -2
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/rule.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/utils.py +2 -2
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/graphql.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/graphql_errors.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/graphql_mutations.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/graphql_prefetch.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/graphql_relations.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/graphql_resolvers.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/graphql_search.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/graphql_subscription_consumer.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/graphql_subscriptions.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/graphql_view.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/graphql_warmup.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/graphql_warmup_registry.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/graphql_warmup_tasks.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/mutation.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/notification_batching.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/property.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/registry.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/remote_api.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/remote_invalidation.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/api/remote_invalidation_client.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/bootstrap.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/bucket/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/bucket/base_bucket.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/bucket/calculation_bucket.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/bucket/database_bucket.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/bucket/group_bucket.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/bucket/indexing.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/bucket/request_bucket.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/cache/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/cache/cache_decorator.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/cache/cache_tracker.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/cache/dependency_cache.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/cache/dependency_index.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/cache/dependency_matching.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/cache/dependency_publish.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/cache/dependency_shards.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/cache/model_dependency_collector.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/cache/run_context.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/audit.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/bootstrap.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/checks.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/consumer.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/errors.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/__main__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/baseline.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/datasets/basic_queries.yaml +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/datasets/demo_readiness.yaml +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/datasets/edge_cases.yaml +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/datasets/follow_ups.yaml +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/datasets/large_schema.yaml +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/datasets/multi_hop.yaml +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/diagnostics.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/fingerprints.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/fixtures.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/judges/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/judges/answer_quality.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/judges/contract.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/judges/result_accuracy.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/judges/tool_sequence.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/readiness.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/runner.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/evals/traces.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/grounding.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/models.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/providers/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/providers/_shared.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/providers/anthropic.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/providers/base.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/providers/google.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/providers/ollama.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/providers/openai.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/rate_limits.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/routing.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/schema_index.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/settings.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/signals.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/system_prompt.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/tool_metadata.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/tools.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/chat/views.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/conf.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/dataframes/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/dataframes/measurements.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/factory/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/factory/auto_factory.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/factory/factories.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/factory/factory_methods.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/base_interface.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/bundles/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/bundles/calculation.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/bundles/database.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/bundles/remote_manager.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/bundles/request.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/base.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/builtin.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/calculation/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/calculation/_compat.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/calculation/lifecycle.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/configuration.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/core/observability.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/core/utils.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/exceptions.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/existing_model/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/existing_model/_compat.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/existing_model/resolution.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/factory.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/orm/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/orm/_compat.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/orm/history.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/orm/lifecycle.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/orm/support.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/orm_utils/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/orm_utils/django_manager_utils.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/orm_utils/field_descriptors.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/orm_utils/payload_normalizer.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/read_only/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/read_only/_compat.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/read_only/_types.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/read_only/lifecycle.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/read_only/management.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/registry.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/remote_manager.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/capabilities/request/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/infrastructure/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/infrastructure/startup_hooks.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/infrastructure/system_checks.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/interfaces/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/interfaces/calculation.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/interfaces/database.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/interfaces/existing_model.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/interfaces/read_only.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/interfaces/remote_manager.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/interfaces/request.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/manifests/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/manifests/capability_builder.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/manifests/capability_manifest.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/manifests/capability_models.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/orm_interface.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/requests.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/utils/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/utils/database_interface_protocols.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/utils/errors.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/utils/history.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/interface/utils/models.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/logging.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/management/commands/chat_cleanup.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/management/commands/cleanup_upload_intents.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/management/commands/graphql_warmup.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/management/commands/graphql_warmup_refresh_due.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/management/commands/search_index.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/management/commands/search_reconcile.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/management/commands/seed_manager_landscape.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/management/commands/shell.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/management/commands/workflow_drain_outbox.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/management/commands/workflow_replay_dead_letters.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/manager/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/manager/general_manager.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/manager/group_manager.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/manager/input.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/manager/meta.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/measurement/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/measurement/measurement.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/measurement/measurement_field.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/metrics/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/metrics/graphql.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/migrations/0001_initial.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/migrations/0002_workflow_outbox_scaling_indexes.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/migrations/0003_workflow_execution_correlation_constraint.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/migrations/0004_chat_persistence_models.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/migrations/0004_search_index_state.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/migrations/0005_merge_chat_search.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/migrations/0006_chat_pending_confirmation_scoped_ids.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/migrations/0007_upload_intent.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/migrations/0008_upload_finalization_versions.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/migrations/0009_upload_cleanup_state.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/migrations/0010_chat_pending_confirmation_portable_uniqueness.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/migrations/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/models.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/permission/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/permission/audit.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/permission/base_permission.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/permission/graphql_capabilities.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/permission/manager_based_permission.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/permission/mutation_permission.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/permission/permission_checks.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/permission/permission_data_manager.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/permission/utils.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/py.typed +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/rule/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/rule/handler.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/rule/rule.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/backend.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/backend_registry.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/backends/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/backends/dev.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/backends/meilisearch.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/backends/opensearch.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/backends/typesense.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/registry.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/tasks.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/search/utils.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/seeding/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/seeding/manager_landscape.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/adapters.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/checks.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/config.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/errors.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/graphql.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/graphql_types.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/metrics.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/models.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/public.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/s3.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/services.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/tokens.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/types.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/urls.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/uploads/views.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/utils/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/utils/args_to_kwargs.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/utils/filter_parser.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/utils/format_string.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/utils/json_encoder.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/utils/make_cache_key.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/utils/none_to_zero.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/utils/path_mapping.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/utils/public_api.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/utils/testing.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/utils/type_checks.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/actions.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/backend_registry.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/backends/__init__.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/backends/celery.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/backends/local.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/backends/n8n.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/config.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/engine.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/event_registry.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/events.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/models.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/signal_bridge.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/tasks.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/workflow/telemetry.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/tests/test_settings.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/tests/test_urls.py +0 -0
- {generalmanager-0.64.4 → generalmanager-0.65.0}/tests/testing_asgi.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.65.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.
|
|
7
|
+
version = "0.65.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.
|
|
3
|
+
Version: 0.65.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
|
|
@@ -59,6 +59,7 @@ src/general_manager/bucket/request_bucket.py
|
|
|
59
59
|
src/general_manager/cache/__init__.py
|
|
60
60
|
src/general_manager/cache/cache_decorator.py
|
|
61
61
|
src/general_manager/cache/cache_tracker.py
|
|
62
|
+
src/general_manager/cache/data_change_context.py
|
|
62
63
|
src/general_manager/cache/dependency_cache.py
|
|
63
64
|
src/general_manager/cache/dependency_index.py
|
|
64
65
|
src/general_manager/cache/dependency_matching.py
|
|
@@ -208,6 +209,7 @@ src/general_manager/migrations/0007_upload_intent.py
|
|
|
208
209
|
src/general_manager/migrations/0008_upload_finalization_versions.py
|
|
209
210
|
src/general_manager/migrations/0009_upload_cleanup_state.py
|
|
210
211
|
src/general_manager/migrations/0010_chat_pending_confirmation_portable_uniqueness.py
|
|
212
|
+
src/general_manager/migrations/0011_search_index_state_dirty_generation.py
|
|
211
213
|
src/general_manager/migrations/__init__.py
|
|
212
214
|
src/general_manager/permission/__init__.py
|
|
213
215
|
src/general_manager/permission/audit.py
|
|
@@ -225,8 +227,11 @@ src/general_manager/search/__init__.py
|
|
|
225
227
|
src/general_manager/search/async_tasks.py
|
|
226
228
|
src/general_manager/search/backend.py
|
|
227
229
|
src/general_manager/search/backend_registry.py
|
|
230
|
+
src/general_manager/search/checks.py
|
|
228
231
|
src/general_manager/search/config.py
|
|
229
232
|
src/general_manager/search/indexer.py
|
|
233
|
+
src/general_manager/search/invalidation.py
|
|
234
|
+
src/general_manager/search/m2m_invalidation.py
|
|
230
235
|
src/general_manager/search/models.py
|
|
231
236
|
src/general_manager/search/reconciliation.py
|
|
232
237
|
src/general_manager/search/registry.py
|
{generalmanager-0.64.4 → generalmanager-0.65.0}/src/general_manager/_types/general_manager.py
RENAMED
|
@@ -19,9 +19,11 @@ __all__ = [
|
|
|
19
19
|
"RequestInterface",
|
|
20
20
|
"Rule",
|
|
21
21
|
"SearchBackend",
|
|
22
|
+
"SearchChange",
|
|
22
23
|
"SearchConfigProtocol",
|
|
23
24
|
"SearchConfigSpec",
|
|
24
25
|
"SearchIndexer",
|
|
26
|
+
"SearchInvalidationRule",
|
|
25
27
|
"configure_search_backend",
|
|
26
28
|
"configure_search_backend_from_settings",
|
|
27
29
|
"get_logger",
|
|
@@ -54,9 +56,11 @@ from general_manager.interface.interfaces.remote_manager import RemoteManagerInt
|
|
|
54
56
|
from general_manager.interface.interfaces.request import RequestInterface
|
|
55
57
|
from general_manager.rule.rule import Rule
|
|
56
58
|
from general_manager.search.backend import SearchBackend
|
|
59
|
+
from general_manager.search.config import SearchChange
|
|
57
60
|
from general_manager.search.config import SearchConfigProtocol
|
|
58
61
|
from general_manager.search.config import SearchConfigSpec
|
|
59
62
|
from general_manager.search.indexer import SearchIndexer
|
|
63
|
+
from general_manager.search.config import SearchInvalidationRule
|
|
60
64
|
from general_manager.search.backend_registry import configure_search_backend
|
|
61
65
|
from general_manager.search.backend_registry import (
|
|
62
66
|
configure_search_backend_from_settings,
|
|
@@ -13,11 +13,13 @@ __all__ = [
|
|
|
13
13
|
"SearchBackendError",
|
|
14
14
|
"SearchBackendNotConfiguredError",
|
|
15
15
|
"SearchBackendNotImplementedError",
|
|
16
|
+
"SearchChange",
|
|
16
17
|
"SearchConfigProtocol",
|
|
17
18
|
"SearchConfigSpec",
|
|
18
19
|
"SearchDocument",
|
|
19
20
|
"SearchHit",
|
|
20
21
|
"SearchIndexer",
|
|
22
|
+
"SearchInvalidationRule",
|
|
21
23
|
"SearchResult",
|
|
22
24
|
"TypesenseBackend",
|
|
23
25
|
"configure_search_backend",
|
|
@@ -37,11 +39,13 @@ from general_manager.search.backend import SearchBackendClientMissingError
|
|
|
37
39
|
from general_manager.search.backend import SearchBackendError
|
|
38
40
|
from general_manager.search.backend import SearchBackendNotConfiguredError
|
|
39
41
|
from general_manager.search.backend import SearchBackendNotImplementedError
|
|
42
|
+
from general_manager.search.config import SearchChange
|
|
40
43
|
from general_manager.search.config import SearchConfigProtocol
|
|
41
44
|
from general_manager.search.config import SearchConfigSpec
|
|
42
45
|
from general_manager.search.backend import SearchDocument
|
|
43
46
|
from general_manager.search.backend import SearchHit
|
|
44
47
|
from general_manager.search.indexer import SearchIndexer
|
|
48
|
+
from general_manager.search.config import SearchInvalidationRule
|
|
45
49
|
from general_manager.search.backend import SearchResult
|
|
46
50
|
from general_manager.search.backends.typesense import TypesenseBackend
|
|
47
51
|
from general_manager.search.backend_registry import configure_search_backend
|
|
@@ -168,8 +168,10 @@ class GeneralmanagerConfig(AppConfig):
|
|
|
168
168
|
self.install_startup_hook_runner()
|
|
169
169
|
self.register_system_checks()
|
|
170
170
|
from general_manager.uploads.checks import register_upload_checks
|
|
171
|
+
from general_manager.search.checks import register_search_checks
|
|
171
172
|
|
|
172
173
|
register_upload_checks()
|
|
174
|
+
register_search_checks()
|
|
173
175
|
_autoload_app_managers_modules()
|
|
174
176
|
self.initialize_general_manager_classes(
|
|
175
177
|
GeneralManagerMeta.pending_attribute_initialization,
|
|
@@ -178,14 +180,19 @@ class GeneralmanagerConfig(AppConfig):
|
|
|
178
180
|
handle_remote_api(GeneralManagerMeta.all_classes)
|
|
179
181
|
configure_audit_logger_from_settings(settings)
|
|
180
182
|
configure_search_backend_from_settings(settings)
|
|
183
|
+
from general_manager.search.invalidation import configure_search_invalidation
|
|
184
|
+
from general_manager.search.m2m_invalidation import (
|
|
185
|
+
configure_search_m2m_invalidation,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
configure_search_invalidation()
|
|
189
|
+
configure_search_m2m_invalidation()
|
|
181
190
|
configure_workflow_engine_from_settings(settings)
|
|
182
191
|
configure_event_registry_from_settings(settings)
|
|
183
192
|
configure_workflow_signal_bridge_from_settings(settings)
|
|
184
193
|
configure_workflow_beat_schedule_from_settings(settings)
|
|
185
194
|
configure_search_reconcile_beat_schedule_from_settings(settings)
|
|
186
195
|
configure_graphql_warmup_beat_schedule_from_settings(settings)
|
|
187
|
-
import general_manager.search.indexer as _search_indexer # noqa: F401
|
|
188
|
-
|
|
189
196
|
from general_manager.conf import get_setting
|
|
190
197
|
|
|
191
198
|
if get_setting("AUTOCREATE_GRAPHQL", False):
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Context-local ownership metadata for ORM data-change transactions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Iterator
|
|
6
|
+
from contextlib import contextmanager
|
|
7
|
+
from contextvars import ContextVar
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class _DataChangeTransaction:
|
|
13
|
+
"""Live marker for one framework-owned transaction envelope."""
|
|
14
|
+
|
|
15
|
+
database_alias: str
|
|
16
|
+
caller_in_atomic_block: bool
|
|
17
|
+
active: bool = True
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
_owned_transactions: ContextVar[tuple[_DataChangeTransaction, ...]] = ContextVar(
|
|
21
|
+
"owned_data_change_transactions",
|
|
22
|
+
default=(),
|
|
23
|
+
)
|
|
24
|
+
_authorized_operations: ContextVar[tuple[_DataChangeTransaction, ...]] = ContextVar(
|
|
25
|
+
"authorized_data_change_operations",
|
|
26
|
+
default=(),
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _current_owner(database_alias: str) -> _DataChangeTransaction | None:
|
|
31
|
+
for owner in reversed(_owned_transactions.get()):
|
|
32
|
+
if owner.active and owner.database_alias == database_alias:
|
|
33
|
+
return owner
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@contextmanager
|
|
38
|
+
def own_data_change_transaction(
|
|
39
|
+
database_alias: str,
|
|
40
|
+
*,
|
|
41
|
+
caller_in_atomic_block: bool,
|
|
42
|
+
) -> Iterator[None]:
|
|
43
|
+
"""Record a live framework envelope without inspecting Django internals."""
|
|
44
|
+
owner = _DataChangeTransaction(
|
|
45
|
+
database_alias=database_alias,
|
|
46
|
+
caller_in_atomic_block=caller_in_atomic_block,
|
|
47
|
+
)
|
|
48
|
+
token = _owned_transactions.set((*_owned_transactions.get(), owner))
|
|
49
|
+
try:
|
|
50
|
+
yield
|
|
51
|
+
finally:
|
|
52
|
+
owner.active = False
|
|
53
|
+
_owned_transactions.reset(token)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@contextmanager
|
|
57
|
+
def authorize_data_change_operation(database_alias: str) -> Iterator[None]:
|
|
58
|
+
"""Authorize only the decorated manager method to reuse its envelope."""
|
|
59
|
+
owner = _current_owner(database_alias)
|
|
60
|
+
if owner is None:
|
|
61
|
+
yield
|
|
62
|
+
return
|
|
63
|
+
token = _authorized_operations.set((*_authorized_operations.get(), owner))
|
|
64
|
+
try:
|
|
65
|
+
yield
|
|
66
|
+
finally:
|
|
67
|
+
_authorized_operations.reset(token)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def owns_data_change_transaction(database_alias: str) -> bool:
|
|
71
|
+
"""Return whether this context has a live framework envelope for an alias."""
|
|
72
|
+
return _current_owner(database_alias) is not None
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def is_data_change_operation_authorized(database_alias: str) -> bool:
|
|
76
|
+
"""Return whether the current owner is running its decorated method body."""
|
|
77
|
+
owner = _current_owner(database_alias)
|
|
78
|
+
if owner is None:
|
|
79
|
+
return False
|
|
80
|
+
return any(
|
|
81
|
+
authorized is owner and authorized.active
|
|
82
|
+
for authorized in _authorized_operations.get()
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def may_reuse_data_change_transaction(database_alias: str) -> bool:
|
|
87
|
+
"""Conservatively authorize reuse when the manager opened the outer block."""
|
|
88
|
+
owner = _current_owner(database_alias)
|
|
89
|
+
return bool(
|
|
90
|
+
owner is not None
|
|
91
|
+
and not owner.caller_in_atomic_block
|
|
92
|
+
and is_data_change_operation_authorized(database_alias)
|
|
93
|
+
)
|
|
@@ -2,12 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from contextlib import nullcontext
|
|
5
6
|
from copy import deepcopy
|
|
6
|
-
from django.dispatch import Signal
|
|
7
|
-
from typing import Callable, TypeVar, ParamSpec, cast, overload
|
|
8
|
-
|
|
9
7
|
from functools import wraps
|
|
8
|
+
from typing import Callable, ParamSpec, TypeVar, cast, overload
|
|
9
|
+
|
|
10
|
+
from django.db import DEFAULT_DB_ALIAS, connections, transaction
|
|
11
|
+
from django.dispatch import Signal
|
|
12
|
+
from django.utils.connection import ConnectionDoesNotExist
|
|
10
13
|
|
|
14
|
+
from general_manager.cache.data_change_context import (
|
|
15
|
+
authorize_data_change_operation,
|
|
16
|
+
own_data_change_transaction,
|
|
17
|
+
)
|
|
11
18
|
from general_manager.logging import get_logger
|
|
12
19
|
|
|
13
20
|
post_data_change = Signal()
|
|
@@ -20,6 +27,16 @@ R = TypeVar("R")
|
|
|
20
27
|
logger = get_logger("cache.signals")
|
|
21
28
|
|
|
22
29
|
|
|
30
|
+
def _caller_in_atomic_block(database_alias: str) -> bool:
|
|
31
|
+
"""Read public transaction state when the configured alias is available."""
|
|
32
|
+
try:
|
|
33
|
+
return bool(connections[database_alias].in_atomic_block)
|
|
34
|
+
except ConnectionDoesNotExist:
|
|
35
|
+
# Preserve lightweight callers that replace ``transaction.atomic`` in
|
|
36
|
+
# isolation. A real atomic call will still reject an unknown alias.
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
|
|
23
40
|
@overload
|
|
24
41
|
def data_change(func: Callable[P, R]) -> Callable[P, R]: ...
|
|
25
42
|
|
|
@@ -39,9 +56,12 @@ def data_change(
|
|
|
39
56
|
clears run-scoped ORM bucket/index caches, emits `pre_data_change`, invokes
|
|
40
57
|
the wrapped callable, then emits `post_data_change` with the changed
|
|
41
58
|
instance, previous instance, action name, identification, and copied
|
|
42
|
-
`_old_values` payload.
|
|
43
|
-
|
|
44
|
-
|
|
59
|
+
`_old_values` payload. Both signals receive a per-call `change_context` and
|
|
60
|
+
the manager interface's database alias. ORM-backed signal dispatch and the
|
|
61
|
+
mutation share one transaction. GraphQL warm-up requeue keys collected
|
|
62
|
+
during signal handling are drained only after the outermost active
|
|
63
|
+
data-change barrier has closed; failed mutations drain pending keys but do
|
|
64
|
+
not enqueue rewarm work.
|
|
45
65
|
|
|
46
66
|
Parameters:
|
|
47
67
|
func: Function that performs a data mutation. Methods named `create`
|
|
@@ -85,6 +105,29 @@ def data_change(
|
|
|
85
105
|
is_dependency_data_change_active,
|
|
86
106
|
)
|
|
87
107
|
from general_manager.cache.run_context import current_calculation_run_context
|
|
108
|
+
from general_manager.interface.orm_interface import OrmInterfaceBase
|
|
109
|
+
|
|
110
|
+
action = decorator_source.__name__
|
|
111
|
+
if action == "create":
|
|
112
|
+
sender = args[0]
|
|
113
|
+
instance_before = None
|
|
114
|
+
else:
|
|
115
|
+
instance_before = args[0]
|
|
116
|
+
sender = instance_before.__class__
|
|
117
|
+
|
|
118
|
+
interface = getattr(sender, "Interface", None)
|
|
119
|
+
is_orm_backed = isinstance(interface, type) and issubclass(
|
|
120
|
+
interface, OrmInterfaceBase
|
|
121
|
+
)
|
|
122
|
+
database_alias = DEFAULT_DB_ALIAS
|
|
123
|
+
if is_orm_backed:
|
|
124
|
+
database_alias = getattr(interface, "database", None) or DEFAULT_DB_ALIAS
|
|
125
|
+
change_context: dict[str, object] = {}
|
|
126
|
+
signal_kwargs = {
|
|
127
|
+
**kwargs,
|
|
128
|
+
"change_context": change_context,
|
|
129
|
+
"database_alias": database_alias,
|
|
130
|
+
}
|
|
88
131
|
|
|
89
132
|
primary_exc: BaseException | None = None
|
|
90
133
|
completed = False
|
|
@@ -95,55 +138,70 @@ def data_change(
|
|
|
95
138
|
context.clear_bucket_indexes()
|
|
96
139
|
context.clear_trusted_orm_managers()
|
|
97
140
|
try:
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
else:
|
|
103
|
-
instance = args[0]
|
|
104
|
-
sender = instance.__class__
|
|
105
|
-
instance_before = instance
|
|
106
|
-
pre_data_change.send(
|
|
107
|
-
sender=sender,
|
|
108
|
-
instance=instance_before,
|
|
109
|
-
action=action,
|
|
110
|
-
**kwargs,
|
|
141
|
+
transaction_context = (
|
|
142
|
+
transaction.atomic(using=database_alias)
|
|
143
|
+
if is_orm_backed
|
|
144
|
+
else nullcontext()
|
|
111
145
|
)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
getattr(instance_before, "identification", None)
|
|
146
|
+
caller_in_atomic_block = (
|
|
147
|
+
_caller_in_atomic_block(database_alias) if is_orm_backed else False
|
|
115
148
|
)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if context is not None:
|
|
124
|
-
context.clear_orm_bucket_results()
|
|
125
|
-
context.clear_bucket_indexes()
|
|
126
|
-
context.clear_trusted_orm_managers()
|
|
127
|
-
|
|
128
|
-
instance = result
|
|
129
|
-
identification = getattr(instance, "identification", None)
|
|
130
|
-
if identification is None:
|
|
131
|
-
identification = pre_identification
|
|
132
|
-
|
|
133
|
-
post_data_change.send(
|
|
134
|
-
sender=sender,
|
|
135
|
-
instance=instance,
|
|
136
|
-
previous_instance=instance_before,
|
|
137
|
-
identification=identification,
|
|
138
|
-
action=action,
|
|
139
|
-
old_relevant_values=old_relevant_values,
|
|
140
|
-
**kwargs,
|
|
149
|
+
ownership_context = (
|
|
150
|
+
own_data_change_transaction(
|
|
151
|
+
database_alias,
|
|
152
|
+
caller_in_atomic_block=caller_in_atomic_block,
|
|
153
|
+
)
|
|
154
|
+
if is_orm_backed
|
|
155
|
+
else nullcontext()
|
|
141
156
|
)
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
157
|
+
with transaction_context, ownership_context:
|
|
158
|
+
pre_data_change.send(
|
|
159
|
+
sender=sender,
|
|
160
|
+
instance=instance_before,
|
|
161
|
+
action=action,
|
|
162
|
+
**signal_kwargs,
|
|
163
|
+
)
|
|
164
|
+
old_relevant_values = getattr(instance_before, "_old_values", {})
|
|
165
|
+
pre_identification = deepcopy(
|
|
166
|
+
getattr(instance_before, "identification", None)
|
|
167
|
+
)
|
|
168
|
+
operation_context = (
|
|
169
|
+
authorize_data_change_operation(database_alias)
|
|
170
|
+
if is_orm_backed
|
|
171
|
+
else nullcontext()
|
|
172
|
+
)
|
|
173
|
+
with operation_context:
|
|
174
|
+
if isinstance(func, classmethod):
|
|
175
|
+
inner = cast(Callable[P, R], func.__func__)
|
|
176
|
+
result = inner(*args, **kwargs)
|
|
177
|
+
else:
|
|
178
|
+
result = func(*args, **kwargs)
|
|
179
|
+
|
|
180
|
+
context = current_calculation_run_context()
|
|
181
|
+
if context is not None:
|
|
182
|
+
context.clear_orm_bucket_results()
|
|
183
|
+
context.clear_bucket_indexes()
|
|
184
|
+
context.clear_trusted_orm_managers()
|
|
185
|
+
|
|
186
|
+
instance = result
|
|
187
|
+
identification = getattr(instance, "identification", None)
|
|
188
|
+
if identification is None:
|
|
189
|
+
identification = pre_identification
|
|
190
|
+
|
|
191
|
+
post_data_change.send(
|
|
192
|
+
sender=sender,
|
|
193
|
+
instance=instance,
|
|
194
|
+
previous_instance=instance_before,
|
|
195
|
+
identification=identification,
|
|
196
|
+
action=action,
|
|
197
|
+
old_relevant_values=old_relevant_values,
|
|
198
|
+
**signal_kwargs,
|
|
199
|
+
)
|
|
200
|
+
if instance_before is not None:
|
|
201
|
+
try:
|
|
202
|
+
delattr(instance_before, "_old_values")
|
|
203
|
+
except AttributeError:
|
|
204
|
+
pass
|
|
147
205
|
completed = True
|
|
148
206
|
except BaseException as error:
|
|
149
207
|
primary_exc = error
|
|
@@ -3,14 +3,15 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from collections.abc import Iterator
|
|
6
|
-
from contextlib import contextmanager
|
|
6
|
+
from contextlib import AbstractContextManager, contextmanager
|
|
7
7
|
from contextvars import ContextVar
|
|
8
8
|
from typing import TYPE_CHECKING, Any, ClassVar, cast
|
|
9
9
|
|
|
10
10
|
from django.contrib.auth import get_user_model
|
|
11
|
-
from django.db import models, transaction
|
|
11
|
+
from django.db import DEFAULT_DB_ALIAS, models, transaction
|
|
12
12
|
from django.db.models import NOT_PROVIDED
|
|
13
13
|
|
|
14
|
+
from general_manager.cache.data_change_context import owns_data_change_transaction
|
|
14
15
|
from general_manager.interface.capabilities.base import CapabilityName
|
|
15
16
|
from general_manager.interface.capabilities.builtin import BaseCapability
|
|
16
17
|
from general_manager.interface.capabilities.orm_utils.payload_normalizer import (
|
|
@@ -67,6 +68,23 @@ def _without_save_with_history_savepoint() -> Iterator[None]:
|
|
|
67
68
|
_save_with_history_savepoint.reset(token)
|
|
68
69
|
|
|
69
70
|
|
|
71
|
+
def _mutation_atomic(
|
|
72
|
+
database_alias: str | None,
|
|
73
|
+
*,
|
|
74
|
+
savepoint: bool = True,
|
|
75
|
+
) -> AbstractContextManager[None]:
|
|
76
|
+
"""Open a mutation boundary without nesting under its signal envelope."""
|
|
77
|
+
alias = database_alias or DEFAULT_DB_ALIAS
|
|
78
|
+
use_savepoint = savepoint and not owns_data_change_transaction(alias)
|
|
79
|
+
if database_alias:
|
|
80
|
+
if use_savepoint:
|
|
81
|
+
return transaction.atomic(using=database_alias)
|
|
82
|
+
return transaction.atomic(using=database_alias, savepoint=False)
|
|
83
|
+
if use_savepoint:
|
|
84
|
+
return transaction.atomic()
|
|
85
|
+
return transaction.atomic(savepoint=False)
|
|
86
|
+
|
|
87
|
+
|
|
70
88
|
class OrmMutationCapability(BaseCapability):
|
|
71
89
|
"""Common utilities to modify ORM instances."""
|
|
72
90
|
|
|
@@ -174,19 +192,10 @@ class OrmMutationCapability(BaseCapability):
|
|
|
174
192
|
database_alias = support.get_database_alias(interface_cls)
|
|
175
193
|
if database_alias:
|
|
176
194
|
instance._state.db = database_alias
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if savepoint
|
|
182
|
-
else transaction.atomic(using=database_alias, savepoint=False)
|
|
183
|
-
)
|
|
184
|
-
else:
|
|
185
|
-
atomic_context = (
|
|
186
|
-
transaction.atomic()
|
|
187
|
-
if savepoint
|
|
188
|
-
else transaction.atomic(savepoint=False)
|
|
189
|
-
)
|
|
195
|
+
atomic_context = _mutation_atomic(
|
|
196
|
+
database_alias,
|
|
197
|
+
savepoint=_save_with_history_savepoint.get(),
|
|
198
|
+
)
|
|
190
199
|
with atomic_context:
|
|
191
200
|
_assign_history_actor(
|
|
192
201
|
instance,
|
|
@@ -388,11 +397,7 @@ class OrmCreateCapability(BaseCapability):
|
|
|
388
397
|
)
|
|
389
398
|
support = get_support_capability(interface_cls)
|
|
390
399
|
database_alias = support.get_database_alias(interface_cls)
|
|
391
|
-
atomic_context = (
|
|
392
|
-
transaction.atomic(using=database_alias)
|
|
393
|
-
if database_alias
|
|
394
|
-
else transaction.atomic()
|
|
395
|
-
)
|
|
400
|
+
atomic_context = _mutation_atomic(database_alias)
|
|
396
401
|
with atomic_context:
|
|
397
402
|
with _without_save_with_history_savepoint():
|
|
398
403
|
pk = mutation.save_with_history(
|
|
@@ -538,11 +543,7 @@ class OrmUpdateCapability(BaseCapability):
|
|
|
538
543
|
interface_instance.__class__, instance, normalized_simple
|
|
539
544
|
)
|
|
540
545
|
database_alias = support.get_database_alias(interface_instance.__class__)
|
|
541
|
-
atomic_context = (
|
|
542
|
-
transaction.atomic(using=database_alias)
|
|
543
|
-
if database_alias
|
|
544
|
-
else transaction.atomic()
|
|
545
|
-
)
|
|
546
|
+
atomic_context = _mutation_atomic(database_alias)
|
|
546
547
|
with atomic_context:
|
|
547
548
|
with _without_save_with_history_savepoint():
|
|
548
549
|
pk = mutation.save_with_history(
|
|
@@ -666,11 +667,7 @@ class OrmDeleteCapability(BaseCapability):
|
|
|
666
667
|
if model_has_field(instance, "changed_by"):
|
|
667
668
|
object.__setattr__(instance, "changed_by_id", creator_id)
|
|
668
669
|
call_update_change_reason(instance, history_comment_local)
|
|
669
|
-
atomic_context = (
|
|
670
|
-
transaction.atomic(using=database_alias)
|
|
671
|
-
if database_alias
|
|
672
|
-
else transaction.atomic()
|
|
673
|
-
)
|
|
670
|
+
atomic_context = _mutation_atomic(database_alias)
|
|
674
671
|
with atomic_context:
|
|
675
672
|
if database_alias:
|
|
676
673
|
instance.delete(using=database_alias)
|
generalmanager-0.65.0/src/general_manager/migrations/0011_search_index_state_dirty_generation.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Generated by Django 5.2.10 on 2026-07-15 00:00
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
dependencies = [
|
|
8
|
+
(
|
|
9
|
+
"general_manager",
|
|
10
|
+
"0010_chat_pending_confirmation_portable_uniqueness",
|
|
11
|
+
),
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
operations = [
|
|
15
|
+
migrations.AddField(
|
|
16
|
+
model_name="searchindexstate",
|
|
17
|
+
name="dirty_generation",
|
|
18
|
+
field=models.PositiveBigIntegerField(default=0),
|
|
19
|
+
),
|
|
20
|
+
]
|
|
@@ -22,6 +22,11 @@ GENERAL_MANAGER_EXPORTS: LazyExportMap = {
|
|
|
22
22
|
"IndexConfig": ("general_manager.search.config", "IndexConfig"),
|
|
23
23
|
"SearchConfigProtocol": ("general_manager.search.config", "SearchConfigProtocol"),
|
|
24
24
|
"SearchConfigSpec": ("general_manager.search.config", "SearchConfigSpec"),
|
|
25
|
+
"SearchChange": ("general_manager.search.config", "SearchChange"),
|
|
26
|
+
"SearchInvalidationRule": (
|
|
27
|
+
"general_manager.search.config",
|
|
28
|
+
"SearchInvalidationRule",
|
|
29
|
+
),
|
|
25
30
|
"resolve_search_config": (
|
|
26
31
|
"general_manager.search.config",
|
|
27
32
|
"resolve_search_config",
|
|
@@ -678,6 +683,11 @@ SEARCH_EXPORTS: LazyExportMap = {
|
|
|
678
683
|
"IndexConfig": ("general_manager.search.config", "IndexConfig"),
|
|
679
684
|
"SearchConfigProtocol": ("general_manager.search.config", "SearchConfigProtocol"),
|
|
680
685
|
"SearchConfigSpec": ("general_manager.search.config", "SearchConfigSpec"),
|
|
686
|
+
"SearchChange": ("general_manager.search.config", "SearchChange"),
|
|
687
|
+
"SearchInvalidationRule": (
|
|
688
|
+
"general_manager.search.config",
|
|
689
|
+
"SearchInvalidationRule",
|
|
690
|
+
),
|
|
681
691
|
"resolve_search_config": (
|
|
682
692
|
"general_manager.search.config",
|
|
683
693
|
"resolve_search_config",
|