Ctrl K
ComunidadGuías…

CLAUDE.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# 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/`)