Add native Fluss log-table connector#3
Conversation
f490465 to
3ce10db
Compare
|
Questions:
"Partitioned tables with partitioned discovery enabled" -> I wonder if you can tell me more about these? Do we want to be supporting partitioned logs from the start? Otherwise this feels like more of just a benchmarking feature |
|
Additionally - how was this change tested? do we have round trip tests to ensure config is right? And that we're reading the right fluss messages? |
|
Thanks for taking this on — the overall shape is exactly what the design (ticket 44 / What's done well
Must fix — correctness1. Dropped partitions never leave the reader's checkpoint state. Fluss's own split reader accumulates removed split IDs and reports them as finished splits through the next 2. No type vetting anywhere. 3. The benchmark compares different engines running different plans. The stock rung runs in batch mode via Fluss's limit-read path (capped at 2,048 rows, limit pushed into a dedicated RPC); the native rung runs in streaming with the Should fix
Minor
|
|
Re-reviewed the new patchset ( New critical issue: the type gate and the benchmark contradict each otherCommit The two right fixes compose: land timestamp (and ideally struct) support across the boundary — a post-decode unit/zone cast in the Rust reader is cheap and stays columnar — or, if deferring that, benchmark an honestly-labeled flattened-schema variant and reword the roadmap/docs to say the Nexmark rung is blocked on boundary type support. Realistically, TIMESTAMP is table stakes for a streaming source; without it the zero-transpose story doesn't reach any real workload, so the roadmap "done" wording should be softened either way — today this is a flat-scalar-table source. Related precision issue: the gate checks the full catalog schema ( What was fixed well
Still open
|
Removed splits now surface through RecordsWithSplitIds.finishedSplits so SourceReaderBase drops them from checkpoint state instead of re-subscribing dropped partitions on restore; native unassign purges pending batches to match. Empty bounded splits finish immediately at assign. Reaching a stopping offset now retires the bucket from both routing maps so in-flight batches cannot emit rows past the stop. Unparseable partition-not-exist errors degrade to the enumerator's removal path instead of failing the job, subscribes are batched per assignment, the reader honors the context configuration, and the unused writer/lookup config plumbing is gone. Harness now covers drop-to-finished reporting and multi-bucket reads.
The matcher now whitelists the 13 type roots verified to round-trip between fluss-rs's Arrow export and the vendored Arrow conversion (TIMESTAMP and TIMESTAMP_LTZ are excluded until the unit/timezone mismatch is resolved) and requires the ARROW log format. Every decline records a reason through the planner's fallbackReasons channel, including translator fallbacks and reflection failures. The translator declines unrecognized client options and non-PLAINTEXT/SASL-PLAIN security instead of silently diverging, while writer and lookup options are ignored as read-irrelevant. A parity test writes the whitelisted type surface once and compares stock and native reads row for row.
The stock rung previously ran in batch mode through Fluss's limit-read path, capped at 2,048 rows, while the native rung ran in streaming with the LIMIT as a Top-N operator, so the reported ratio compared different plans at a startup-dominated scale. Both engines now run the identical SQL in the default streaming runtime at SF_ROWS scale, measuring time-to-Nth-row with a count-then-cancel sink calibrated per query. Numbers in docs/benchmarks.md are pending a full run.
CI gains a fluss-tests job so the feature-gated suites stop silently skipping, the fluss-rs fork pin documents that its only change is the arrow alignment pending an upstream bump, and the board reflects the shipped Fluss source.
2c9f47e to
cfebbab
Compare
|
Took another pass over the latest patchset ( The blockers are properly fixed
CI: the new job failed on a missing system dependency (its first run — it did its job)
Two levels of fix:
Two remaining one-liners (non-blocking)
Bottom line: mergeable once |
Summary
This PR adds the native Fluss log-table source path and the Fluss Nexmark baseline scaffold.
The shape is the same pattern as the native Kafka source: keep Fluss/Flink coordination on the JVM side, reuse Fluss' enumerator for startup offsets, partition discovery, and split assignment, then pass the assigned log splits into Rust so
fluss-rscan read ArrowRecordBatches directly.What's In Here
SF_MATRIX_FLUSS=trueNexmark matrix rung using a local Fluss test cluster.flussfeature.flusscargo feature: open table scan, subscribe assigned buckets, pollScanBatches, honor stopping offsets, and export Arrow through C Data.LogSplits and get handed to Rust with table/partition/bucket/offset info.PartitionsRemovedEvent-> native split removal/unsubscribe ->PartitionBucketsUnsubscribedEvent.IOExceptions instead of Rust panics crossing JNI.Benchmarks
Fresh post-switch Fluss Nexmark q0 run, using the streaming/count-N path:
0.124s(808,251 ev/s)0.089s(1,129,921 ev/s)1.40xThis was Fluss-only q0 at
SF_ROWS=100000, best-of-2, with a release native build using--features mimalloc,fluss. I have not rerun the full Fluss matrix yet.Testing
Ran locally with Java 17 and the native
flussfeature built:mvn -Dnative.cargo.args="build --features fluss" -Dtest='io.github.jordepic.streamfusion.fluss.*Test' test13tests passingcargo check --manifest-path native/Cargo.toml --features fluss --keep-going