matrx-orm 3.1.119__tar.gz → 3.1.121__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.
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/.gitignore +2 -2
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/PKG-INFO +1 -1
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/FEATURE.md +11 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/async_db_manager.py +35 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/base.py +8 -2
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/query/FEATURE.md +10 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/query/builder.py +7 -3
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/pyproject.toml +1 -1
- matrx_orm-3.1.121/tests/level1/test_persisted_count.py +33 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_pool_maintenance.py +29 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/AGENTS.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/BASE_CLASS_METHODS.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/CLAUDE.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/MODEL_API.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/database/orm/extended/managers/ai_model_base.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/docs/migrations.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/FEATURE.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/MODULE_README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/adapters/MODULE_README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/adapters/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/adapters/async_postgresql.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/adapters/base_adapter.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/adapters/postgresql.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/adapters/supabase_adapter.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/admin/FEATURE.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/admin/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/admin/router.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/api/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/api/auth.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/api/config.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/api/handlers.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/api/protocol.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/api/server.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/associations.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/cache_debug.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/catalog.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/catalog_sql.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/client/MODULE_README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/client/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/client/postgres_connection.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/client/postgrest.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/client/supabase_auth.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/client/supabase_config.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/client/supabase_manager.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/EXTENDED-TASK.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/MODULE_README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/TASKS.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/config.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/connections.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/db_function.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/diagnostics.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/expressions.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/extended.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/fields.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/introspection.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/listen.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/loop_filters.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/model_dto.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/model_view.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/one_database.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/paginator.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/pool_maintenance.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/pool_watch.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/pooler_role.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/pydantic_bridge.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/registry.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/relations.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/resilience.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/rls_session.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/signals.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/tls.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/transaction.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/types.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/core/write_queue.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/entity.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/error_handling.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/exceptions.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/extended/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/extended/app_error_handler.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/identity_rule.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/local_sqlite.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/middleware/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/middleware/base.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/migrations/MODULE_README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/migrations/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/migrations/cli.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/migrations/ddl.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/migrations/diff.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/migrations/executor.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/migrations/integration.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/migrations/loader.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/migrations/operations.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/migrations/state.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/migrations/table_filter.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/FEATURE.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/MODULE_README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/bulk_update_values.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/conflict.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/conflict_writes.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/create.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/db_functions.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/delete.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/dynamic_admin.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/dynamic_crud.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/graph_walk.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/latest_rows.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/queue_claim.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/read.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/relational_backfill.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/staging_load.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/operations/update.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/platform_db.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/py.typed +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/python_sql/MODULE_README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/python_sql/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/python_sql/db_objects.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/query/MODULE_README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/query/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/query/executor.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/FEATURE.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/MODULE_README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/code_handler.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/codegen_writer.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/columns.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/common.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/diff_preview.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/generator.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/package_wiring.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/relationships.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/runner.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/schema.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/schema_manager.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/tables.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/views.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/secrets_battery/FEATURE.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/secrets_battery/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/secrets_battery/attachments.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/secrets_battery/crypto.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/secrets_battery/host_authorization.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/secrets_battery/items.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/secrets_battery/model.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/secrets_battery/org_service.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/secrets_battery/service.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/session/README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/session/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/session/coalesce.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/session/dag.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/session/errors.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/session/fallback.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/session/flush.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/session/lifecycle.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/session/managed.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/session/op.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/session/reads.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/session/session.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/session/telemetry.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/sql_executor/MODULE_README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/sql_executor/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/sql_executor/executor.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/sql_executor/queries.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/sql_executor/registry.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/sql_executor/types.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/sql_executor/utils.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/state.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/utils/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/utils/sql_utils.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/utils/type_converters.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/scripts/git-branches.sh +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/scripts/publish.sh +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/scripts/release.sh +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/MODULE_README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/conftest.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/MODULE_README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_admin_db_columns.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_admin_response_rendering.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_admin_search_negation.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_admin_search_sentinels.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_advisory_lock.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_agent_message.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_api_auth.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_api_config.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_api_handlers.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_api_protocol.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_array_agg_order_by.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_associations.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_bulk_hydration_offload.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_bulk_update_by_pk.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_cache_debug.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_call_function.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_case_when.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_catalog.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_composite_pk_filter.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_composite_pk_write_paths.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_config.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_conflict_target.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_conflict_writes.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_connection_codecs.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_connection_poison_guard.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_connection_primitives.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_count_composite_distinct.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_db_function_field.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_ddl_generator.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_derived_table.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_dirty_tracking.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_dynamic_crud.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_exceptions.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_execute_query_integrity_mapping.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_expression_primitives.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_fields.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_from_alias.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_fts.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_func_expression_args.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_graph_walk.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_having_annotate_alias.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_introspect_rls_policies.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_join_and_aggregate.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_latest_rows.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_listen_notify.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_local_sqlite.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_managed_write_guard.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_matrx_entity.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_migration_diff_types.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_migration_loader.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_model_instance.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_model_meta.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_optimistic_concurrency.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_order_by_expression.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_parameter_name_hydration.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_patch_jsonb_path.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_pool_holder_census.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_pool_loop_recreation.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_postgrest_filters.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_pydantic_bridge.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_query_builder.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_query_error_detail.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_query_executor_sql.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_query_timeout.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_queue_claim.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_read_connection_retry.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_registry.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_registry_multi_database.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_registry_multi_schema.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_relational_backfill.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_relations.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_resilience.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_rls_session_scope.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_schema_exists.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_session_advisory_lock.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_state_cache.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_subquery_filter_raw.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_subquery_in_filter.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_subquery_nested_expressions.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_supabase_auth.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_supabase_config.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_tls.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_typed_join_projection.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_typed_predicates.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_update_case_expression.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_update_subquery.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_update_with_rebase.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_upsert_default_leak.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_upsert_with_conflict.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_values_jsonb_decode.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_watched_lifecycle.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level1/test_write_retry_semantics.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level2/MODULE_README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level2/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level2/conftest.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level2/test_bulk_ops.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level2/test_cache_integration.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level2/test_crud.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level2/test_foreign_keys.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level2/test_m2m.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level2/test_manager.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level2/test_migrations_live.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level2/test_query_execution.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/level2/test_schema_diff.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/live_pooler_role.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/sample_project/.env.example +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/sample_project/README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/sample_project/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/sample_project/generate.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/sample_project/generated/.gitkeep +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/sample_project/matrx_orm.yaml +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/sample_project/test_schema_generation.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/sample_project_desktop/.env.example +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/sample_project_desktop/README.md +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/sample_project_desktop/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/sample_project_desktop/client_example.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/sample_project_desktop/client_example.ts +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/sample_project_desktop/client_supabase_example.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/sample_project_desktop/server.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema/entity_tests.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema/test_base_generation.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema/test_composite_pk_fk_generation.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema/test_composite_unique_generation.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema/test_dto_identity_generation.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema/test_entity_capability_generation.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema/test_enum_ordering.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema/test_generate_schema.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema/test_junction_analysis.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema/test_multi_schema_output.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema/test_schema_analysis.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema/test_sql_expression_defaults.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema/test_table_relationships_query.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema/test_view_generation.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema_builder/test_array_default_parsing.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema_builder/test_focused_generation_plan.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/schema_builder/test_host_models_aggregator.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/session/__init__.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/session/conftest.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/session/test_cache_no_downgrade.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/session/test_capture_poison_proof.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/session/test_coalesce.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/session/test_dag.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/session/test_disk_spill_fallback.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/session/test_flush_individual_fallback.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/session/test_governed_write.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/session/test_managed.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/session/test_op_enqueue_site.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/session/test_reads.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/session/test_session.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/test_array_arg_element_type.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/test_database_name_alias.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/test_db_functions.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/test_keyed_digest.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/test_model_cls_refactor.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/test_no_blocking_asyncpg_tls.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/test_one_database.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/test_pooler_role_guard.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/test_secrets_battery.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/test_secrets_minting_keys.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/test_sql_param_casts.py +0 -0
- {matrx_orm-3.1.119 → matrx_orm-3.1.121}/tests/test_sync_twins_guard.py +0 -0
|
@@ -293,5 +293,5 @@ apps/shared/matrx-agents/*.tgz
|
|
|
293
293
|
# the real tree the guard scans (a temp dir would prove nothing) and delete
|
|
294
294
|
# them in teardown — ignoring them keeps the auto-commit tooling from
|
|
295
295
|
# capturing one mid-run.
|
|
296
|
-
_kind_boundary_scratch
|
|
297
|
-
_kind_marker_law_scratch
|
|
296
|
+
_kind_boundary_scratch*/
|
|
297
|
+
_kind_marker_law_scratch*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: matrx-orm
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.121
|
|
4
4
|
Summary: Async-first PostgreSQL ORM with bidirectional migrations, schema introspection, many-to-many relationships, and built-in state caching
|
|
5
5
|
Project-URL: Homepage, https://github.com/AI-Matrix-Engine/aidream-current
|
|
6
6
|
Project-URL: Repository, https://github.com/AI-Matrix-Engine/aidream-current
|
|
@@ -74,6 +74,15 @@ connection and can strand old holders in release/reset.
|
|
|
74
74
|
|
|
75
75
|
Pinned by `tests/level1/test_pool_maintenance.py`.
|
|
76
76
|
|
|
77
|
+
**A server restart rejected during checkout is a connection failure.** PostgreSQL
|
|
78
|
+
`AdminShutdownError`, `CrashShutdownError`, and `CannotConnectNowError` raised
|
|
79
|
+
while `pool.acquire()` opens a physical connection become `ConnectionError` at
|
|
80
|
+
`AsyncDatabaseManager.get_connection`. No caller SQL was sent, so an explicitly
|
|
81
|
+
replay-safe owner can use `retry_on_transient`; the failure never falls through
|
|
82
|
+
as an unrelated `CacheError`.
|
|
83
|
+
|
|
84
|
+
Pinned by `tests/level1/test_pool_maintenance.py`.
|
|
85
|
+
|
|
77
86
|
**Every checkout is attributable.** `AsyncDatabaseManager.get_connection` and
|
|
78
87
|
the sanctioned caller-supplied-pool helper register the holder's asyncio task,
|
|
79
88
|
checkout call site/stack, current suspended call site/stack, and age. On the
|
|
@@ -177,6 +186,8 @@ can never disagree about who the blocker was.
|
|
|
177
186
|
Verified against the live database: 2026-08-21.
|
|
178
187
|
|
|
179
188
|
## Change log
|
|
189
|
+
- 2026-08-30: Classified server restart/failover rejection during pool checkout
|
|
190
|
+
as retryable connection failure before any caller SQL is sent.
|
|
180
191
|
- 2026-08-24: Recovered read-only disconnects masked by empty-read reproof's
|
|
181
192
|
transaction teardown, while preserving diagnostic handling for unrelated
|
|
182
193
|
interface errors.
|
|
@@ -71,6 +71,15 @@ _SCHEMA_MISMATCH_EXC = (
|
|
|
71
71
|
asyncpg.exceptions.InvalidSchemaNameError,
|
|
72
72
|
)
|
|
73
73
|
|
|
74
|
+
# PostgreSQL emits these SQLSTATE class-57 errors while asyncpg is opening a
|
|
75
|
+
# physical connection during a server restart/failover. They happen before a
|
|
76
|
+
# checkout exists, so no caller SQL was sent and a replay-safe owner may retry.
|
|
77
|
+
_ACQUIRE_SERVER_TRANSIENT_EXC = (
|
|
78
|
+
asyncpg.exceptions.AdminShutdownError,
|
|
79
|
+
asyncpg.exceptions.CrashShutdownError,
|
|
80
|
+
asyncpg.exceptions.CannotConnectNowError,
|
|
81
|
+
)
|
|
82
|
+
|
|
74
83
|
|
|
75
84
|
def _integrity_constraint_kind(exc: asyncpg.exceptions.IntegrityConstraintViolationError) -> str:
|
|
76
85
|
if isinstance(exc, asyncpg.exceptions.CheckViolationError):
|
|
@@ -822,6 +831,22 @@ class AsyncDatabaseManager:
|
|
|
822
831
|
async with asyncio.timeout(timeout):
|
|
823
832
|
conn = await cls._acquire_bounded_growth(config_name, pool)
|
|
824
833
|
break
|
|
834
|
+
except asyncpg.exceptions.AdminShutdownError as exc:
|
|
835
|
+
# Caught before a connection reaches the caller: no SQL was sent.
|
|
836
|
+
if _acquire_attempt >= POOL_ACQUIRE_RETRIES:
|
|
837
|
+
raise
|
|
838
|
+
backoff = POOL_ACQUIRE_RETRY_BASE_BACKOFF * (2**_acquire_attempt)
|
|
839
|
+
logger.warning(
|
|
840
|
+
"[matrx_orm] PostgreSQL administrator shutdown while acquiring "
|
|
841
|
+
"'%s' (attempt %d/%d) — retrying in %.2fs (no SQL sent, safe): %s",
|
|
842
|
+
config_name,
|
|
843
|
+
_acquire_attempt + 1,
|
|
844
|
+
1 + POOL_ACQUIRE_RETRIES,
|
|
845
|
+
backoff,
|
|
846
|
+
type(exc).__name__,
|
|
847
|
+
)
|
|
848
|
+
await asyncio.sleep(backoff)
|
|
849
|
+
continue
|
|
825
850
|
except TimeoutError:
|
|
826
851
|
from matrx_orm.core.pool_watch import emit_first_pool_timeout
|
|
827
852
|
|
|
@@ -961,6 +986,16 @@ class AsyncDatabaseManager:
|
|
|
961
986
|
timeout=timeout,
|
|
962
987
|
):
|
|
963
988
|
raise _timeout_err from None
|
|
989
|
+
except _ACQUIRE_SERVER_TRANSIENT_EXC as e:
|
|
990
|
+
# A server restart can reject asyncpg's lazy replacement handshake
|
|
991
|
+
# from inside pool.acquire(). Classify it at the checkout boundary;
|
|
992
|
+
# otherwise handle_orm_operation wraps it as CacheError and hides
|
|
993
|
+
# the transient connection identity from retry_on_transient.
|
|
994
|
+
raise ConnectionError(
|
|
995
|
+
model=None,
|
|
996
|
+
db_url=config_name,
|
|
997
|
+
original_error=e,
|
|
998
|
+
) from e
|
|
964
999
|
except asyncpg.exceptions.InterfaceError as e:
|
|
965
1000
|
async with handle_orm_operation(
|
|
966
1001
|
operation_name="acquire_connection",
|
|
@@ -923,14 +923,20 @@ class Model(RuntimeMixin, metaclass=ModelMeta):
|
|
|
923
923
|
)
|
|
924
924
|
|
|
925
925
|
@classmethod
|
|
926
|
-
async def count(cls, **kwargs: Any) -> int:
|
|
926
|
+
async def count(cls, *, include_pending: bool = True, **kwargs: Any) -> int:
|
|
927
927
|
"""Lightweight row count without full model hydration.
|
|
928
928
|
|
|
929
929
|
Usage:
|
|
930
930
|
total = await MyModel.count()
|
|
931
931
|
active = await MyModel.count(status="active")
|
|
932
|
+
|
|
933
|
+
Pass ``include_pending=False`` for persisted-state telemetry and
|
|
934
|
+
inventory reads that must remain a database aggregate inside a
|
|
935
|
+
request Session with queued writes.
|
|
932
936
|
"""
|
|
933
|
-
return await QueryBuilder(cls).filter(**kwargs).count(
|
|
937
|
+
return await QueryBuilder(cls).filter(**kwargs).count(
|
|
938
|
+
include_pending=include_pending
|
|
939
|
+
)
|
|
934
940
|
|
|
935
941
|
@classmethod
|
|
936
942
|
def count_sync(cls, **kwargs: Any) -> int:
|
|
@@ -44,8 +44,18 @@ explicit `.values(...)` projects the grouped columns plus its aggregate
|
|
|
44
44
|
expressions. These shapes keep every generated aggregate valid in PostgreSQL
|
|
45
45
|
without forcing callers to add a redundant projection.
|
|
46
46
|
|
|
47
|
+
## Persisted-state counts
|
|
48
|
+
|
|
49
|
+
`count()` remains session-aware by default: when the active Session stack has
|
|
50
|
+
pending writes for the model, it merges those writes so business decisions see
|
|
51
|
+
read-your-own-writes state. Telemetry and inventory callers that explicitly
|
|
52
|
+
want persisted database state call `count(include_pending=False)`. That opt-out
|
|
53
|
+
always uses the database aggregate and never hydrates or serializes every
|
|
54
|
+
matching model merely because a request Coordinator has queued a write.
|
|
55
|
+
|
|
47
56
|
## Change log
|
|
48
57
|
|
|
58
|
+
- 2026-08-28 — Added persisted-state counts that bypass pending-row hydration.
|
|
49
59
|
- 2026-08-18 — Moved async terminal SQL compilation off the event loop.
|
|
50
60
|
- 2026-08-15 — Moved bulk hydration off the event loop, made complete-primary-key
|
|
51
61
|
misses constant-time, and documented cache bypass for request-local scans.
|
|
@@ -953,15 +953,19 @@ class QueryBuilder(Generic[ModelT]):
|
|
|
953
953
|
return False
|
|
954
954
|
return has_pending_in_stack(self.model)
|
|
955
955
|
|
|
956
|
-
async def count(self) -> int:
|
|
956
|
+
async def count(self, *, include_pending: bool = True) -> int:
|
|
957
957
|
"""Count matching records.
|
|
958
958
|
|
|
959
959
|
Session-aware: when the Session stack has pending writes for this
|
|
960
960
|
Model, count() reflects the merged (DB + pending) result so a nested
|
|
961
|
-
Session never under/over-counts rows an ancestor queued.
|
|
961
|
+
Session never under/over-counts rows an ancestor queued. Callers doing
|
|
962
|
+
telemetry or inventory over persisted state may pass
|
|
963
|
+
``include_pending=False`` to keep the database aggregate path even
|
|
964
|
+
when the request Session has queued writes; this avoids hydrating and
|
|
965
|
+
serializing an arbitrarily large table just to obtain its row count.
|
|
962
966
|
"""
|
|
963
967
|
try:
|
|
964
|
-
if self._stack_has_pending():
|
|
968
|
+
if include_pending and self._stack_has_pending():
|
|
965
969
|
return len(await self.all())
|
|
966
970
|
executor = await self._get_executor_async()
|
|
967
971
|
return await executor.count()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "matrx-orm"
|
|
3
|
-
version = "3.1.
|
|
3
|
+
version = "3.1.121"
|
|
4
4
|
description = "Async-first PostgreSQL ORM with bidirectional migrations, schema introspection, many-to-many relationships, and built-in state caching"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { text = "MIT" }
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Persisted counts stay aggregate-only inside a pending-write Session."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from unittest.mock import AsyncMock
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from matrx_orm.query.builder import QueryBuilder
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.asyncio
|
|
13
|
+
async def test_count_can_bypass_pending_model_hydration(monkeypatch):
|
|
14
|
+
builder = QueryBuilder(AsyncMock())
|
|
15
|
+
executor = AsyncMock()
|
|
16
|
+
executor.count.return_value = 41
|
|
17
|
+
monkeypatch.setattr(builder, "_stack_has_pending", lambda: True)
|
|
18
|
+
monkeypatch.setattr(builder, "_get_executor_async", AsyncMock(return_value=executor))
|
|
19
|
+
all_rows = AsyncMock(return_value=[object()] * 1000)
|
|
20
|
+
monkeypatch.setattr(builder, "all", all_rows)
|
|
21
|
+
|
|
22
|
+
assert await builder.count(include_pending=False) == 41
|
|
23
|
+
executor.count.assert_awaited_once_with()
|
|
24
|
+
all_rows.assert_not_awaited()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.mark.asyncio
|
|
28
|
+
async def test_count_preserves_read_your_own_writes_by_default(monkeypatch):
|
|
29
|
+
builder = QueryBuilder(AsyncMock())
|
|
30
|
+
monkeypatch.setattr(builder, "_stack_has_pending", lambda: True)
|
|
31
|
+
monkeypatch.setattr(builder, "all", AsyncMock(return_value=[object(), object()]))
|
|
32
|
+
|
|
33
|
+
assert await builder.count() == 2
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
|
|
5
|
+
import asyncpg
|
|
5
6
|
import pytest
|
|
6
7
|
from matrx_orm.core.async_db_manager import AsyncDatabaseManager
|
|
7
8
|
from matrx_orm.core.pool_maintenance import (
|
|
@@ -9,6 +10,7 @@ from matrx_orm.core.pool_maintenance import (
|
|
|
9
10
|
acquire_connected_holder,
|
|
10
11
|
maintain_one_connection,
|
|
11
12
|
)
|
|
13
|
+
from matrx_orm.exceptions import ConnectionError as OrmConnectionError
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
class FakeProxy:
|
|
@@ -85,6 +87,33 @@ class FakePool:
|
|
|
85
87
|
self._queue.put_nowait(proxy.holder)
|
|
86
88
|
|
|
87
89
|
|
|
90
|
+
@pytest.mark.asyncio
|
|
91
|
+
async def test_get_connection_classifies_admin_shutdown_during_acquire(monkeypatch) -> None:
|
|
92
|
+
class RestartingPool:
|
|
93
|
+
async def acquire(self) -> None:
|
|
94
|
+
raise asyncpg.exceptions.AdminShutdownError(
|
|
95
|
+
"terminating connection due to administrator command"
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
config_name = "restart-handshake"
|
|
99
|
+
pool = RestartingPool()
|
|
100
|
+
|
|
101
|
+
async def fake_get_pool(cls: type[AsyncDatabaseManager], name: str) -> object:
|
|
102
|
+
return pool
|
|
103
|
+
|
|
104
|
+
monkeypatch.setattr(
|
|
105
|
+
AsyncDatabaseManager,
|
|
106
|
+
"get_pool",
|
|
107
|
+
classmethod(fake_get_pool),
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
with pytest.raises(OrmConnectionError) as caught:
|
|
111
|
+
async with AsyncDatabaseManager.get_connection(config_name, timeout=0.01):
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
assert isinstance(caught.value.__cause__, asyncpg.exceptions.AdminShutdownError)
|
|
115
|
+
assert "administrator command" in str(caught.value)
|
|
116
|
+
|
|
88
117
|
@pytest.mark.asyncio
|
|
89
118
|
async def test_maintenance_grows_exactly_one_disconnected_holder() -> None:
|
|
90
119
|
pool = FakePool(connected=7, maximum=20)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/python_sql/table_detailed_relationships.py
RENAMED
|
File without changes
|
{matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/python_sql/table_typescript_relationship.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{matrx_orm-3.1.119 → matrx_orm-3.1.121}/matrx_orm/schema_builder/helpers/entity_generators.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|