jvspatial 0.2.1__tar.gz → 0.2.2__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.
- {jvspatial-0.2.1/jvspatial.egg-info → jvspatial-0.2.2}/PKG-INFO +2 -2
- {jvspatial-0.2.1 → jvspatial-0.2.2}/README.md +1 -1
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/context.py +23 -3
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/_observable.py +27 -31
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/factory.py +6 -7
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/mongodb.py +4 -4
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/postgres.py +366 -90
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/transaction.py +139 -9
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/observability/__init__.py +2 -2
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/version.py +1 -1
- {jvspatial-0.2.1 → jvspatial-0.2.2/jvspatial.egg-info}/PKG-INFO +2 -2
- {jvspatial-0.2.1 → jvspatial-0.2.2}/AUTHORS +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/LICENSE +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/_route_utils.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/_session_store.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/api_key_service.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/cleanup.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/config.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/enhanced.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/models.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/oauth/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/oauth/bridge.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/oauth/client_adapter.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/oauth/dcr.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/oauth/denylist.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/oauth/keys.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/oauth/metadata.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/oauth/models.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/oauth/refresh_store.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/oauth/requests.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/oauth/resource.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/oauth/revocation.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/oauth/routes.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/oauth/server.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/openapi_config.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/rbac.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/auth/service.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/components/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/components/app_builder.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/components/auth_configurator.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/components/auth_middleware.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/components/database_configurator.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/components/endpoint_auth_resolver.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/components/endpoint_manager.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/components/error_handler.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/components/logging_config.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/components/path_matcher.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/config.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/config_groups.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/constants.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/context.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/decorators/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/decorators/deferred_registry.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/decorators/field.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/decorators/function_wrappers.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/decorators/route.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/decorators/route_config.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/deferred_invoke_route.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/endpoints/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/endpoints/factory.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/endpoints/graph_visualization.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/endpoints/metadata.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/endpoints/registry.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/endpoints/response.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/endpoints/router.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/endpoints/walker_executor.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/exceptions.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/integrations/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/integrations/scheduler/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/integrations/scheduler/decorators.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/integrations/scheduler/middleware.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/integrations/scheduler/models.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/integrations/scheduler/scheduler.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/integrations/storage/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/integrations/storage/service.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/integrations/webhooks/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/integrations/webhooks/helpers.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/integrations/webhooks/middleware.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/integrations/webhooks/models.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/integrations/webhooks/utils.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/integrations/webhooks/webhook_auth.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/middleware/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/middleware/manager.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/middleware/rate_limit.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/middleware/rate_limit_backend.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/server.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/server_app_factory.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/server_configurator.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/server_lifecycle.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/server_registration.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/server_run.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/services/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/services/discovery.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/services/file_storage.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/services/lifecycle.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/utils/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/utils/path_utils.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/api/utils/reload.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/async_utils/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/cache/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/cache/base.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/cache/factory.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/cache/layered.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/cache/memory.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/cache/redis.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/cli.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/annotations.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/decorators.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/entities/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/entities/_visit_hooks.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/entities/edge.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/entities/node.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/entities/node_query.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/entities/object.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/entities/root.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/entities/walker.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/entities/walker_components/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/entities/walker_components/event_system.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/entities/walker_components/protection.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/entities/walker_components/trail_store.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/entities/walker_components/walker_queue.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/entities/walker_components/walker_trail.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/events.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/graph.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/graph_context_config.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/graph_expansion.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/graph_payload.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/graph_projection.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/migrations.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/mixins/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/mixins/deferred_save.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/pager.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/utils.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/core/validate.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/_atomic.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/_cache.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/_path_locks.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/_postgres_translate.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/_sqlite_translate.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/database.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/dynamodb.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/jsondb.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/manager.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/query.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/sqlite.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/db/work_claim.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/dev_tools/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/env.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/env_adapter.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/exceptions.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/logging/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/logging/config.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/logging/custom_levels.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/logging/endpoints.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/logging/filter_utils.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/logging/handler.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/logging/models.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/logging/service.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/memory/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/observability/metrics.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/observability/otel.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/observability/tracing.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/profiling/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/py.typed +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/runtime/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/runtime/eventbridge_readiness.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/runtime/lwa.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/runtime/serverless.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/serverless/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/serverless/deferred_invoke.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/serverless/factory.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/serverless/tasks/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/serverless/tasks/aws_lambda.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/serverless/tasks/aws_sqs.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/serverless/tasks/base.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/serverless/tasks/stub.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/serverless/tasks/sync.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/storage/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/storage/exceptions.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/storage/interfaces/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/storage/interfaces/_stream.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/storage/interfaces/base.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/storage/interfaces/local.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/storage/interfaces/s3.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/storage/internal_markers.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/storage/managers/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/storage/managers/proxy.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/storage/models.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/storage/security/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/storage/security/path_sanitizer.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/storage/security/validator.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/testing/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/utils/__init__.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/utils/context.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/utils/decorators.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/utils/deprecation.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/utils/factory.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/utils/normalization.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/utils/retry.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/utils/serialization.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/utils/stability.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/utils/types.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial/utils/validation.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial.egg-info/SOURCES.txt +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial.egg-info/dependency_links.txt +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial.egg-info/entry_points.txt +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial.egg-info/requires.txt +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/jvspatial.egg-info/top_level.txt +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/pyproject.toml +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/setup.cfg +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/tests/test_config.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/tests/test_create_task.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/tests/test_env.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/tests/test_env_adapter_eventbridge_validation.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/tests/test_env_adapter_postgres.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/tests/test_node_operations.py +0 -0
- {jvspatial-0.2.1 → jvspatial-0.2.2}/tests/test_normalize_optional_secret.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jvspatial
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: An asynchronous object-spatial Python library for persistence and business logic application layers.
|
|
5
5
|
Author-email: "TrueSelph Inc." <adminh@trueselph.com>
|
|
6
6
|
License: MIT
|
|
@@ -353,7 +353,7 @@ server = Server(
|
|
|
353
353
|
- [Custom Database Guide](https://github.com/TrueSelph/jvspatial/blob/main/docs/md/custom-database-guide.md) - Implementing custom database backends
|
|
354
354
|
- [Graph Visualization](https://github.com/TrueSelph/jvspatial/blob/main/docs/md/graph-visualization.md) - Export graphs in DOT/Mermaid formats
|
|
355
355
|
- [Pagination](https://github.com/TrueSelph/jvspatial/blob/main/docs/md/pagination.md) - ObjectPager usage
|
|
356
|
-
- [Observability](https://github.com/TrueSelph/jvspatial/blob/main/docs/md/observability.md) -
|
|
356
|
+
- [Observability](https://github.com/TrueSelph/jvspatial/blob/main/docs/md/observability.md) - Failure-only DB logging, operation/slow-call metrics, OpenTelemetry adapter
|
|
357
357
|
- [Performance Benchmarks](https://github.com/TrueSelph/jvspatial/blob/main/docs/md/benchmarks.md) - Regression-detection bench suite (pytest-benchmark + CI workflow)
|
|
358
358
|
- [API Stability](https://github.com/TrueSelph/jvspatial/blob/main/docs/md/stability.md) - Public/internal/experimental tiers and deprecation policy
|
|
359
359
|
|
|
@@ -273,7 +273,7 @@ server = Server(
|
|
|
273
273
|
- [Custom Database Guide](https://github.com/TrueSelph/jvspatial/blob/main/docs/md/custom-database-guide.md) - Implementing custom database backends
|
|
274
274
|
- [Graph Visualization](https://github.com/TrueSelph/jvspatial/blob/main/docs/md/graph-visualization.md) - Export graphs in DOT/Mermaid formats
|
|
275
275
|
- [Pagination](https://github.com/TrueSelph/jvspatial/blob/main/docs/md/pagination.md) - ObjectPager usage
|
|
276
|
-
- [Observability](https://github.com/TrueSelph/jvspatial/blob/main/docs/md/observability.md) -
|
|
276
|
+
- [Observability](https://github.com/TrueSelph/jvspatial/blob/main/docs/md/observability.md) - Failure-only DB logging, operation/slow-call metrics, OpenTelemetry adapter
|
|
277
277
|
- [Performance Benchmarks](https://github.com/TrueSelph/jvspatial/blob/main/docs/md/benchmarks.md) - Regression-detection bench suite (pytest-benchmark + CI workflow)
|
|
278
278
|
- [API Stability](https://github.com/TrueSelph/jvspatial/blob/main/docs/md/stability.md) - Public/internal/experimental tiers and deprecation policy
|
|
279
279
|
|
|
@@ -587,9 +587,22 @@ class GraphContext:
|
|
|
587
587
|
imap = _request_identity_map.get()
|
|
588
588
|
if imap is not None and entity_id in imap:
|
|
589
589
|
result = imap[entity_id]
|
|
590
|
+
# Identity-map entries are context-bound. A transaction replaces
|
|
591
|
+
# the request map, but callers may explicitly use another context
|
|
592
|
+
# while that map is active; do not return an entity attached to a
|
|
593
|
+
# different database handle in that case.
|
|
594
|
+
if getattr(result, "_graph_context", self) is self:
|
|
595
|
+
if self._perf_monitoring_enabled and self._perf_monitor:
|
|
596
|
+
self._perf_monitor.record_cache_hit()
|
|
597
|
+
return result
|
|
598
|
+
# A graph transaction owns an isolated identity map. Consulting the
|
|
599
|
+
# process cache here could return an entity bound to the outer
|
|
600
|
+
# database context, causing reads to escape the transaction and
|
|
601
|
+
# writes to bypass its connection (or expose uncommitted state).
|
|
602
|
+
if self._transaction_cache_keys is not None:
|
|
590
603
|
if self._perf_monitoring_enabled and self._perf_monitor:
|
|
591
|
-
self._perf_monitor.
|
|
592
|
-
return
|
|
604
|
+
self._perf_monitor.record_cache_miss()
|
|
605
|
+
return None
|
|
593
606
|
result = await self._cache.get(entity_id)
|
|
594
607
|
# Track cache hit/miss
|
|
595
608
|
if self._perf_monitoring_enabled and self._perf_monitor:
|
|
@@ -606,6 +619,8 @@ class GraphContext:
|
|
|
606
619
|
imap = _request_identity_map.get()
|
|
607
620
|
if imap is not None:
|
|
608
621
|
imap[entity_id] = entity
|
|
622
|
+
if self._transaction_cache_keys is not None:
|
|
623
|
+
return
|
|
609
624
|
await self._cache.set(entity_id, entity)
|
|
610
625
|
|
|
611
626
|
async def _evict_from_cache(self, entity_id: str) -> None:
|
|
@@ -2275,7 +2290,8 @@ async def graph_transaction(database: Optional[Any] = None):
|
|
|
2275
2290
|
back every write in the block.
|
|
2276
2291
|
|
|
2277
2292
|
Requires a backend that exposes ``begin_transaction``,
|
|
2278
|
-
``commit_transaction``, and ``rollback_transaction`` (
|
|
2293
|
+
``commit_transaction``, and ``rollback_transaction`` (PostgreSQL and
|
|
2294
|
+
transaction-capable MongoDB deployments).
|
|
2279
2295
|
|
|
2280
2296
|
Usage:
|
|
2281
2297
|
async with graph_transaction(db) as ctx:
|
|
@@ -2293,6 +2309,10 @@ async def graph_transaction(database: Optional[Any] = None):
|
|
|
2293
2309
|
"graph_transaction requires a database with begin/commit/rollback"
|
|
2294
2310
|
)
|
|
2295
2311
|
txn = await db.begin_transaction()
|
|
2312
|
+
if txn is None:
|
|
2313
|
+
raise TransactionUnavailable(
|
|
2314
|
+
"The configured deployment cannot start a native transaction"
|
|
2315
|
+
)
|
|
2296
2316
|
ctx = GraphContext(txn)
|
|
2297
2317
|
parent_ctx = _default_context_var.get() or _module_default_context
|
|
2298
2318
|
ctx._transaction_cache_keys = set()
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
"""Observability wrapper for :class:`Database` instances.
|
|
2
2
|
|
|
3
3
|
Wraps any backend (raw or already wrapped in :class:`CachingDatabase`)
|
|
4
|
-
and
|
|
4
|
+
and records, for each operation:
|
|
5
5
|
|
|
6
|
-
1. A structured
|
|
7
|
-
|
|
8
|
-
/ ``success``. DEBUG for successful calls under the threshold;
|
|
9
|
-
WARNING for failures or calls reaching ``slow_query_ms``.
|
|
6
|
+
1. A structured ERROR for failed operations. Successful operations, including
|
|
7
|
+
calls above ``slow_query_ms``, produce no log record.
|
|
10
8
|
2. One metrics emission to the configured :class:`MetricsRecorder`:
|
|
11
9
|
a duration histogram and a counter, both labeled with the standard
|
|
12
10
|
dimensions.
|
|
@@ -63,9 +61,8 @@ from jvspatial.observability.metrics import (
|
|
|
63
61
|
logger = logging.getLogger("jvspatial.db.observable")
|
|
64
62
|
|
|
65
63
|
|
|
66
|
-
# Default slow-query threshold.
|
|
67
|
-
#
|
|
68
|
-
# configuration. Tunable per-instance via ``slow_query_ms``.
|
|
64
|
+
# Default slow-query threshold. Calls above it increment a metric; they do not
|
|
65
|
+
# generate log records. Tunable per-instance via ``slow_query_ms``.
|
|
69
66
|
DEFAULT_SLOW_QUERY_MS = 100.0
|
|
70
67
|
|
|
71
68
|
|
|
@@ -83,15 +80,16 @@ def _backend_label(inner: Database) -> str:
|
|
|
83
80
|
|
|
84
81
|
|
|
85
82
|
class ObservableDatabase(Database):
|
|
86
|
-
"""
|
|
83
|
+
"""Wrap a :class:`Database` with per-operation metrics and sparse logs.
|
|
87
84
|
|
|
88
85
|
Args:
|
|
89
86
|
inner: The wrapped database. May itself be wrapped (e.g. by
|
|
90
87
|
:class:`~jvspatial.db._cache.CachingDatabase`).
|
|
91
88
|
metrics: A :class:`MetricsRecorder`. Defaults to
|
|
92
89
|
:class:`NullMetricsRecorder` (zero overhead).
|
|
93
|
-
slow_query_ms: Threshold above which
|
|
94
|
-
|
|
90
|
+
slow_query_ms: Threshold above which successful calls increment the
|
|
91
|
+
slow-operation metric. Successful calls are not logged. Failures
|
|
92
|
+
are logged at ERROR. Defaults to 100ms.
|
|
95
93
|
"""
|
|
96
94
|
|
|
97
95
|
def __init__(
|
|
@@ -123,7 +121,7 @@ class ObservableDatabase(Database):
|
|
|
123
121
|
*,
|
|
124
122
|
result_count_extractor: Optional[Callable[[Any], int]] = None,
|
|
125
123
|
) -> Any:
|
|
126
|
-
"""Run ``coro_factory()`` while
|
|
124
|
+
"""Run ``coro_factory()`` while recording metrics and failure logs.
|
|
127
125
|
|
|
128
126
|
``coro_factory`` is a thunk so we measure the underlying call
|
|
129
127
|
only, not the time spent constructing the coroutine.
|
|
@@ -186,26 +184,24 @@ class ObservableDatabase(Database):
|
|
|
186
184
|
"collection": collection,
|
|
187
185
|
"success": success,
|
|
188
186
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
log_extra["result_count"] = result_count
|
|
192
|
-
|
|
193
|
-
if query_plan:
|
|
194
|
-
log_extra.update(query_plan)
|
|
195
|
-
if active_duration_s is not None:
|
|
196
|
-
log_extra["active_duration_ms"] = round(active_duration_s * 1000, 3)
|
|
197
|
-
|
|
198
|
-
# Structured log. WARNING when slow or failed, DEBUG otherwise. extra=
|
|
199
|
-
# supplies the structured fields to any handler that
|
|
200
|
-
# understands them (json formatters, structlog, etc.).
|
|
187
|
+
# Build failure-only log data lazily. Successful calls do not allocate
|
|
188
|
+
# a logging payload or format a message, even when DEBUG is enabled.
|
|
201
189
|
slow = duration_ms >= self.slow_query_ms
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
190
|
+
if not success and logger.isEnabledFor(logging.ERROR):
|
|
191
|
+
log_extra = {**labels, "duration_ms": round(duration_ms, 3)}
|
|
192
|
+
if result_count is not None:
|
|
193
|
+
log_extra["result_count"] = result_count
|
|
194
|
+
if query_plan:
|
|
195
|
+
log_extra.update(query_plan)
|
|
196
|
+
if active_duration_s is not None:
|
|
197
|
+
log_extra["active_duration_ms"] = round(active_duration_s * 1000, 3)
|
|
198
|
+
logger.error(
|
|
199
|
+
"FAILED db.%s on '%s' took %.2fms",
|
|
200
|
+
op,
|
|
201
|
+
collection,
|
|
202
|
+
duration_ms,
|
|
203
|
+
extra=log_extra,
|
|
204
|
+
)
|
|
209
205
|
|
|
210
206
|
# Metrics. Best-effort -- do not surface backend errors here.
|
|
211
207
|
try:
|
|
@@ -278,12 +278,12 @@ def create_database(
|
|
|
278
278
|
TTL (LRU eviction only).
|
|
279
279
|
observe: When ``True``, wrap the database in an
|
|
280
280
|
:class:`~jvspatial.db._observable.ObservableDatabase` that
|
|
281
|
-
|
|
281
|
+
records metrics per operation and logs failures only.
|
|
282
282
|
Defaults to ``False`` (no behavior change for existing
|
|
283
283
|
callers).
|
|
284
|
-
slow_query_ms: Threshold above which
|
|
285
|
-
|
|
286
|
-
``observe=True``. Defaults to 100ms.
|
|
284
|
+
slow_query_ms: Threshold above which successful operations are
|
|
285
|
+
counted as slow in metrics. Successful operations are not
|
|
286
|
+
logged. Only meaningful when ``observe=True``. Defaults to 100ms.
|
|
287
287
|
metrics: Optional :class:`~jvspatial.observability.metrics.MetricsRecorder`
|
|
288
288
|
implementation. Defaults to
|
|
289
289
|
:class:`~jvspatial.observability.metrics.NullMetricsRecorder`
|
|
@@ -345,9 +345,8 @@ def create_database(
|
|
|
345
345
|
db = CachingDatabase(db, max_entries=cache_get_size, ttl_seconds=cache_get_ttl)
|
|
346
346
|
|
|
347
347
|
# Optional observability layer (off by default). Applied AFTER the
|
|
348
|
-
# cache so
|
|
349
|
-
# including cache hits/misses
|
|
350
|
-
# need.
|
|
348
|
+
# cache so metrics and slow-query counters measure user-visible
|
|
349
|
+
# latency including cache hits/misses.
|
|
351
350
|
if observe:
|
|
352
351
|
db = ObservableDatabase(db, metrics=metrics, slow_query_ms=slow_query_ms)
|
|
353
352
|
|
|
@@ -1179,8 +1179,8 @@ class MongoDB(Database):
|
|
|
1179
1179
|
Returns a ``MongoDBTransaction`` whose session is bound to a
|
|
1180
1180
|
``start_transaction`` call. If the deployment does not support
|
|
1181
1181
|
transactions (standalone / DocumentDB without transactions), the
|
|
1182
|
-
returned object will be ``None
|
|
1183
|
-
|
|
1182
|
+
returned object will be ``None``. Callers requiring atomicity must
|
|
1183
|
+
reject that case rather than perform unprotected writes.
|
|
1184
1184
|
"""
|
|
1185
1185
|
from jvspatial.db.transaction import MongoDBTransaction
|
|
1186
1186
|
|
|
@@ -1208,13 +1208,13 @@ class MongoDB(Database):
|
|
|
1208
1208
|
"""Commit the given transaction and end its session."""
|
|
1209
1209
|
if txn is not None:
|
|
1210
1210
|
await txn.commit()
|
|
1211
|
-
txn.session.end_session()
|
|
1211
|
+
await _resolve_driver_result(txn.session.end_session())
|
|
1212
1212
|
|
|
1213
1213
|
async def rollback_transaction(self, txn) -> None:
|
|
1214
1214
|
"""Roll back the given transaction and end its session."""
|
|
1215
1215
|
if txn is not None:
|
|
1216
1216
|
await txn.rollback()
|
|
1217
|
-
txn.session.end_session()
|
|
1217
|
+
await _resolve_driver_result(txn.session.end_session())
|
|
1218
1218
|
|
|
1219
1219
|
async def drop_deprecated_indexes(self, deprecated: Dict[str, List[str]]) -> None:
|
|
1220
1220
|
"""Drop indexes that have been removed or renamed in code.
|