CLAUDE.md
Rama main · réplica de lectura del repositorio original.
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
FalkorDB-rs is a Rust implementation of FalkorDB, a graph database that runs as a Redis module. It implements the Cypher query language using GraphBLAS sparse matrices for efficient graph storage and traversal.
## Reference implementation and performance bar
The C implementation is the reference. It lives on the `master` branch of this
same repository; the easiest way to get a loadable C module is the published
image `docker.io/falkordb/falkordb-server:edge-c`, whose module sits at
`/var/lib/falkordb/bin/falkordb.so`. Note the tag: **`:edge-c`, not `:edge`** —
`:edge` now resolves to the Rust engine and shares a digest with `:edge-rs`, so
anything pointed at `:edge` expecting C is silently measuring Rust.
Extracting the `.so` from that image is the deliberate default rather than a
shortcut: `benchmark-cov.yml` compiles no engine at all, and measures published
images for all three sides (PR, base, C) so that what is measured is what was
shipped. A local `master` build is the alternative and puts a module under
`bin/` — use it when you need a C module on macOS, where the published image is
Linux-only.
Success criterion for performance work: p99 latency of all benchmark queries must be the same or better than C, and memory usage must match C with no per-entity overhead. Always benchmark against the C module and report real numbers.
Prefer general optimizations in shared paths (e.g. expression eval, runtime iterators) over op-specific special cases.
## Build Commands
```bash
# Build (debug)
cargo build
# Build (release)
cargo build --release
# Format check
cargo fmt --all -- --check
# Lint (requires clang++)
CXX=clang++ cargo clippy --all-targets
```
## Testing
**Unit tests (Rust):**
```bash
cargo test -p graph
```
**E2E and function tests (Python):**
```bash
# Activate virtualenv first
source venv/bin/activate
RELEASE=1 pytest tests/test_e2e.py tests/test_functions.py -vv
```
**TCK (Technology Compatibility Kit) tests:**
```bash
# Run all passing TCK tests
RELEASE=1 TCK_DONE=tck_done.txt pytest tests/tck/test_tck.py -s
# Run specific TCK test subset
TCK_INCLUDE=tests/tck/features/expressions/list pytest tests/tck/test_tck.py -s
```
**MVCC and concurrency tests:**
```bash
RELEASE=1 pytest tests/test_mvcc.py tests/test_concurrency.py -vv
```
**Flow tests:**
```bash
# All flow tests
./flow.sh
# Single test, release build, quiet output (the usual way to run these)
RELEASE=1 VERBOSE=0 TEST=test_name ./flow.sh
```
## Dependencies
GraphBLAS, LAGraph and RediSearch are git submodules under `deps/`, built by
the `native-deps` crate:
```bash
git submodule update --init --recursive
cargo build # graph/build.rs calls native-deps; nothing else to run
```
On macOS, export `CC`/`CXX` as Homebrew's clang first (see README): the system
clang has no OpenMP, and GraphBLAS would silently build single-threaded.
git owns those checkouts — `native-deps` only builds what is there. The gitlink
is the authoritative pin; `deps/native-deps.lock` mirrors it for contexts with
no `.git` (the Docker dep stages), and CI checks the two agree. The Docker images COPY the
submodules in, so any workflow feeding one needs `submodules: recursive`.
`native-deps` caches its output at
`${XDG_CACHE_HOME:-$HOME/.cache}/falkordb/native-deps/<dep>/<key>/`
(`$FALKORDB_DEPS_CACHE` overrides the root). The key covers the submodule revision, the GB_control
patch, the vendored PreJIT kernels, the recipe sources, `$CC`/`$CXX --version`,
the target triple and the OpenMP/sanitizer flavour — so worktrees share archives
and a compiler bump never yields a stale-ABI cache hit. Build them explicitly
with `cargo run --manifest-path native-deps/Cargo.toml`.
To bump a dependency, move the gitlink and stage it (`git add deps/<Name>`:
`lock` reads the pin from the index), then re-run
`cargo run --manifest-path native-deps/Cargo.toml -- lock`; CI enforces that
`deps/native-deps.lock` matches via `lock --check`.
### PreJIT kernels (`build/graphblas/PreJIT/`)
The `GB_jit__*.c` files in `build/graphblas/PreJIT/` are AUTOGENERATED by
`native-deps prejit` from GraphBLAS's runtime JIT. NEVER hand-edit or locally
harvest them — ALWAYS regenerate them by running
`cargo run --manifest-path native-deps/Cargo.toml -- prejit` inside the
Linux Docker toolchain image (`ghcr.io/falkordb/falkordb-build`, the
production/CI target). Kernels harvested on macOS can embed platform-specific
JIT defn strings (e.g. Apple fortify headers rewrite `memcpy` to
`__builtin___memcpy_chk`), which makes their `_query` hash check fail on
Linux and GraphBLAS silently falls back to slow generic kernels.
Python tests require a virtualenv:
```bash
python3 -m venv venv
source venv/bin/activate
pip install -r tests/requirements.txt
```
## Architecture
### Crate Structure
- **`falkordb-rs`** (root `src/`) - Redis module integration, command handlers, response serialization
- **`graph`** (`graph/src/`) - Core graph database implementation, query processing, runtime
### Query Processing Pipeline
```text
Cypher Query String
│
▼
┌─────────────────┐
│ Parser │ cypher.rs - Hand-written recursive descent parser
│ (cypher.rs) │ Produces: DynTree<ExprIR<Arc<String>>>
└─────────────────┘
│
▼
┌─────────────────┐
│ Binder │ binder.rs - Semantic analysis, name resolution
│ (binder.rs) │ Resolves variable names to numeric IDs
└─────────────────┘
│
▼
┌─────────────────┐
│ Planner │ planner.rs - Converts AST to execution plan (IR tree)
│ (planner.rs) │ IR operators: NodeByLabelScan, CondTraverse, Filter, etc.
└─────────────────┘
│
▼
┌─────────────────┐
│ Optimizer │ optimizer.rs - Index utilization, node-by-ID optimization
│ (optimizer.rs) │ Rewrites plan for better performance
└─────────────────┘
│
▼
┌─────────────────┐
│ Runtime │ runtime/runtime.rs - Pull-based iterator execution
│ (runtime/) │ Evaluates IR tree, manages pending mutations
└─────────────────┘
```
### Graph Storage Model (`graph/src/graph/`)
- **graph.rs** - Main Graph struct: adjacency matrices, label matrices, relationship tensors, attribute stores
- **matrix.rs** - GraphBLAS sparse matrix wrapper (FFI to C library)
- **vector.rs** - GraphBLAS sparse vector wrapper
- **tensor.rs** - 3D sparse structure for relationship storage (src × dst × edge_id)
- **versioned_matrix.rs** - Copy-on-write matrix with version tracking
- **mvcc_graph.rs** - MVCC wrapper providing snapshot isolation for reads, serialized writes
- **attribute_store.rs** - Property storage for nodes and relationships
- **block_vec.rs** - Block-allocated vector for efficient memory usage
### Concurrency Model
- **Read queries**: Execute concurrently on thread pool using MVCC snapshots
- **Write queries**: Serialized through mpsc channel, processed by single thread
- **ThreadedGraph** (`src/lib.rs`): Wraps MvccGraph with write queue for Redis integration
### Redis Commands
- `GRAPH.QUERY` - Read/write Cypher queries (blocks client, executes on thread pool)
- `GRAPH.RO_QUERY` - Read-only queries (errors on write operations)
- `GRAPH.EXPLAIN` - Show execution plan without executing
- `GRAPH.DELETE` - Delete a graph
- `GRAPH.LIST` - List all graphs
- `GRAPH.MEMORY` - Get memory usage
### Key Types
- **Value** (`runtime/value.rs`) - Runtime value enum: Null, Bool, Int, Float, String, List, Map, Node, Relationship, Path, Point, etc.
- **IR** (`planner.rs`) - Intermediate representation nodes for execution plan
- **Env** (`runtime/value.rs`) - Variable bindings flowing through pipeline
- **Pending** (`runtime/pending.rs`) - Batched mutations for transactional semantics
## Code Style
- Uses `rustfmt` with vertical function parameter layout (`fn_params_layout = "Vertical"`)
- Bring items into scope with `use`; do not write fully-qualified paths at the call
site. Prefer `use crate::query_session::QuerySession;` and then
`QuerySession::begin(graph)` over `crate::query_session::QuerySession::begin(graph)`
(see `src/commands/explain.rs`)
- The parser (`cypher.rs`) is hand-written, not generated from Cypher.g4 grammar file
- GraphBLAS FFI bindings are in `graph/src/graph/GraphBLAS.rs` (auto-generated, do not edit)
## Configuration
- `CACHE_SIZE` - Query plan cache size (default: 25, range: 0-1000)
- `IMPORT_FOLDER` - CSV import path (default: `/var/lib/FalkorDB/import/`)