LakeSoul is a cloud-native Lakehouse framework (LF AI & Data sandbox project, v3.0.0). It provides ACID transactions, LSM-Tree style upserts, schema evolution, CDC ingestion, time travel, and unified batch/streaming processing.
The codebase is split across two build systems:
- Rust (Cargo workspace) — native metadata client and IO/merge layer
- Java/Scala (Maven multi-module) — Spark, Flink, and Presto integrations, plus a Java JNI bridge to the Rust layer
LakeSoul/
├── rust/ # Cargo workspace root (active members below)
│ ├── proto/ # Protobuf definitions (entity.proto) + generated Rust types
│ ├── lakesoul-metadata/ # PostgreSQL metadata client (tokio-postgres, bb8 pool)
│ ├── lakesoul-metadata-c/ # C FFI shim over lakesoul-metadata (for Java JNI)
│ ├── lakesoul-io/ # Native IO: Arrow/DataFusion/Parquet read-merge-write
│ ├── lakesoul-io-c/ # C FFI shim over lakesoul-io (for Java JNI)
│ ├── lakesoul-datafusion/ # DataFusion SQL integration
│ ├── lakesoul-flight/ # Arrow Flight server (workspace-disabled, WIP)
│ ├── lakesoul-s3-proxy/ # S3 proxy (workspace-disabled, WIP)
│ └── lakesoul-console/ # CLI console (workspace-disabled, WIP)
│
├── native-io/
│ └── lakesoul-io-java/ # Java JNI bridge (loads liblakesoul_io_c.so / .dylib)
│
├── lakesoul-common/ # Shared Java utilities (protobuf, config, etc.)
├── lakesoul-spark/ # Apache Spark 3.3 integration (Scala 2.12)
├── lakesoul-flink/ # Apache Flink integration (Java + Scala)
├── lakesoul-presto/ # Presto/Trino integration
├── lakesoul-spark-gluten/ # Spark + Gluten/Velox integration (optional Maven profile)
│
├── python/ # Python bindings (maturin/PyO3, pyproject.toml)
│
├── script/
│ ├── meta_init.sql # PostgreSQL schema DDL
│ ├── meta_init_for_local_test.sh
│ ├── meta_rbac_init.sql # RBAC row-level security policies
│ └── meta_cleanup.sql
│
└── docker/ # Docker-compose setups for local dev
| Component | Technology |
|---|---|
| Metadata store | PostgreSQL 14+ (ACID, MVCC, RBAC row-level security) |
| Native IO/merge | Rust — DataFusion, Arrow, Parquet, object_store |
| Async runtime | Tokio (full features) |
| gRPC | Tonic |
| Java bridge | JNI via lakesoul-io-c / lakesoul-metadata-c (C FFI) |
| Spark | Apache Spark 3.5.8, Scala 2.12 |
| Flink | Apache Flink (Java + Scala) |
| Python | PyO3 + maturin, pyarrow |
| Build (Rust) | Cargo stable toolchain + rustfmt + clippy |
| Build (JVM) | Maven, Java 8 target |
-
PostgreSQL 14+ running locally with a test database:
./script/meta_init_for_local_test.sh -j 1
Default test credentials: user=
lakesoul_test, password=lakesoul_test, db=lakesoul_test -
protoc (Protocol Buffers compiler) — required for Rust
build.rscode generation. -
JDK 11 (for Maven builds, despite Java 8 source/target compatibility).
# Build all active workspace members
cargo -q build
# Build release
cargo -q build --release
# Run all tests (requires PostgreSQL)
RUST_BACKTRACE=full cargo test
# Run tests for a specific package
cargo -q test --package lakesoul-io
cargo -q test --package lakesoul-metadata
# Lint
cargo fmt --all --check
cargo clippy
# Build the C FFI libraries (used by Java JNI)
cargo -q build --release -p lakesoul-io-c
cargo -q build --release -p lakesoul-metadata-c
# Output: rust/target/release/liblakesoul_io_c.so (Linux) or .dylib (macOS)The Rust toolchain is pinned to stable in rust-toolchain.toml.
The Java build requires the Rust C FFI .so/.dylib files to be built first
and placed at rust/target/release/.
# Build everything (skip tests)
mvn -q -B clean package -DskipTests --file pom.xml
# Run Spark tests (subset 1)
mvn -q -B clean test -pl lakesoul-spark -am -Pcross-build -Pparallel-test \
-Dtest='UpdateScalaSuite,ReadSuite,...' -Dsurefire.failIfNoSpecifiedTests=false
# Run Flink tests
mvn -q -B clean test -pl lakesoul-flink -am -Pcross-build
# Enable Gluten/Velox profile
mvn -q -B clean package -Pgluten -DskipTests
# Generate test report
mvn surefire-report:report-only -pl lakesoul-spark -amThe Python package uses maturin to compile the Rust extension and uv for dependency management.
cd python
# Install dev dependencies
uv sync --group dev
# Build and install the Rust extension in-place (development mode)
uv run maturin develop
# Run tests
uv run pytest tests/
# Build a release wheel
uv run maturin build --release- All table/partition/data-commit metadata is stored in PostgreSQL.
- The
DaoTypeenum insrc/lib.rsenumerates every SQL operation (select, insert, update, delete). execute_query,execute_insert,execute_updateare the three async entry points used by both Rust and the JNI bridge.- Connection pooling via
bb8-postgres; results cached withcachedcrate. - RBAC uses PostgreSQL row-level security (
meta_rbac_init.sql).
- Implements vectorised merge-on-read for LSM-Tree style hash-partitioned tables.
- Built on DataFusion physical plan execution; custom
PhysicalPlannodes live insrc/physical_plan/. - Object store abstraction via
object_storecrate (S3, local, HDFS optional viahdfsfeature). - Local disk data cache implemented in
src/cache/. LakeSoulReader(src/reader.rs) and async writer (src/writer/) are the primary public APIs.- Parquet is the underlying file format.
- Loads native shared libraries at runtime from the classpath.
- Provides Java-callable wrappers for
LakeSoulReader,LakeSoulWriter, and metadata operations.
LakeSoulSparkSessionExtensionregisters custom rules and strategies.LakeSoulTableis the DataFrame/SQL API entry point (similar to Delta'sDeltaTable).SparkMetaVersionbridges Spark to the metadata client via JNI.- Custom ANTLR4 grammar extends Spark SQL with LakeSoul-specific syntax.
- Compaction service lives under
spark/compaction/.
- Provides
TableSourceandTableSinkfor both batch and streaming. - Supports Flink CDC with auto DDL sync and exactly-once semantics.
| Variable | Purpose |
|---|---|
lakesoul.pg.url |
PostgreSQL JDBC URL for metadata |
RUST_BACKTRACE |
Set to full for detailed Rust panics in tests |
RUSTFLAGS |
Set to -Awarnings in CI to suppress warnings as errors |
Local config files:
lakesoul.properties— default runtime propertiespg.property— PostgreSQL connection details for local dev
- Use
cargo -qinstead ofcargo. - Use
mvn -qinstead ofmvn. - Prefer quiet command output unless debugging failures.
This repo has large generated/lock files. Do not open them unless the user asks or the task requires them.
Avoid:
- Cargo.lock
- **/target/
- **/build/
- .direnv/
- .devenv/
- **/node_modules/
- **/uv.lcok
- flake.lock
For dependency questions, read Cargo.toml first. Only inspect Cargo.lock for
lockfile conflicts, exact resolved versions, supply-chain audit, or reproducible
build issues.
Do not read Cargo.lock unless the task is specifically about dependency resolution, lockfile conflicts, version auditing, or reproducible builds.
Prefer reading Cargo.toml first for dependency questions.
When searching the repository, exclude generated or lock files where possible: rg --glob '!Cargo.lock' ...
| Workflow | Trigger | What it does |
|---|---|---|
rust-ci.yml |
Push/PR to rust/** |
Cargo test with PostgreSQL + RustFS services, plus Clippy lint check |
maven-test.yml |
Push/PR (non-rust paths) | Builds Rust .so, then runs Spark + Flink Maven tests |
flink-cdc-test.yml |
Scheduled/PR | End-to-end Flink CDC tests |
python-ci.yml |
Push/PR to python/** |
Python build + pytest |
native-build.yml |
Push/PR | Linux x64 native library builds |
- Branch naming:
feature/<short-description>orbug/<short-description> - PR title format:
[Component] Description(e.g.,[Flink] add table source implementation) - All changes should include tests.
- Keep diffs small and self-contained.
- Open an issue before large changes to discuss the approach.
- Tag issues with the relevant component (
spark,flink,rust,python, etc.).
- Protoc not installed —
cargo -q buildwill fail with a codegen error. Installprotocfirst. - Native libraries missing for Maven tests —
lakesoul-io-javaneeds the.so/.dylibon the classpath or atrust/target/release/. Build Rust first. - PostgreSQL not running — both Rust and JVM tests need a live PostgreSQL instance. Run
meta_init_for_local_test.shto initialize the schema. - Workspace-disabled crates —
lakesoul-datafusion,lakesoul-flight, etc. are commented out inCargo.toml. Add them back to thememberslist to build them. - Python maturin build — must run from the
python/directory, not the repo root; the rootCargo.tomldoes not include thepythoncrate in active members.
Output (focus on building a data-flow mental model, not file-by-file summaries):
-
Entry points
- External APIs, public functions, or interfaces where data enters the system
-
Core data structures
- Key structs/enums/objects and their roles in the data flow
-
Data flow path
- End-to-end path: input → transformations → output
- Highlight intermediate representations
-
State mutation points
- Where and how state changes occur
-
Concurrency paths
- Async tasks, threads, channels, or event-driven flows
-
Error flow
- Where errors originate, how they propagate, and how they are handled
-
Call chains
- Key function call sequences along the main data flow
-
Potential risks
- Race conditions, stale state, resource leaks, or inconsistent state
Finally:
- Provide an ASCII data flow diagram
- Explicitly point out areas of uncertainty or assumptions
When reviewing pull requests, ignore changes to Cargo.lock.
Do not leave review comments on Cargo.lock unless:
- the lockfile change introduces an obvious supply-chain/security risk;
- the PR is specifically about dependency updates;
- the user explicitly asks to review lockfile changes.
For normal code reviews, treat Cargo.lock changes as generated dependency-resolution output.
Focus review comments on source code, build configuration, tests, and public API behavior.