lora-python 0.8.1__tar.gz → 0.8.3__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.
- {lora_python-0.8.1 → lora_python-0.8.3}/Cargo.lock +16 -16
- {lora_python-0.8.1 → lora_python-0.8.3}/Cargo.toml +11 -11
- {lora_python-0.8.1 → lora_python-0.8.3}/PKG-INFO +1 -1
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/Cargo.toml +4 -0
- lora_python-0.8.3/crates/lora-database/benches/concurrency_guard_benchmarks.rs +303 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/database/builder.rs +2 -3
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/database/execute.rs +11 -19
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/database/mod.rs +16 -14
- lora_python-0.8.3/crates/lora-database/src/database/occ.rs +52 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/database/write_guard.rs +113 -17
- lora_python-0.8.3/crates/lora-database/src/durable_io.rs +30 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/lib.rs +1 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/snapshot/mod.rs +7 -18
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/snapshot/store.rs +4 -14
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/stream.rs +3 -5
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/transaction.rs +0 -5
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/wal/admin.rs +4 -4
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/wal/archive/format.rs +3 -2
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/wal/archive/platform.rs +3 -11
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/wal/write_scope.rs +1 -1
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/config.rs +16 -17
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/dir.rs +5 -13
- lora_python-0.8.3/crates/lora-wal/src/io.rs +31 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/lib.rs +1 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/recorder/errors.rs +4 -5
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/recorder/recorder.rs +92 -105
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/recorder/tests.rs +1 -1
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/segment.rs +10 -10
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/testing.rs +10 -2
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/wal/group_flusher.rs +5 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/wal/mod.rs +7 -4
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/wal/tests.rs +2 -22
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/wal/wal.rs +132 -48
- {lora_python-0.8.1 → lora_python-0.8.3}/pyproject.toml +1 -1
- lora_python-0.8.1/crates/lora-database/src/database/occ.rs +0 -137
- {lora_python-0.8.1 → lora_python-0.8.3}/LICENSE +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/README.md +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/bindings/lora-python/.gitignore +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/bindings/lora-python/Cargo.toml +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/bindings/lora-python/LICENSE +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/bindings/lora-python/README.md +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/bindings/lora-python/build.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/bindings/lora-python/examples/async_demo.py +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/bindings/lora-python/examples/basic.py +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/bindings/lora-python/src/errors.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/bindings/lora-python/src/from_python.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/bindings/lora-python/src/lib.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/bindings/lora-python/src/to_python.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/bindings/lora-python/tests/test_async.py +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/bindings/lora-python/tests/test_explain_profile.py +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/bindings/lora-python/tests/test_sync.py +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-analyzer/Cargo.toml +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-analyzer/src/analyzer/clauses.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-analyzer/src/analyzer/expressions.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-analyzer/src/analyzer/mod.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-analyzer/src/analyzer/patterns.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-analyzer/src/analyzer/state.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-analyzer/src/analyzer/tests.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-analyzer/src/errors.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-analyzer/src/lib.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-analyzer/src/resolved.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-analyzer/src/scope.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-analyzer/src/symbols.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-analyzer/tests/error_messages.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-ast/Cargo.toml +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-ast/src/ast.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-ast/src/lib.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-compiler/Cargo.toml +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-compiler/src/lib.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-compiler/src/logical.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-compiler/src/optimizer.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-compiler/src/pattern.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-compiler/src/physical.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-compiler/src/plan_tree.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-compiler/src/planner.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/benches/advanced_benchmarks.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/benches/concurrent_benchmarks.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/benches/engine_benchmarks.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/benches/fixtures.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/benches/perf_smoke_baseline.json +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/benches/perf_smoke_benchmarks.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/benches/scale_benchmarks.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/benches/temporal_spatial_benchmarks.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/benches/wal_benchmarks.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/database/compile.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/database/explain.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/database/graph_api.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/database/profile.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/database/pull_mode.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/database/replay.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/database/stream.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/error.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/explain.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/live_store.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/named.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/plan_cache.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/snapshot/json.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/wal/archive/lock.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/wal/archive/worker.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/wal/archive/workspace.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/wal/archive.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/src/wal/mod.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/advanced_queries.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/aggregation.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/backend_stub.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/binary.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/create.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/error_messages.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/errors.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/explain_profile.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/expressions.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/functions_extended.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/invariants.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/managed_snapshots.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/match.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/merge.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/ordering.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/parameters.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/parser.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/paths.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/projection.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/scale.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/seeds.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/snapshot.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/spatial.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/temporal.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/test_helpers.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/transactions.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/types_advanced.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/union.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/update.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/vectors.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/wal.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/where_clause.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-database/tests/with.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/Cargo.toml +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/errors.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/eval/binops.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/eval/errors.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/eval/expr.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/eval/functions.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/eval/mod.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/eval/point.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/eval/vector.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/executor/helpers.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/executor/immutable.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/executor/mod.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/executor/mutable.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/lib.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/profile.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/aggregate.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/columns.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/context.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/expand.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/filter.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/hydration.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/mod.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/mutable.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/optional.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/path.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/projection.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/scan.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/shape.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/sort.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/source.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/tests.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/traits.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/pull/union.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/src/value.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-executor/tests/error_messages.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-parser/Cargo.toml +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-parser/src/cypher.pest +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-parser/src/errors.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-parser/src/lib.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-parser/src/parser/clauses.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-parser/src/parser/expressions.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-parser/src/parser/literals.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-parser/src/parser/mod.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-parser/src/parser/patterns.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-parser/src/parser/query.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-parser/src/parser/tests.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-parser/src/parser/util.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-parser/tests/error_messages.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-snapshot/Cargo.toml +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-snapshot/src/body.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-snapshot/src/codec.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-snapshot/src/columnar.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-snapshot/src/envelope.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-snapshot/src/errors.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-snapshot/src/format.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-snapshot/src/lib.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-snapshot/src/options.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-snapshot/src/tests.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-snapshot/src/transform.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-snapshot/src/view.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-snapshot/tests/error_messages.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/Cargo.toml +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/lib.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/lock_table.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/memory/graph.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/memory/impls.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/memory/mod.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/memory/property_index.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/memory/snapshot.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/memory/tests.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/mutation.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/snapshot.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/traits.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/binary/mod.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/binary/tests.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/binary/traits.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/binary/types.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/graph.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/mod.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/property_value.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/spatial/distance.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/spatial/mod.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/spatial/point.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/spatial/srid.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/spatial/tests.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/temporal/calendar.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/temporal/date.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/temporal/datetime.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/temporal/duration.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/temporal/format.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/temporal/mod.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/temporal/parsing.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/temporal/time.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/vector/build.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/vector/mod.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/vector/similarity.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/vector/tests.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/src/types/vector/types.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-store/tests/error_messages.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/Cargo.toml +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/codec/decode.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/codec/encode.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/codec/format.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/codec/mod.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/codec/tests.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/errors.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/lock.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/lsn.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/record.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/recorder/mirror.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/recorder/mod.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/src/replay.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/crates/lora-wal/tests/error_messages.rs +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/python/lora_python/__init__.py +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/python/lora_python/_async.py +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/python/lora_python/_native.pyi +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/python/lora_python/py.typed +0 -0
- {lora_python-0.8.1 → lora_python-0.8.3}/python/lora_python/types.py +0 -0
|
@@ -797,7 +797,7 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
|
|
797
797
|
|
|
798
798
|
[[package]]
|
|
799
799
|
name = "lora-analyzer"
|
|
800
|
-
version = "0.8.
|
|
800
|
+
version = "0.8.3"
|
|
801
801
|
dependencies = [
|
|
802
802
|
"lora-ast",
|
|
803
803
|
"lora-parser",
|
|
@@ -807,14 +807,14 @@ dependencies = [
|
|
|
807
807
|
|
|
808
808
|
[[package]]
|
|
809
809
|
name = "lora-ast"
|
|
810
|
-
version = "0.8.
|
|
810
|
+
version = "0.8.3"
|
|
811
811
|
dependencies = [
|
|
812
812
|
"smallvec 2.0.0-alpha.12",
|
|
813
813
|
]
|
|
814
814
|
|
|
815
815
|
[[package]]
|
|
816
816
|
name = "lora-binding-buffer"
|
|
817
|
-
version = "0.8.
|
|
817
|
+
version = "0.8.3"
|
|
818
818
|
dependencies = [
|
|
819
819
|
"lora-database",
|
|
820
820
|
"lora-store",
|
|
@@ -822,7 +822,7 @@ dependencies = [
|
|
|
822
822
|
|
|
823
823
|
[[package]]
|
|
824
824
|
name = "lora-compiler"
|
|
825
|
-
version = "0.8.
|
|
825
|
+
version = "0.8.3"
|
|
826
826
|
dependencies = [
|
|
827
827
|
"lora-analyzer",
|
|
828
828
|
"lora-ast",
|
|
@@ -830,7 +830,7 @@ dependencies = [
|
|
|
830
830
|
|
|
831
831
|
[[package]]
|
|
832
832
|
name = "lora-database"
|
|
833
|
-
version = "0.8.
|
|
833
|
+
version = "0.8.3"
|
|
834
834
|
dependencies = [
|
|
835
835
|
"anyhow",
|
|
836
836
|
"arc-swap",
|
|
@@ -852,7 +852,7 @@ dependencies = [
|
|
|
852
852
|
|
|
853
853
|
[[package]]
|
|
854
854
|
name = "lora-executor"
|
|
855
|
-
version = "0.8.
|
|
855
|
+
version = "0.8.3"
|
|
856
856
|
dependencies = [
|
|
857
857
|
"lora-analyzer",
|
|
858
858
|
"lora-ast",
|
|
@@ -867,7 +867,7 @@ dependencies = [
|
|
|
867
867
|
|
|
868
868
|
[[package]]
|
|
869
869
|
name = "lora-ffi"
|
|
870
|
-
version = "0.8.
|
|
870
|
+
version = "0.8.3"
|
|
871
871
|
dependencies = [
|
|
872
872
|
"anyhow",
|
|
873
873
|
"lora-binding-buffer",
|
|
@@ -879,7 +879,7 @@ dependencies = [
|
|
|
879
879
|
|
|
880
880
|
[[package]]
|
|
881
881
|
name = "lora-node"
|
|
882
|
-
version = "0.8.
|
|
882
|
+
version = "0.8.3"
|
|
883
883
|
dependencies = [
|
|
884
884
|
"anyhow",
|
|
885
885
|
"lora-binding-buffer",
|
|
@@ -894,7 +894,7 @@ dependencies = [
|
|
|
894
894
|
|
|
895
895
|
[[package]]
|
|
896
896
|
name = "lora-parser"
|
|
897
|
-
version = "0.8.
|
|
897
|
+
version = "0.8.3"
|
|
898
898
|
dependencies = [
|
|
899
899
|
"lora-ast",
|
|
900
900
|
"pest",
|
|
@@ -905,7 +905,7 @@ dependencies = [
|
|
|
905
905
|
|
|
906
906
|
[[package]]
|
|
907
907
|
name = "lora-python"
|
|
908
|
-
version = "0.8.
|
|
908
|
+
version = "0.8.3"
|
|
909
909
|
dependencies = [
|
|
910
910
|
"anyhow",
|
|
911
911
|
"lora-database",
|
|
@@ -917,7 +917,7 @@ dependencies = [
|
|
|
917
917
|
|
|
918
918
|
[[package]]
|
|
919
919
|
name = "lora-server"
|
|
920
|
-
version = "0.8.
|
|
920
|
+
version = "0.8.3"
|
|
921
921
|
dependencies = [
|
|
922
922
|
"anyhow",
|
|
923
923
|
"axum",
|
|
@@ -931,7 +931,7 @@ dependencies = [
|
|
|
931
931
|
|
|
932
932
|
[[package]]
|
|
933
933
|
name = "lora-snapshot"
|
|
934
|
-
version = "0.8.
|
|
934
|
+
version = "0.8.3"
|
|
935
935
|
dependencies = [
|
|
936
936
|
"argon2",
|
|
937
937
|
"bincode",
|
|
@@ -946,7 +946,7 @@ dependencies = [
|
|
|
946
946
|
|
|
947
947
|
[[package]]
|
|
948
948
|
name = "lora-store"
|
|
949
|
-
version = "0.8.
|
|
949
|
+
version = "0.8.3"
|
|
950
950
|
dependencies = [
|
|
951
951
|
"bincode",
|
|
952
952
|
"crc32fast",
|
|
@@ -958,7 +958,7 @@ dependencies = [
|
|
|
958
958
|
|
|
959
959
|
[[package]]
|
|
960
960
|
name = "lora-wal"
|
|
961
|
-
version = "0.8.
|
|
961
|
+
version = "0.8.3"
|
|
962
962
|
dependencies = [
|
|
963
963
|
"crc32fast",
|
|
964
964
|
"lora-store",
|
|
@@ -968,7 +968,7 @@ dependencies = [
|
|
|
968
968
|
|
|
969
969
|
[[package]]
|
|
970
970
|
name = "lora-wasm"
|
|
971
|
-
version = "0.8.
|
|
971
|
+
version = "0.8.3"
|
|
972
972
|
dependencies = [
|
|
973
973
|
"anyhow",
|
|
974
974
|
"console_error_panic_hook",
|
|
@@ -984,7 +984,7 @@ dependencies = [
|
|
|
984
984
|
|
|
985
985
|
[[package]]
|
|
986
986
|
name = "lora_ruby"
|
|
987
|
-
version = "0.8.
|
|
987
|
+
version = "0.8.3"
|
|
988
988
|
dependencies = [
|
|
989
989
|
"anyhow",
|
|
990
990
|
"lora-database",
|
|
@@ -4,7 +4,7 @@ resolver = "2"
|
|
|
4
4
|
|
|
5
5
|
[workspace.package]
|
|
6
6
|
edition = "2021"
|
|
7
|
-
version = "0.8.
|
|
7
|
+
version = "0.8.3"
|
|
8
8
|
license = "BUSL-1.1"
|
|
9
9
|
authors = ["LoraDB, Inc."]
|
|
10
10
|
repository = "https://github.com/lora-db/lora"
|
|
@@ -15,16 +15,16 @@ rust-version = "1.87"
|
|
|
15
15
|
# Internal crates — versions are kept in lockstep with [workspace.package].version
|
|
16
16
|
# by `scripts/sync-versions.mjs`. Both `path` and `version` are set so that
|
|
17
17
|
# `cargo publish` works (crates.io cannot resolve path-only deps).
|
|
18
|
-
lora-ast = { path = "crates/lora-ast", version = "=0.8.
|
|
19
|
-
lora-parser = { path = "crates/lora-parser", version = "=0.8.
|
|
20
|
-
lora-analyzer = { path = "crates/lora-analyzer", version = "=0.8.
|
|
21
|
-
lora-compiler = { path = "crates/lora-compiler", version = "=0.8.
|
|
22
|
-
lora-store = { path = "crates/lora-store", version = "=0.8.
|
|
23
|
-
lora-snapshot = { path = "crates/lora-snapshot", version = "=0.8.
|
|
24
|
-
lora-wal = { path = "crates/lora-wal", version = "=0.8.
|
|
25
|
-
lora-executor = { path = "crates/lora-executor", version = "=0.8.
|
|
26
|
-
lora-database = { path = "crates/lora-database", version = "=0.8.
|
|
27
|
-
lora-binding-buffer = { path = "crates/bindings/lora-binding-buffer", version = "=0.8.
|
|
18
|
+
lora-ast = { path = "crates/lora-ast", version = "=0.8.3" }
|
|
19
|
+
lora-parser = { path = "crates/lora-parser", version = "=0.8.3" }
|
|
20
|
+
lora-analyzer = { path = "crates/lora-analyzer", version = "=0.8.3" }
|
|
21
|
+
lora-compiler = { path = "crates/lora-compiler", version = "=0.8.3" }
|
|
22
|
+
lora-store = { path = "crates/lora-store", version = "=0.8.3" }
|
|
23
|
+
lora-snapshot = { path = "crates/lora-snapshot", version = "=0.8.3", default-features = false }
|
|
24
|
+
lora-wal = { path = "crates/lora-wal", version = "=0.8.3" }
|
|
25
|
+
lora-executor = { path = "crates/lora-executor", version = "=0.8.3" }
|
|
26
|
+
lora-database = { path = "crates/lora-database", version = "=0.8.3" }
|
|
27
|
+
lora-binding-buffer = { path = "crates/bindings/lora-binding-buffer", version = "=0.8.3" }
|
|
28
28
|
|
|
29
29
|
# External crates.
|
|
30
30
|
anyhow = "1"
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
//! Tight local performance guard for concurrency work.
|
|
2
|
+
//!
|
|
3
|
+
//! `perf_smoke_benchmarks` is the broad CI canary and intentionally allows
|
|
4
|
+
//! large runner noise. This suite is narrower and meant for phase-by-phase
|
|
5
|
+
//! local checks while changing the concurrency/write/WAL plumbing:
|
|
6
|
+
//!
|
|
7
|
+
//! ```text
|
|
8
|
+
//! cargo bench -p lora-database --bench concurrency_guard_benchmarks \
|
|
9
|
+
//! -- --output-format bencher > /tmp/lora-before.bencher
|
|
10
|
+
//! # make one implementation step
|
|
11
|
+
//! cargo bench -p lora-database --bench concurrency_guard_benchmarks \
|
|
12
|
+
//! -- --output-format bencher > /tmp/lora-after.bencher
|
|
13
|
+
//! node scripts/check-bench-delta.mjs \
|
|
14
|
+
//! --baseline /tmp/lora-before.bencher \
|
|
15
|
+
//! --current /tmp/lora-after.bencher \
|
|
16
|
+
//! --threshold 1.15
|
|
17
|
+
//! ```
|
|
18
|
+
//!
|
|
19
|
+
//! The cases here deliberately cover the hot surfaces most likely to regress
|
|
20
|
+
//! while introducing concurrent writes: snapshot reads, live streams,
|
|
21
|
+
//! auto-commit writes, explicit transactions, mixed read/write threads, and
|
|
22
|
+
//! WAL-backed write paths.
|
|
23
|
+
|
|
24
|
+
mod fixtures;
|
|
25
|
+
|
|
26
|
+
use std::collections::BTreeMap;
|
|
27
|
+
use std::hint::black_box;
|
|
28
|
+
use std::path::PathBuf;
|
|
29
|
+
use std::sync::{Arc, Barrier};
|
|
30
|
+
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
|
31
|
+
|
|
32
|
+
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
|
|
33
|
+
use fixtures::{build_node_graph, BenchDb, Scale};
|
|
34
|
+
use lora_database::{
|
|
35
|
+
Database, ExecuteOptions, InMemoryGraph, LoraValue, ResultFormat, SyncMode, TransactionMode,
|
|
36
|
+
WalConfig,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
fn opts() -> Option<ExecuteOptions> {
|
|
40
|
+
Some(ExecuteOptions {
|
|
41
|
+
format: ResultFormat::Rows,
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
fn guard_config() -> Criterion {
|
|
46
|
+
Criterion::default()
|
|
47
|
+
.warm_up_time(Duration::from_millis(400))
|
|
48
|
+
.measurement_time(Duration::from_millis(1_800))
|
|
49
|
+
.sample_size(30)
|
|
50
|
+
.noise_threshold(0.08)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
struct ScratchDir {
|
|
54
|
+
path: PathBuf,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
impl ScratchDir {
|
|
58
|
+
fn new(tag: &str) -> Self {
|
|
59
|
+
let mut path = std::env::temp_dir();
|
|
60
|
+
path.push(format!(
|
|
61
|
+
"lora-concurrency-guard-{}-{}-{}",
|
|
62
|
+
tag,
|
|
63
|
+
std::process::id(),
|
|
64
|
+
SystemTime::now()
|
|
65
|
+
.duration_since(UNIX_EPOCH)
|
|
66
|
+
.unwrap()
|
|
67
|
+
.as_nanos()
|
|
68
|
+
));
|
|
69
|
+
std::fs::create_dir_all(&path).unwrap();
|
|
70
|
+
Self { path }
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
impl Drop for ScratchDir {
|
|
75
|
+
fn drop(&mut self) {
|
|
76
|
+
let _ = std::fs::remove_dir_all(&self.path);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
fn wal_config(dir: &std::path::Path, sync_mode: SyncMode) -> WalConfig {
|
|
81
|
+
WalConfig::Enabled {
|
|
82
|
+
dir: dir.to_path_buf(),
|
|
83
|
+
sync_mode,
|
|
84
|
+
segment_target_bytes: 8 * 1024 * 1024,
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
fn int_param(name: &str, value: i64) -> BTreeMap<String, LoraValue> {
|
|
89
|
+
let mut params = BTreeMap::new();
|
|
90
|
+
params.insert(name.to_string(), LoraValue::Int(value));
|
|
91
|
+
params
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
fn two_int_params(a: (&str, i64), b: (&str, i64)) -> BTreeMap<String, LoraValue> {
|
|
95
|
+
let mut params = BTreeMap::new();
|
|
96
|
+
params.insert(a.0.to_string(), LoraValue::Int(a.1));
|
|
97
|
+
params.insert(b.0.to_string(), LoraValue::Int(b.1));
|
|
98
|
+
params
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
fn bench_concurrency_guard(c: &mut Criterion) {
|
|
102
|
+
let mut group = c.benchmark_group("concurrency_guard");
|
|
103
|
+
|
|
104
|
+
// Snapshot read path: catches regressions in `LiveStore::load_full`,
|
|
105
|
+
// plan execution, and read-only WAL prechecks.
|
|
106
|
+
{
|
|
107
|
+
let db = build_node_graph(Scale::SMALL);
|
|
108
|
+
group.bench_function("read_scan_1k", |b| {
|
|
109
|
+
b.iter(|| {
|
|
110
|
+
black_box(
|
|
111
|
+
db.service
|
|
112
|
+
.execute("MATCH (n:Node) RETURN n.id", opts())
|
|
113
|
+
.unwrap(),
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Live read stream: pins an Arc snapshot and drops after one row.
|
|
120
|
+
{
|
|
121
|
+
let db = build_node_graph(Scale::SMALL);
|
|
122
|
+
group.bench_function("stream_pull_one_1k", |b| {
|
|
123
|
+
b.iter(|| {
|
|
124
|
+
let mut stream = db.service.stream("MATCH (n:Node) RETURN n.id").unwrap();
|
|
125
|
+
black_box(stream.next_row().unwrap());
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Auto-commit create on one long-lived DB. This keeps the benchmark on the
|
|
131
|
+
// write hot path instead of measuring fixture setup.
|
|
132
|
+
{
|
|
133
|
+
let db = BenchDb::new();
|
|
134
|
+
let mut next = 0i64;
|
|
135
|
+
group.bench_function("write_create_one_steady", |b| {
|
|
136
|
+
b.iter(|| {
|
|
137
|
+
next += 1;
|
|
138
|
+
black_box(
|
|
139
|
+
db.service
|
|
140
|
+
.execute_with_params(
|
|
141
|
+
"CREATE (:Guard {id: $id})",
|
|
142
|
+
opts(),
|
|
143
|
+
int_param("id", next),
|
|
144
|
+
)
|
|
145
|
+
.unwrap(),
|
|
146
|
+
);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Existing-record write on a 1k graph. Future per-record commit
|
|
152
|
+
// validation should keep this close to the current single-writer cost.
|
|
153
|
+
{
|
|
154
|
+
let db = build_node_graph(Scale::SMALL);
|
|
155
|
+
let mut next = 0i64;
|
|
156
|
+
group.bench_function("write_set_existing_1k", |b| {
|
|
157
|
+
b.iter(|| {
|
|
158
|
+
next += 1;
|
|
159
|
+
black_box(
|
|
160
|
+
db.service
|
|
161
|
+
.execute_with_params(
|
|
162
|
+
"MATCH (n:Node {id: $id}) SET n.value = $value",
|
|
163
|
+
opts(),
|
|
164
|
+
two_int_params(("id", 500), ("value", next)),
|
|
165
|
+
)
|
|
166
|
+
.unwrap(),
|
|
167
|
+
);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Fixed explicit transaction cost. This should stay tiny while
|
|
173
|
+
// introducing concurrent write bookkeeping.
|
|
174
|
+
{
|
|
175
|
+
let db = build_node_graph(Scale::SMALL);
|
|
176
|
+
group.bench_function("tx_roundtrip_empty", |b| {
|
|
177
|
+
b.iter(|| {
|
|
178
|
+
let tx = db
|
|
179
|
+
.service
|
|
180
|
+
.begin_transaction(TransactionMode::ReadWrite)
|
|
181
|
+
.unwrap();
|
|
182
|
+
tx.commit().unwrap();
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Explicit transaction write path, including buffering recorder and
|
|
188
|
+
// publish. Fresh DB per iteration so the committed write cannot
|
|
189
|
+
// accumulate into the next sample.
|
|
190
|
+
group.bench_function("tx_write_create_one", |b| {
|
|
191
|
+
b.iter_batched(
|
|
192
|
+
BenchDb::new,
|
|
193
|
+
|db| {
|
|
194
|
+
let mut tx = db
|
|
195
|
+
.service
|
|
196
|
+
.begin_transaction(TransactionMode::ReadWrite)
|
|
197
|
+
.unwrap();
|
|
198
|
+
black_box(tx.execute("CREATE (:TxGuard {id: 1})", opts()).unwrap());
|
|
199
|
+
tx.commit().unwrap();
|
|
200
|
+
},
|
|
201
|
+
BatchSize::SmallInput,
|
|
202
|
+
);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// Mixed reader/writer pressure. Thread spawn overhead is intentional here:
|
|
206
|
+
// this is a coarse local guard for accidental global locks on read paths.
|
|
207
|
+
{
|
|
208
|
+
let db = Arc::new(build_node_graph(Scale::SMALL).service);
|
|
209
|
+
let mut next = 0i64;
|
|
210
|
+
group.bench_function("mixed_4_readers_1_writer", |b| {
|
|
211
|
+
b.iter(|| {
|
|
212
|
+
next += 1;
|
|
213
|
+
let barrier = Arc::new(Barrier::new(5));
|
|
214
|
+
let handles: Vec<_> = (0..4)
|
|
215
|
+
.map(|_| {
|
|
216
|
+
let db = db.clone();
|
|
217
|
+
let barrier = barrier.clone();
|
|
218
|
+
std::thread::spawn(move || {
|
|
219
|
+
barrier.wait();
|
|
220
|
+
black_box(db.execute("MATCH (n:Node) RETURN n.id", opts()).unwrap());
|
|
221
|
+
})
|
|
222
|
+
})
|
|
223
|
+
.collect();
|
|
224
|
+
|
|
225
|
+
let writer = {
|
|
226
|
+
let db = db.clone();
|
|
227
|
+
let barrier = barrier.clone();
|
|
228
|
+
std::thread::spawn(move || {
|
|
229
|
+
barrier.wait();
|
|
230
|
+
black_box(
|
|
231
|
+
db.execute_with_params(
|
|
232
|
+
"CREATE (:MixedGuard {id: $id})",
|
|
233
|
+
opts(),
|
|
234
|
+
int_param("id", next),
|
|
235
|
+
)
|
|
236
|
+
.unwrap(),
|
|
237
|
+
);
|
|
238
|
+
})
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
for handle in handles {
|
|
242
|
+
handle.join().unwrap();
|
|
243
|
+
}
|
|
244
|
+
writer.join().unwrap();
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// WAL write paths without the per-iteration directory setup measured.
|
|
250
|
+
// `None` isolates WAL encoding/flush-buffer overhead; cooperative Group
|
|
251
|
+
// isolates the path that future concurrent fsync coordination will touch.
|
|
252
|
+
{
|
|
253
|
+
let dir = ScratchDir::new("wal-none");
|
|
254
|
+
let db = Database::<InMemoryGraph>::open_with_wal(wal_config(&dir.path, SyncMode::None))
|
|
255
|
+
.unwrap();
|
|
256
|
+
let mut next = 0i64;
|
|
257
|
+
group.bench_function("wal_none_create_delete_one", |b| {
|
|
258
|
+
b.iter(|| {
|
|
259
|
+
next += 1;
|
|
260
|
+
black_box(
|
|
261
|
+
db.execute_with_params(
|
|
262
|
+
"CREATE (n:WalGuard {id: $id}) DELETE n",
|
|
263
|
+
opts(),
|
|
264
|
+
int_param("id", next),
|
|
265
|
+
)
|
|
266
|
+
.unwrap(),
|
|
267
|
+
);
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
{
|
|
273
|
+
let dir = ScratchDir::new("wal-group");
|
|
274
|
+
let db = Database::<InMemoryGraph>::open_with_wal(wal_config(
|
|
275
|
+
&dir.path,
|
|
276
|
+
SyncMode::Group { interval_ms: 50 },
|
|
277
|
+
))
|
|
278
|
+
.unwrap();
|
|
279
|
+
let mut next = 0i64;
|
|
280
|
+
group.bench_function("wal_group_create_delete_one", |b| {
|
|
281
|
+
b.iter(|| {
|
|
282
|
+
next += 1;
|
|
283
|
+
black_box(
|
|
284
|
+
db.execute_with_params(
|
|
285
|
+
"CREATE (n:WalGuard {id: $id}) DELETE n",
|
|
286
|
+
opts(),
|
|
287
|
+
int_param("id", next),
|
|
288
|
+
)
|
|
289
|
+
.unwrap(),
|
|
290
|
+
);
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
group.finish();
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
criterion_group! {
|
|
299
|
+
name = benches;
|
|
300
|
+
config = guard_config();
|
|
301
|
+
targets = bench_concurrency_guard,
|
|
302
|
+
}
|
|
303
|
+
criterion_main!(benches);
|
|
@@ -132,9 +132,8 @@ impl Database<InMemoryGraph> {
|
|
|
132
132
|
let mirror: Arc<dyn WalMirror> = archive;
|
|
133
133
|
let recorder = Arc::new(WalRecorder::new_with_mirror(wal, Some(mirror)));
|
|
134
134
|
// Mark the archive dirty so a fresh named database is materialized as
|
|
135
|
-
// a portable ZIP.
|
|
136
|
-
//
|
|
137
|
-
// on database drop.
|
|
135
|
+
// a portable ZIP. Follow-up writes refresh the archive on explicit
|
|
136
|
+
// `sync()` / checkpoint and on clean database drop.
|
|
138
137
|
recorder.flush()?;
|
|
139
138
|
Ok(Self::from_graph_with_wal(graph, recorder, None))
|
|
140
139
|
}
|
|
@@ -68,21 +68,17 @@ where
|
|
|
68
68
|
/// 2. The executor runs; every primitive mutation fires
|
|
69
69
|
/// `MutationRecorder::record`, which buffers events in memory.
|
|
70
70
|
/// 3. On Ok, `recorder.commit()` writes `TxBegin`, one batched
|
|
71
|
-
/// mutation record, and `TxCommit` only when mutations occurred
|
|
72
|
-
///
|
|
73
|
-
/// a read-only query never pays an `fsync`.
|
|
71
|
+
/// mutation record, and `TxCommit` only when mutations occurred,
|
|
72
|
+
/// then applies the WAL's configured single-thread flush policy.
|
|
74
73
|
/// 4. On Err, `recorder.abort()` clears the pending batch. The
|
|
75
74
|
/// engine has no rollback, so the in-memory state may already
|
|
76
75
|
/// be partially mutated; the live handle is quarantined while
|
|
77
76
|
/// durable recovery stays atomic because no committed batch was
|
|
78
77
|
/// written.
|
|
79
|
-
/// 5. The recorder's poisoned flag is polled once
|
|
80
|
-
///
|
|
81
|
-
///
|
|
82
|
-
///
|
|
83
|
-
/// refuses further appends until the operator restarts the
|
|
84
|
-
/// database, which recovers from the last consistent
|
|
85
|
-
/// snapshot + WAL.
|
|
78
|
+
/// 5. The recorder's poisoned flag is polled once. If set, the query
|
|
79
|
+
/// fails loudly with the durability error so the caller can act on it;
|
|
80
|
+
/// the WAL refuses further appends until the operator restarts the
|
|
81
|
+
/// database, which recovers from the last consistent snapshot + WAL.
|
|
86
82
|
pub fn execute_with_params(
|
|
87
83
|
&self,
|
|
88
84
|
query: &str,
|
|
@@ -157,15 +153,11 @@ where
|
|
|
157
153
|
.map_err(anyhow::Error::from);
|
|
158
154
|
}
|
|
159
155
|
|
|
160
|
-
// Mutating path. Drop the snapshot
|
|
161
|
-
//
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
// critical section). Multiple auto-commit writers can run
|
|
166
|
-
// their prep work in parallel; they only serialize at the
|
|
167
|
-
// commit point. On conflict (another writer published since
|
|
168
|
-
// we took our snapshot), retry from a fresh snapshot.
|
|
156
|
+
// Mutating path. Drop the snapshot used for compilation and route
|
|
157
|
+
// through the single-writer auto-commit path. The writer mutex is held
|
|
158
|
+
// for mutate + WAL commit so live state and WAL order stay identical.
|
|
159
|
+
// The method name still says "optimistic" because this is the seam a
|
|
160
|
+
// future write-set/CAS implementation can reuse.
|
|
169
161
|
drop(store);
|
|
170
162
|
debug_assert!(shape.is_mutating());
|
|
171
163
|
|
|
@@ -26,7 +26,6 @@ use crate::explain::{QueryPlan, QueryProfile};
|
|
|
26
26
|
use crate::live_store::LiveStore;
|
|
27
27
|
use crate::plan_cache::PlanCache;
|
|
28
28
|
use crate::snapshot::ManagedSnapshotStore;
|
|
29
|
-
use crate::wal::write_scope::WalAbortPolicy;
|
|
30
29
|
|
|
31
30
|
/// Minimal abstraction any transport can depend on to run Lora queries.
|
|
32
31
|
///
|
|
@@ -192,14 +191,12 @@ where
|
|
|
192
191
|
/// Drop every node and relationship, returning WAL/archive errors to the
|
|
193
192
|
/// caller.
|
|
194
193
|
///
|
|
195
|
-
/// When a WAL is attached, the
|
|
196
|
-
///
|
|
197
|
-
///
|
|
198
|
-
///
|
|
199
|
-
/// writes fail until the database is reopened from durable state.
|
|
194
|
+
/// When a WAL is attached, the buffered `MutationEvent::Clear` is appended
|
|
195
|
+
/// to the log on success. The clear runs in place against the live
|
|
196
|
+
/// graph via the same fast path as `with_logged_store_mut`, so a
|
|
197
|
+
/// large graph clear no longer pays an O(N+E) snapshot clone.
|
|
200
198
|
pub fn try_clear(&self) -> Result<(), LoraError> {
|
|
201
|
-
|
|
202
|
-
self.with_logged_write_guard(guard, WalAbortPolicy::AbortOnly, |store| {
|
|
199
|
+
self.with_logged_store_mut(|store| {
|
|
203
200
|
store.clear();
|
|
204
201
|
Ok(())
|
|
205
202
|
})
|
|
@@ -236,13 +233,18 @@ where
|
|
|
236
233
|
|
|
237
234
|
/// Run a closure with an exclusive borrow of the underlying store. Reserved
|
|
238
235
|
/// for admin paths (restore, bulk load); regular mutation goes through
|
|
239
|
-
/// `execute_with_params`. The closure mutates
|
|
240
|
-
///
|
|
236
|
+
/// `execute_with_params`. The closure mutates the live graph in place
|
|
237
|
+
/// via `Arc::make_mut`, so callers don't pay an O(N+E) snapshot clone
|
|
238
|
+
/// just to overwrite the graph. Concurrent readers, when present,
|
|
239
|
+
/// force a single CoW clone and keep observing their pre-mutation
|
|
240
|
+
/// snapshot via the `Arc<S>` they already hold.
|
|
241
241
|
pub fn with_store_mut<R>(&self, f: impl FnOnce(&mut S) -> R) -> R {
|
|
242
|
-
let
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
242
|
+
let _lock = self
|
|
243
|
+
.writer
|
|
244
|
+
.lock()
|
|
245
|
+
.unwrap_or_else(|poisoned| poisoned.into_inner());
|
|
246
|
+
let mut handle = self.store.write();
|
|
247
|
+
f(handle.as_mut())
|
|
246
248
|
}
|
|
247
249
|
}
|
|
248
250
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//! Auto-commit write path for `InMemoryGraph`.
|
|
2
|
+
//!
|
|
3
|
+
//! This module is the dispatcher between [`Database::execute_with_params`]
|
|
4
|
+
//! and the canonical mutating shape in [`super::write_guard`]. It
|
|
5
|
+
//! builds a `MutableExecutor` against the live store and hands it to
|
|
6
|
+
//! [`Database::run_with_durable_recorder`], which owns the writer
|
|
7
|
+
//! mutex, recorder arm/commit/abort lifecycle, and the
|
|
8
|
+
//! managed-snapshot trigger. The single-writer design (`Arc::make_mut`
|
|
9
|
+
//! against the live `Arc<S>`) and the failure trade-off — a query
|
|
10
|
+
//! that fails mid-execution can leave the live graph partially
|
|
11
|
+
//! mutated, but never the durable log — are documented in
|
|
12
|
+
//! [`super::write_guard`].
|
|
13
|
+
|
|
14
|
+
use std::any::Any;
|
|
15
|
+
use std::collections::BTreeMap;
|
|
16
|
+
use std::sync::Arc;
|
|
17
|
+
use std::time::Instant;
|
|
18
|
+
|
|
19
|
+
use anyhow::Result;
|
|
20
|
+
use lora_compiler::CompiledQuery;
|
|
21
|
+
use lora_executor::{LoraValue, MutableExecutionContext, MutableExecutor, Row};
|
|
22
|
+
use lora_store::{GraphStorage, GraphStorageMut};
|
|
23
|
+
|
|
24
|
+
use crate::database::Database;
|
|
25
|
+
|
|
26
|
+
impl<S> Database<S>
|
|
27
|
+
where
|
|
28
|
+
S: GraphStorage + GraphStorageMut + Any + Clone + Send + Sync + 'static,
|
|
29
|
+
{
|
|
30
|
+
/// Auto-commit a mutating query. Builds a `MutableExecutor`
|
|
31
|
+
/// against the staged graph and routes through the canonical
|
|
32
|
+
/// write shape in [`Database::run_with_durable_recorder`].
|
|
33
|
+
pub(crate) fn execute_mutating_optimistic(
|
|
34
|
+
&self,
|
|
35
|
+
params: BTreeMap<String, LoraValue>,
|
|
36
|
+
deadline: Option<Instant>,
|
|
37
|
+
compiled: &Arc<CompiledQuery>,
|
|
38
|
+
) -> Result<Vec<Row>> {
|
|
39
|
+
self.run_with_durable_recorder(|staged| {
|
|
40
|
+
let mut executor = MutableExecutor::with_deadline(
|
|
41
|
+
MutableExecutionContext {
|
|
42
|
+
storage: staged,
|
|
43
|
+
params,
|
|
44
|
+
},
|
|
45
|
+
deadline,
|
|
46
|
+
);
|
|
47
|
+
executor
|
|
48
|
+
.execute_compiled_rows(compiled)
|
|
49
|
+
.map_err(anyhow::Error::from)
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
}
|