matrx-orm 3.1.113__tar.gz → 3.1.115__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.113 → matrx_orm-3.1.115}/PKG-INFO +1 -1
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/FEATURE.md +24 -1
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/session/lifecycle.py +42 -26
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/pyproject.toml +1 -1
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_watched_lifecycle.py +64 -1
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/.gitignore +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/AGENTS.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/BASE_CLASS_METHODS.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/CLAUDE.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/MODEL_API.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/database/orm/extended/managers/ai_model_base.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/docs/migrations.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/MODULE_README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/adapters/MODULE_README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/adapters/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/adapters/async_postgresql.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/adapters/base_adapter.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/adapters/postgresql.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/adapters/postgrest_client_adapter.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/adapters/supabase_adapter.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/admin/FEATURE.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/admin/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/admin/router.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/api/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/api/auth.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/api/config.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/api/handlers.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/api/protocol.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/api/server.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/associations.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/cache_debug.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/catalog.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/catalog_sql.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/client/MODULE_README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/client/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/client/postgres_connection.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/client/postgrest.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/client/supabase_auth.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/client/supabase_config.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/client/supabase_manager.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/EXTENDED-TASK.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/FEATURE.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/MODULE_README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/RELATIONS-TASKS.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/TASKS.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/async_db_manager.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/base.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/config.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/connections.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/db_function.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/diagnostics.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/expressions.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/extended.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/fields.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/introspection.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/listen.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/loop_filters.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/model_dto.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/model_view.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/one_database.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/paginator.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/pool_maintenance.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/pool_watch.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/pooler_role.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/pydantic_bridge.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/registry.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/relations.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/resilience.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/rls_session.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/signals.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/tls.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/transaction.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/types.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/core/write_queue.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/entity.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/error_handling.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/exceptions.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/extended/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/extended/app_error_handler.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/identity_rule.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/local_sqlite.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/middleware/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/middleware/base.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/migrations/MODULE_README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/migrations/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/migrations/cli.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/migrations/ddl.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/migrations/diff.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/migrations/executor.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/migrations/integration.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/migrations/loader.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/migrations/operations.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/migrations/state.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/migrations/table_filter.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/FEATURE.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/MODULE_README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/bulk_update_values.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/conflict.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/conflict_writes.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/create.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/db_functions.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/delete.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/dynamic_admin.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/dynamic_crud.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/graph_walk.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/latest_rows.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/queue_claim.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/read.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/relational_backfill.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/staging_load.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/operations/update.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/platform_db.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/py.typed +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/python_sql/MODULE_README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/python_sql/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/python_sql/db_objects.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/query/FEATURE.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/query/MODULE_README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/query/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/query/builder.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/query/executor.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/FEATURE.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/MODULE_README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/code_handler.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/codegen_writer.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/columns.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/common.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/diff_preview.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/entity_capabilities.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/generator.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/helpers/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/package_wiring.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/relationships.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/runner.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/schema.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/schema_manager.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/tables.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/schema_builder/views.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/secrets_battery/FEATURE.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/secrets_battery/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/secrets_battery/attachments.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/secrets_battery/crypto.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/secrets_battery/host_authorization.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/secrets_battery/items.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/secrets_battery/model.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/secrets_battery/org_service.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/secrets_battery/service.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/session/README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/session/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/session/coalesce.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/session/dag.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/session/errors.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/session/fallback.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/session/flush.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/session/managed.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/session/op.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/session/reads.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/session/session.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/session/telemetry.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/sql_executor/MODULE_README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/sql_executor/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/sql_executor/executor.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/sql_executor/queries.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/sql_executor/registry.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/sql_executor/types.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/sql_executor/utils.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/state.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/utils/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/utils/sql_utils.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/utils/type_converters.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/scripts/git-branches.sh +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/scripts/publish.sh +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/scripts/release.sh +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/MODULE_README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/conftest.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/MODULE_README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_admin_db_columns.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_admin_response_rendering.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_admin_search_negation.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_admin_search_sentinels.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_advisory_lock.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_agent_message.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_api_auth.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_api_config.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_api_handlers.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_api_protocol.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_array_agg_order_by.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_associations.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_bulk_hydration_offload.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_bulk_update_by_pk.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_bulk_upsert_increment_set_fields.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_cache_debug.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_call_function.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_case_when.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_catalog.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_composite_pk_filter.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_composite_pk_write_paths.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_config.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_conflict_target.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_conflict_writes.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_connection_codecs.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_connection_poison_guard.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_connection_primitives.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_count_composite_distinct.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_db_function_field.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_ddl_generator.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_derived_table.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_dirty_tracking.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_dynamic_crud.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_exceptions.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_execute_query_integrity_mapping.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_expression_primitives.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_fields.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_filter_jsonb_agg_array_index.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_from_alias.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_fts.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_func_expression_args.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_graph_walk.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_having_annotate_alias.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_insert_ignore_and_admin_primitives.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_introspect_rls_policies.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_join_and_aggregate.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_latest_rows.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_listen_notify.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_local_sqlite.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_managed_write_guard.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_matrx_entity.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_migration_diff_types.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_migration_loader.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_model_instance.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_model_meta.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_optimistic_concurrency.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_order_by_expression.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_parameter_name_hydration.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_patch_jsonb_path.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_pool_holder_census.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_pool_loop_recreation.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_pool_maintenance.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_postgrest_filters.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_pydantic_bridge.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_query_builder.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_query_error_detail.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_query_executor_sql.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_query_timeout.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_querybuilder_clone_semantics.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_queue_claim.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_read_connection_retry.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_registry.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_registry_multi_database.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_registry_multi_schema.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_relational_backfill.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_relations.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_resilience.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_rls_session_scope.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_schema_exists.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_session_advisory_lock.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_state_cache.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_subquery_filter_raw.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_subquery_in_filter.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_subquery_nested_expressions.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_supabase_auth.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_supabase_config.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_tls.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_typed_join_projection.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_typed_predicates.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_update_case_expression.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_update_subquery.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_update_with_rebase.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_upsert_default_leak.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_upsert_with_conflict.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_values_jsonb_decode.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level1/test_write_retry_semantics.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level2/MODULE_README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level2/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level2/conftest.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level2/test_bulk_ops.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level2/test_cache_integration.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level2/test_crud.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level2/test_foreign_keys.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level2/test_m2m.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level2/test_manager.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level2/test_migrations_live.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level2/test_query_execution.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/level2/test_schema_diff.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/live_pooler_role.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/sample_project/.env.example +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/sample_project/README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/sample_project/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/sample_project/generate.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/sample_project/generated/.gitkeep +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/sample_project/matrx_orm.yaml +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/sample_project/test_schema_generation.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/sample_project_desktop/.env.example +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/sample_project_desktop/README.md +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/sample_project_desktop/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/sample_project_desktop/client_example.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/sample_project_desktop/client_example.ts +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/sample_project_desktop/client_supabase_example.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/sample_project_desktop/server.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema/entity_tests.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema/test_base_generation.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema/test_composite_pk_fk_generation.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema/test_composite_unique_generation.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema/test_dto_identity_generation.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema/test_entity_capability_generation.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema/test_enum_ordering.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema/test_generate_schema.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema/test_junction_analysis.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema/test_multi_schema_output.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema/test_schema_analysis.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema/test_sql_expression_defaults.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema/test_table_relationships_query.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema/test_view_generation.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema_builder/test_array_default_parsing.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema_builder/test_focused_generation_plan.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/schema_builder/test_host_models_aggregator.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/session/__init__.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/session/conftest.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/session/test_cache_no_downgrade.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/session/test_capture_poison_proof.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/session/test_coalesce.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/session/test_dag.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/session/test_disk_spill_fallback.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/session/test_flush_individual_fallback.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/session/test_governed_write.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/session/test_managed.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/session/test_op_enqueue_site.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/session/test_reads.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/session/test_session.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/test_database_name_alias.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/test_db_functions.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/test_model_cls_refactor.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/test_no_blocking_asyncpg_tls.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/test_one_database.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/test_pooler_role_guard.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/test_secrets_battery.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/test_secrets_minting_keys.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/test_sql_param_casts.py +0 -0
- {matrx_orm-3.1.113 → matrx_orm-3.1.115}/tests/test_sync_twins_guard.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: matrx-orm
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.115
|
|
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
|
|
@@ -34,10 +34,33 @@
|
|
|
34
34
|
|
|
35
35
|
- Runtime hierarchy and formatting: `exceptions.py`
|
|
36
36
|
- Failure capture + org stamping: `session/fallback.py`
|
|
37
|
-
-
|
|
37
|
+
- Watched-lifecycle recovery: `session/lifecycle.py`
|
|
38
|
+
- Focused unit coverage: `tests/level1/test_exceptions.py`,
|
|
39
|
+
`tests/level1/test_watched_lifecycle.py`
|
|
40
|
+
|
|
41
|
+
## Watchdog reads use the resilient SELECT boundary
|
|
42
|
+
|
|
43
|
+
- **Lifecycle SELECTs call `adapter.execute_query`.** They inherit the ORM's
|
|
44
|
+
bounded retry for one transient command timeout on a fresh connection.
|
|
45
|
+
- **Raw borrowed-connection reads are forbidden here.** A direct `conn.fetch`
|
|
46
|
+
bypasses read recovery and turns a healthy table's transient timeout into a
|
|
47
|
+
`lifecycle_watchdog_query_failure`.
|
|
48
|
+
|
|
49
|
+
## Watchdog transitions are the alert claim
|
|
50
|
+
|
|
51
|
+
- **Only the replica that changes a timed-out row emits its stuck-row alert.**
|
|
52
|
+
`_transition_stuck_row()` returns the guarded UPDATE result; losing replicas
|
|
53
|
+
suppress duplicate `app_log` and `system_error` records for the same row.
|
|
54
|
+
- **Alert-only watches still report the SELECT result.** With no timeout
|
|
55
|
+
transition there is no database claim, so their in-process reminder cadence
|
|
56
|
+
remains authoritative.
|
|
38
57
|
|
|
39
58
|
## Change Log
|
|
40
59
|
|
|
60
|
+
- 2026-08-26 — Made the guarded timeout transition the multi-replica alert
|
|
61
|
+
claim so one stuck row produces one structured watchdog occurrence.
|
|
62
|
+
- 2026-08-26 — Routed watched-lifecycle SELECTs through the resilient adapter
|
|
63
|
+
read boundary so one transient command timeout retries on a fresh connection.
|
|
41
64
|
- 2026-08-24 — Lifecycle watchdog ERROR boundaries now call `record_error` so
|
|
42
65
|
stuck rows plus SELECT/transition failures reach `ops.system_error` instead
|
|
43
66
|
of existing only in `app_log`.
|
|
@@ -415,15 +415,18 @@ async def _fetch_stuck_rows(
|
|
|
415
415
|
|
|
416
416
|
adapter = AdapterRegistry.get(database)
|
|
417
417
|
sql, params = _build_select_query(cfg, limit)
|
|
418
|
-
|
|
419
|
-
|
|
418
|
+
# Route watchdog reads through the adapter's normal SELECT boundary. That
|
|
419
|
+
# path retries one transient command timeout on a fresh connection; using
|
|
420
|
+
# a raw borrowed connection here bypassed that recovery and emitted a
|
|
421
|
+
# lifecycle_watchdog_query_failure for an otherwise healthy table.
|
|
422
|
+
return await adapter.execute_query(sql, *params)
|
|
420
423
|
|
|
421
424
|
|
|
422
425
|
async def _transition_stuck_row(
|
|
423
426
|
cfg: WatchedLifecycleConfig,
|
|
424
427
|
pk_value: Any,
|
|
425
428
|
database: str | None,
|
|
426
|
-
) ->
|
|
429
|
+
) -> bool:
|
|
427
430
|
"""UPDATE one stuck row at timeout. Fully parameterized.
|
|
428
431
|
|
|
429
432
|
Builds the SET list dynamically so a single UPDATE atomically applies, in
|
|
@@ -442,7 +445,7 @@ async def _transition_stuck_row(
|
|
|
442
445
|
and not cfg.extra_fields_on_timeout
|
|
443
446
|
and not cfg.extra_expression_fields_on_timeout
|
|
444
447
|
):
|
|
445
|
-
return
|
|
448
|
+
return False
|
|
446
449
|
|
|
447
450
|
from matrx_orm.adapters import AdapterRegistry
|
|
448
451
|
from matrx_orm.core.config import get_all_database_project_names
|
|
@@ -482,7 +485,7 @@ async def _transition_stuck_row(
|
|
|
482
485
|
)
|
|
483
486
|
|
|
484
487
|
if not set_clauses:
|
|
485
|
-
return
|
|
488
|
+
return False
|
|
486
489
|
|
|
487
490
|
predicate_sql = cfg.predicate.as_sql(params)
|
|
488
491
|
params.append(pk_value)
|
|
@@ -500,7 +503,10 @@ async def _transition_stuck_row(
|
|
|
500
503
|
f"AND {cfg.age_column} < now() - make_interval(secs => ${age_param})"
|
|
501
504
|
)
|
|
502
505
|
async with adapter.get_connection() as conn:
|
|
503
|
-
await conn.execute(sql, *params)
|
|
506
|
+
result = await conn.execute(sql, *params)
|
|
507
|
+
# Multiple app replicas run the sweep. The guarded UPDATE is the claim:
|
|
508
|
+
# only the replica that changed the row may report it as newly stuck.
|
|
509
|
+
return result == "UPDATE 1"
|
|
504
510
|
|
|
505
511
|
|
|
506
512
|
def _format_watchdog_db_failure(
|
|
@@ -625,9 +631,34 @@ async def sweep_once(
|
|
|
625
631
|
_should_emit_stuck_rows_alert(cfg, stuck_count=0)
|
|
626
632
|
continue
|
|
627
633
|
|
|
634
|
+
claimed_rows = rows
|
|
635
|
+
if cfg.transition_to_on_timeout is not None:
|
|
636
|
+
claimed_rows = []
|
|
637
|
+
for row in rows:
|
|
638
|
+
try:
|
|
639
|
+
if await _transition_stuck_row(cfg, row["pk"], database):
|
|
640
|
+
claimed_rows.append(row)
|
|
641
|
+
except Exception as exc:
|
|
642
|
+
banner, structured = _format_watchdog_db_failure(
|
|
643
|
+
cfg, "UPDATE", exc, pk=row["pk"]
|
|
644
|
+
)
|
|
645
|
+
vcprint(banner, color="red")
|
|
646
|
+
logger.error("watchdog_update_failed", extra=structured)
|
|
647
|
+
await _capture_watchdog_error(
|
|
648
|
+
exc,
|
|
649
|
+
kind="lifecycle_watchdog_transition_failure",
|
|
650
|
+
cfg=cfg,
|
|
651
|
+
phase="update",
|
|
652
|
+
database=database,
|
|
653
|
+
)
|
|
654
|
+
|
|
655
|
+
claimed_count = len(claimed_rows)
|
|
656
|
+
if claimed_count == 0:
|
|
657
|
+
continue
|
|
658
|
+
|
|
628
659
|
color = _alert_color(cfg.alert_channel)
|
|
629
660
|
ages_seconds = []
|
|
630
|
-
for row in
|
|
661
|
+
for row in claimed_rows:
|
|
631
662
|
try:
|
|
632
663
|
aged: datetime = row["aged"]
|
|
633
664
|
if aged.tzinfo is None:
|
|
@@ -637,10 +668,10 @@ async def sweep_once(
|
|
|
637
668
|
pass
|
|
638
669
|
max_age_seen = max(ages_seconds) if ages_seconds else 0
|
|
639
670
|
|
|
640
|
-
if _should_emit_stuck_rows_alert(cfg, stuck_count=
|
|
671
|
+
if _should_emit_stuck_rows_alert(cfg, stuck_count=claimed_count):
|
|
641
672
|
summary = _format_stuck_rows_summary(
|
|
642
673
|
cfg,
|
|
643
|
-
stuck_count=
|
|
674
|
+
stuck_count=claimed_count,
|
|
644
675
|
max_age_seen=max_age_seen,
|
|
645
676
|
)
|
|
646
677
|
_emit_stuck_rows_summary(summary, color=color)
|
|
@@ -650,7 +681,7 @@ async def sweep_once(
|
|
|
650
681
|
"matrx_watchdog": {
|
|
651
682
|
"table": cfg.table,
|
|
652
683
|
"schema": cfg.schema,
|
|
653
|
-
"stuck_count":
|
|
684
|
+
"stuck_count": claimed_count,
|
|
654
685
|
"predicate": repr(cfg.predicate),
|
|
655
686
|
"max_age_secs": cfg.max_age_secs,
|
|
656
687
|
"alert_channel": cfg.alert_channel,
|
|
@@ -664,25 +695,10 @@ async def sweep_once(
|
|
|
664
695
|
kind="lifecycle_watchdog_stuck_rows",
|
|
665
696
|
cfg=cfg,
|
|
666
697
|
phase="stuck_rows",
|
|
667
|
-
stuck_count=
|
|
698
|
+
stuck_count=claimed_count,
|
|
668
699
|
database=database,
|
|
669
700
|
)
|
|
670
701
|
|
|
671
|
-
for row in rows:
|
|
672
|
-
try:
|
|
673
|
-
await _transition_stuck_row(cfg, row["pk"], database)
|
|
674
|
-
except Exception as exc:
|
|
675
|
-
banner, structured = _format_watchdog_db_failure(cfg, "UPDATE", exc, pk=row["pk"])
|
|
676
|
-
vcprint(banner, color="red")
|
|
677
|
-
logger.error("watchdog_update_failed", extra=structured)
|
|
678
|
-
await _capture_watchdog_error(
|
|
679
|
-
exc,
|
|
680
|
-
kind="lifecycle_watchdog_transition_failure",
|
|
681
|
-
cfg=cfg,
|
|
682
|
-
phase="update",
|
|
683
|
-
database=database,
|
|
684
|
-
)
|
|
685
|
-
|
|
686
702
|
return out
|
|
687
703
|
|
|
688
704
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "matrx-orm"
|
|
3
|
-
version = "3.1.
|
|
3
|
+
version = "3.1.115"
|
|
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" }
|
|
@@ -80,6 +80,7 @@ def captured_update(monkeypatch):
|
|
|
80
80
|
async def execute(self, sql, *params):
|
|
81
81
|
captured["sql"] = sql
|
|
82
82
|
captured["params"] = params
|
|
83
|
+
return "UPDATE 1"
|
|
83
84
|
|
|
84
85
|
class _Adapter:
|
|
85
86
|
@asynccontextmanager
|
|
@@ -138,6 +139,37 @@ async def test_timeout_update_stamps_extra_fields(captured_update):
|
|
|
138
139
|
)
|
|
139
140
|
|
|
140
141
|
|
|
142
|
+
@pytest.mark.asyncio
|
|
143
|
+
async def test_stuck_row_select_uses_resilient_adapter_read(monkeypatch):
|
|
144
|
+
captured: dict[str, object] = {}
|
|
145
|
+
|
|
146
|
+
class _Adapter:
|
|
147
|
+
async def execute_query(self, sql, *params):
|
|
148
|
+
captured["sql"] = sql
|
|
149
|
+
captured["params"] = params
|
|
150
|
+
return [{"pk": "call-1", "aged": lc.datetime.now(lc.UTC)}]
|
|
151
|
+
|
|
152
|
+
def get_connection(self):
|
|
153
|
+
raise AssertionError("watchdog SELECT bypassed the resilient read boundary")
|
|
154
|
+
|
|
155
|
+
fake_adapters = types.ModuleType("matrx_orm.adapters")
|
|
156
|
+
fake_adapters.AdapterRegistry = types.SimpleNamespace(get=lambda db: _Adapter())
|
|
157
|
+
monkeypatch.setitem(sys.modules, "matrx_orm.adapters", fake_adapters)
|
|
158
|
+
|
|
159
|
+
cfg = lc.WatchedLifecycleConfig(
|
|
160
|
+
schema="chat",
|
|
161
|
+
table="tool_call",
|
|
162
|
+
predicate=ArrayAny(F("status"), ["pending", "running"]),
|
|
163
|
+
max_age_secs=1800,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
rows = await lc._fetch_stuck_rows(cfg, "matrx", 500)
|
|
167
|
+
|
|
168
|
+
assert rows[0]["pk"] == "call-1"
|
|
169
|
+
assert "FROM chat.tool_call" in str(captured["sql"])
|
|
170
|
+
assert captured["params"] == (["pending", "running"], 1800)
|
|
171
|
+
|
|
172
|
+
|
|
141
173
|
@pytest.mark.asyncio
|
|
142
174
|
async def test_extra_fields_only_without_status_transition(captured_update):
|
|
143
175
|
cfg = lc.WatchedLifecycleConfig(
|
|
@@ -300,7 +332,7 @@ async def test_sweep_forces_stuck_row_into_system_error(monkeypatch):
|
|
|
300
332
|
return [{"pk": "job-1", "aged": lc.datetime.now(lc.UTC)}]
|
|
301
333
|
|
|
302
334
|
async def fake_transition(*_args, **_kwargs):
|
|
303
|
-
return
|
|
335
|
+
return True
|
|
304
336
|
|
|
305
337
|
async def fake_record_error(_exc: BaseException, **fields):
|
|
306
338
|
captured.append(fields)
|
|
@@ -316,6 +348,37 @@ async def test_sweep_forces_stuck_row_into_system_error(monkeypatch):
|
|
|
316
348
|
assert [row["kind"] for row in captured] == ["lifecycle_watchdog_stuck_rows"]
|
|
317
349
|
|
|
318
350
|
|
|
351
|
+
@pytest.mark.asyncio
|
|
352
|
+
async def test_sweep_only_alerts_replica_that_wins_timeout_transition(monkeypatch):
|
|
353
|
+
captured: list[dict] = []
|
|
354
|
+
cfg = lc.WatchedLifecycleConfig(
|
|
355
|
+
table="tool_call",
|
|
356
|
+
schema="chat",
|
|
357
|
+
predicate=Compare(F("status"), "=", "running"),
|
|
358
|
+
max_age_secs=1800,
|
|
359
|
+
transition_to_on_timeout="error",
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
async def fake_fetch(*_args, **_kwargs):
|
|
363
|
+
return [{"pk": "call-1", "aged": lc.datetime.now(lc.UTC)}]
|
|
364
|
+
|
|
365
|
+
async def lost_transition_race(*_args, **_kwargs):
|
|
366
|
+
return False
|
|
367
|
+
|
|
368
|
+
async def fake_record_error(_exc: BaseException, **fields):
|
|
369
|
+
captured.append(fields)
|
|
370
|
+
|
|
371
|
+
monkeypatch.setattr(lc.WatchedLifecycleRegistry, "all", lambda: [cfg])
|
|
372
|
+
monkeypatch.setattr(lc, "_fetch_stuck_rows", fake_fetch)
|
|
373
|
+
monkeypatch.setattr(lc, "_transition_stuck_row", lost_transition_race)
|
|
374
|
+
monkeypatch.setattr(lc, "_emit_stuck_rows_summary", lambda *_args, **_kwargs: None)
|
|
375
|
+
monkeypatch.setattr(lc, "record_error", fake_record_error)
|
|
376
|
+
|
|
377
|
+
await lc.sweep_once(database="matrx")
|
|
378
|
+
|
|
379
|
+
assert captured == []
|
|
380
|
+
|
|
381
|
+
|
|
319
382
|
def test_alert_only_watch_alerts_on_change_and_hourly_reminder():
|
|
320
383
|
cfg = lc.WatchedLifecycleConfig(
|
|
321
384
|
table="system_write_failure",
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{matrx_orm-3.1.113 → matrx_orm-3.1.115}/matrx_orm/python_sql/table_detailed_relationships.py
RENAMED
|
File without changes
|
{matrx_orm-3.1.113 → matrx_orm-3.1.115}/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
|