Fluss client settings audit¶
Audited against the released fluss-flink-1.18:1.0.0 and
fluss-flink-2.2:1.0.0 client/connector sources and the Apache Fluss checkout at
64b3b4611. StreamFusion admits only the released 1.0.0 implementation; the
checkout is reference material, not a runtime dependency. No Fluss source is
modified or forked.
Admission rule¶
The Arrow transport delegates connection configuration to the released Java client.
The following explicit settings are admitted: bootstrap.servers, client.id,
client.connect-timeout, client.request-timeout, netty.client.num-network-threads,
netty.client.allocator.heap-buffer-first, the released client.security.* options
listed below, and client.writer.dynamic-create-partition.enabled. Explicit heap
preference selects the copying Arrow decoder instead of overriding that preference.
Allowed netty.* table options are restored into the Java configuration because the
stock table factory drops them.
Other explicit settings retain the stock endpoint, including defaults, arbitrary filesystem settings and unknown keys. The source and sink are checked separately. Diagnostics identify a key without its value, including credentials. A fallback does not imply that stock Fluss accepts an invalid or arbitrary option.
FlinkTableFactory.toFlussClientConfig forwards all client.* table properties.
FlinkCatalog.getTable includes stored table properties and catalog security
properties in the resolved table options. Admission checks the resulting
flussConfig and resolved table options, then copies admitted connection settings to
the runtime configuration.
The factory drops netty.* table properties, so the raw table-options gate is
necessary even when the resulting SDK configuration contains only bootstrap
servers. Programmatically supplied network settings also decline acceleration.
Stock Fluss remains
responsible for validating a declined setting or rejecting an invalid combination.
A fallback is not a claim that stock Fluss accepts every arbitrary key.
The policy separates connection ownership from unverified data-plane policies. The audit adds registry-wide
regression coverage, precise diagnostics, a gate for factory-dropped settings, and a
missing table-statistics gate. It also replaces the Arrow writer's deterministic batch rotation with the released
StickyBucketAssigner, explicitly sends the default fetch read preference, and
acknowledges duplicate-sequence replies as already committed writes like the SDK.
Do not broaden the whitelist based solely on finding a config.get(...) call:
the full batching, routing, recovery and observability contract needs verification.
Complete released client/network inventory¶
Keys marked admitted delegate to the released connection or the verified partition creator.
Every other key causes planning-time fallback when explicitly present.
The notes describe the unconfigured default path and why forwarding the setting to
the Java connection alone does not establish support. The test enumerates the
installed released ConfigOptions registry, so newly exposed options cannot escape
coverage. The 46 options below are supplemented by filesystem and unknown-key tests.
| Setting | Default-path audit |
|---|---|
netty.client.num-network-threads |
Admitted. Java RPC transport owns its event loop. |
netty.client.allocator.heap-buffer-first |
Admitted. Explicit heap reception is respected and uses the copying Arrow decoder. |
client.id |
Admitted. Java connection creates its own client identity and RPC metrics group. |
client.connect-timeout |
Admitted. Java RPC transport owns connection establishment. |
client.writer.buffer.memory-size |
Acknowledgement queue applies the default byte ceiling, plus a 64-batch ceiling and task memory accounting. |
client.writer.buffer.page-size |
Arrow/wire allocations replace SDK segment-page allocation; no page allocator setting is reproduced. |
client.writer.buffer.per-request-memory-size |
Arrow/wire allocations replace SDK segment reservations. |
client.writer.buffer.wait-timeout |
Default unbounded buffer wait is retained; a finite allocation-wait timeout is not implemented. |
client.writer.batch-size |
Slices Arrow roots toward the default batch target. This is a batching target, not a per-row wire-size guarantee. |
client.writer.dynamic-batch-size.enabled |
SDK adaptive segment allocation is replaced by Arrow-root slicing and bounded coalescing; explicit allocation policy stays stock. |
client.writer.batch-timeout |
Sealed batches are scheduled immediately; StreamFusion does not reproduce a configured SDK linger schedule. |
client.writer.bucket.no-key-assigner |
Uses the released sticky assigner at sealed Arrow-batch boundaries, with current cluster metadata; per-row round robin is not supported. |
client.writer.acks |
Requests require all in-sync replicas (-1); zero/leader-only acknowledgement modes are not implemented. |
client.writer.request-max-size |
Encoded batches and coalesced records are bounded by the default request-record limit; oversized single records fail. |
client.writer.retries |
Default transient retries retain the same encoded batches and sequences; configurable retry combinations stay stock. |
client.writer.enable-idempotence |
Writer IDs and per-bucket batch sequences deduplicate retries within a writer lifetime. Explicit enable/disable and conflicting-option validation stay stock. |
client.writer.max-inflight-requests-per-bucket |
One request per bucket is in flight, within the SDK default ceiling of five. Configurable concurrency stays stock. |
client.writer.dynamic-create-partition.enabled |
Admitted. The released dynamic partition creator handles enabled/disabled creation and auto-partition validation. |
client.writer.kv-backpressure.max-throttle |
KV writes remain stock; the Arrow sink is append-only. |
client.request-timeout |
Admitted. Java RPC transport and append requests use the SDK default timeout. Request timeout is forwarded to the connection and append RPC; writer retry policy remains outside admission. |
client.scanner.log.check-crc |
Complete unprojected batches are CRC-checked. Broker-projected replies skip CRC like the SDK, whose projection invalidates the original checksum. |
client.scanner.log.max-poll-records |
The reader emits one Arrow batch at a time, rather than a row polling API; it does not promise configurable row poll granularity. |
client.security.protocol |
Admitted. Authentication/handshake remain on the released Java transport; broker tests cover SASL/PLAIN with credentials and heap/direct reception. |
client.security.enable-plugin-discovery |
Admitted. Authentication/handshake remain on the released Java transport; broker tests cover SASL/PLAIN with credentials and heap/direct reception. |
client.scanner.log.fetch.max-bytes |
FetchLog sends the default total byte limit. |
client.scanner.log.fetch.max-bytes-for-bucket |
FetchLog sends the default per-bucket byte limit. |
client.scanner.log.fetch.wait-max-time |
FetchLog sends the default broker wait limit. |
client.scanner.log.fetch.min-bytes |
FetchLog sends the default minimum byte threshold. |
client.scanner.kv.fetch.max-bytes |
Snapshot/KV scans remain stock. |
client.scanner.kv.batch-strategy |
Snapshot/KV scans remain stock. |
client.lookup.queue-size |
Lookup joins remain stock; the scan substitution does not replace a lookup provider. |
client.lookup.max-batch-size |
Lookup joins remain stock; the scan substitution does not replace a lookup provider. |
client.lookup.max-inflight-requests |
Lookup joins remain stock; the scan substitution does not replace a lookup provider. |
client.lookup.batch-timeout |
Lookup joins remain stock; the scan substitution does not replace a lookup provider. |
client.lookup.max-retries |
Lookup joins remain stock; the scan substitution does not replace a lookup provider. |
client.scanner.remote-log.prefetch-num |
Uses the released downloader, requesting segments sequentially, within its default prefetch ceiling. |
client.scanner.log.read-preference |
FetchLog explicitly sends the default LOCAL_FIRST preference; alternative tier preferences stay stock. |
client.scanner.io.tmpdir |
Released remote downloader owns its default temporary files. |
client.remote-file.download-thread-num |
Released connection owns the remote file downloader. |
client.filesystem.security.token.renewal.backoff |
Released connection owns the security token manager; configured credentials/renewal policy stays stock. |
client.filesystem.security.token.renewal.time-ratio |
Released connection owns the security token manager; configured credentials/renewal policy stays stock. |
client.metrics.enabled |
Default is false. Native queues/Arrow decoding do not reproduce every SDK scanner/writer metric; enabled SDK metrics stay stock. |
client.security.sasl.mechanism |
Admitted. Authentication/handshake remain on the released Java transport; broker tests cover SASL/PLAIN with credentials and heap/direct reception. |
client.security.sasl.jaas.config |
Admitted. Authentication/handshake remain on the released Java transport; broker tests cover SASL/PLAIN with credentials and heap/direct reception. |
client.security.sasl.username |
Admitted. Authentication/handshake remain on the released Java transport; broker tests cover SASL/PLAIN with credentials and heap/direct reception. |
client.security.sasl.password |
Admitted. Authentication/handshake remain on the released Java transport; broker tests cover SASL/PLAIN with credentials and heap/direct reception. |
The newer Fluss checkout additionally defines
client.scanner.remote-log.fetch.max-retries. The 1.0.0 transport is not upgraded
implicitly: this key is also rejected by the blanket explicit-entry rule, and a
newer connector implementation version is declined altogether.
Connector, table and planner contracts¶
| Configuration or ability | Disposition |
|---|---|
bootstrap.servers |
Forwarded unchanged; multiple bootstrap addresses remain supported. |
scan.startup.mode, scan.startup.timestamp |
Uses the factory's parsed startup options and SDK offsets initializers, including the configured SQL timezone. EARLIEST/LATEST/TIMESTAMP log reads are admitted; FULL is earliest for append tables. FULL primary-key snapshots fall back. |
scan.bounded.mode, scan.bounded.timestamp |
Uses the released stopping-offset initializer, boundedness and enumerator. Snapshot/hybrid combinations stay stock. |
scan.partition.discovery.interval |
Forwarded to the SDK enumerator. Native readers handle the released partition-removal event and acknowledge unsubscribed buckets. |
scan.split.assignment.batch-size |
Forwarded to the SDK enumerator, which pushes all assignment batches eagerly. |
scan.kv.snapshot.lease.id, scan.kv.snapshot.lease.duration |
SDK lease context is retained by the delegate. Snapshot reads remain stock; there is no native KV scan. |
lookup.async, lookup.insert-if-not-exists, Flink lookup.* cache/async settings |
Lookup nodes are never substituted by the Arrow scan rule. |
sink.ignore-delete |
Enabled mode falls back; the Arrow sink admits only insert-only input. |
sink.producer-id |
Explicit identity falls back; undo recovery is not implemented. |
sink.distribution-mode, deprecated sink.bucket-shuffle |
The factory resolves these into DistributionMode. AUTO/NONE on append tables with scalar bucket keys or sticky routing are admitted; BUCKET/PARTITION_DYNAMIC stay stock. |
bucket.num |
Uses each partition's broker metadata count, including mixed counts after rescaling the default. |
bucket.key, primary keys, partition keys |
Scalar bucket keys use native compacted-key hashing and stable Arrow grouping. Complex bucket keys and primary-key sinks stay stock. Partitioned append sinks use actual per-partition bucket counts; primary-key log sources preserve change types. |
auto-increment.fields, table.auto-increment.cache-size |
Auto-increment is an upstream primary-key write contract, which remains stock. |
table.log.format |
Source requires resolved ARROW; sink requires an explicitly resolved ARROW table. INDEXED/COMPACTED_LOG stay stock. |
table.log.arrow.compression.type, table.log.arrow.compression.zstd.level |
NONE/LZ4_FRAME/ZSTD encoding uses the current broker table compression settings; existing interop tests cover all three. |
table.statistics.columns |
Native streaming writes emit V1 statistics. Arrow column scans find min/max indexes and null counts; the released SDK serializes only the extrema. Each bucket/size split recomputes its own statistics. Sources can decode statistics-bearing V1/V2 batches; batch-filter pushdown is sent to the broker with the full schema ID. |
table.replication.factor |
Broker owns replication; native appends require all in-sync replica acknowledgements. |
table.log.ttl, table.log.tiered.local-segments, table.log.local-ttl |
Broker owns retention/tiering; reads retain offsets/high-watermarks and use the released remote downloader when directed to tiered logs. No selective remote column range reads are implemented. |
table.kv.format, table.kv.format-version, table.kv.value-layout-version, table.kv.standby-replica.enabled, table.kv.ttl, table.kv.ttl.time-column |
KV storage and expiry remain broker-owned; primary-key writes and KV snapshots stay stock. Live log reads consume the resulting broker changelog. |
table.changelog.image, table.delete.behavior |
Broker owns changelog generation/delete behavior. Read sidecar preserves emitted kinds; FULL/WAL primary-key log parity is tested. |
table.merge-engine, table.merge-engine.versioned.ver-column |
Merge-engine sources and sinks fall back, including aggregation undo recovery. |
All table.auto-partition.* options |
Released enumerator/partition creator own discovery, expiry and validation; native readers handle removal and native writers resolve actual partition bucket counts. |
All table.datalake.* options |
Lake/hybrid sources and lake sinks stay stock. Catalog-side lake creation/tiering is not replaced. |
| Flink source projection | Physical top-level and zero-column projections are supported. Nested SQL field access runs natively on the containing struct; Fluss 1.0 does not prune individual nested fields on the wire. Evolved schemas use full batches with local nullable trailing-column handling. |
| Flink filter/limit/count pushdowns | Partition pruning and statistics-based streaming log batch filtering are supported, with residual predicates retained. Point lookup, limit and count pushdowns stay stock. |
| Flink watermark pushdowns/options | Shared ScanWatermarkSpec admits verified periodic expressions and idle timeouts. Source watermarks, alignment and on-event emit fall back. |
| Flink sink materialization, row modifications, target-column/constraint abilities | Shared constraint gate and sink ability gate retain the stock sink when host enforcement is needed. |
| Checkpoint/recovery | Source uses SDK split/enumerator serializers; positions advance after successful collection, including offset-only progress across skipped batches. Sink flush waits for acknowledgements; restart delivery is at-least-once, as for the stock append connector, not transactional exactly-once. |
Server-side table settings must be resolved through the normal Fluss catalog. The writer reads its statistics mapping and bucket keys from table metadata at startup, including statistics enabled after planning. Later schema/statistics/key configuration changes require a job restart. New partitions continue to resolve their own actual bucket counts, including runtime bucket-count changes.
Verification and limits¶
FlussTablesTest enumerates admitted and excluded released client/network settings for append sources,
primary-key log sources and append sinks, plus explicit defaults, unknown keys,
filesystem options, bootstrap lists and table statistics. FlussSqlTest executes
configured consumer/producer fallback and statistics-enabled native writes against
the released broker and checks both plans and output. FlussArrowClientTest verifies
one- and four-bucket sticky batches, partition removal/recovery, filtered offset progress,
SASL/PLAIN authentication, heap/direct reception, SDK-compatible bucket placement and broker
pruning of native-produced statistics under NONE/LZ4/ZSTD compression.
Partitioned SQL tests cover mixed bucket counts, live partition discovery and projected
primary-key changelogs. The Arrow splitter tests composite names, stable row order,
timestamps and null-key rejection. These tests
and FlussProduceResponseTest's duplicate acknowledgement/identity/fatal-error regressions
are included in the existing Java and Fluss SQL CI jobs on both supported Flink lines.
The optimization intentionally changes physical allocation, column-batch scheduling, connection sharing and network teardown; it does not promise identical internal SDK page allocation, row poll boundaries or linger behavior. Explicit settings for those policies remain stock. Passing SQL parity and this inventory do not prove arbitrary failure scenarios or future SDK compatibility. Expand supported settings only with tests of their observable contract, including failure/recovery behavior. The published Nexmark numbers predate this audit; this change does not re-label or replace those measurements.