Skip to content

[kafka] Implement Metadata API over Fluss table metadata - #4261

Open
gyang94 wants to merge 22 commits into
apache:mainfrom
gyang94:codex/kafka-metadata-api
Open

gyang94 wants to merge 22 commits into
apache:mainfrom
gyang94:codex/kafka-metadata-api

Conversation

@gyang94

@gyang94 gyang94 commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

Closes #4266. Part of #4185.

Expose pre-created, Kafka-enabled Fluss tables through Metadata v0-v11. Clients can address a table by its canonical database.table name or its configured default-database alias, cache both names together, and detect table recreation. Missing databases and hidden tables do not suppress brokers or other valid topics.

This is PR04, based on PR03 DDL table mapping (#4277 / #4275), following PR02 ApiVersions (#4260 / #4265) and PR01 (#4259 / #4264).

Brief change log

  • Implement and advertise Metadata v0-v11 through a narrow backend contract and a local TabletServer gateway adapter. Reject Metadata v12 before invoking the gateway and ID-only lookup in v10/v11.
  • Resolve canonical names and aliases using the configured default database (fluss by default). Named responses retain requested names; all-topic discovery lists canonical names only. Missing aliases never fall back to another database.
  • Reuse PR03's public schema contract and persisted table.kafka.enabled opt-in. Disabled, missing and authorization-filtered tables return UNKNOWN_TOPIC_OR_PARTITION without exposing an ID. Enabled tables with invalid contracts return INVALID_TOPIC_EXCEPTION. Persisted enablement changes remain visible without a stale schema cache.
  • Give aliases stable wire UUIDs in a separate namespace derived from the same native Fluss Table ID. This supports Kafka client caches containing both names and recreation with a lower leader epoch. Both names retain the same table, buckets, leaders and native authorization identity.
  • Preserve brokers, aliases and valid topics across missing-database or deletion races, including synchronous and asynchronous gateway failures. Propagate unrelated failures.
  • Map partitions, leaders, replicas, authoritative ISR and offline replicas using the Kafka listener. Use a conservative available-leader ISR fallback only when bucket epoch is absent.
  • Pass one RpcGatewayService through the plugin and request handler. The backend checks that it implements TabletServerGateway and casts it internally, ensuring both typed references refer to the same service.
  • Consolidate overlapping Metadata tests while preserving version coverage, alias/canonical identity, real Kafka cache updates, authorization filtering, missing-database retries and real listener behavior.
  • Keep the snapshot-lease restart regression fix: wait for server metadata to converge after each coordinator restart while leaving the client cache stale to exercise refresh and retry.

The latest PR03 creates a configured custom Kafka default database at coordinator startup when Kafka is enabled. The native fluss database retains its cluster-initialization behavior. Metadata requests themselves create neither databases nor tables and do not recreate a deleted default database; the integration test now reflects this distinction.

Increment relative to PR03: 14 files changed, 2465 insertions(+), 19 deletions(-). DDL validation and startup database creation remain in PR03.

Tests

Validated the tree committed as ecbb368832efd3d5f542880c190e419f3ad5604b with Java 11:

mvn -o -pl fluss-kafka,fluss-client -am clean verify \
  '-Dtest=Kafka*Test,Kafka*ITCase,ApiVersionsHandlerTest,RetryableGatewayClientProxyTest,TableChangeWatcherTest,FlussAdminITCase#testKvSnapshotLease*' \
  -Dsurefire.failIfNoSpecifiedTests=false
  • All 158 distinct selected cases passed with zero failures, errors or skips: 112 Kafka, 28 public schema-contract, 6 RPC retry, 5 default-database, 5 table-change watcher and 2 snapshot-lease cases. Both Maven test phases passed; counts do not double-count them.
  • Kafka coverage includes 31 Metadata handler cases, 22 mapper cases, 5 real Metadata integration cases and 12 table-mapping integration cases.
  • Both snapshot-lease cases passed, including the previously failing testKvSnapshotLeaseAfterCoordinatorServerRestart.
  • All Fluss SNAPSHOT test dependencies came from this worktree's clean reactor build. Spotless, Checkstyle, RAT and git diff --check passed.

Real Kafka Metadata cache tests cover v10/v11 full and partial updates with canonical names and aliases together, plus delete/recreate with leader epoch dropping from 5 to 0. Listener tests exercise Metadata v0-v11, default/custom aliases, startup-created and deleted default databases, persisted enablement changes, invalid enabled contracts and canonical-only discovery. The optional three-field _kafka_metadata contract is covered through named and discovery paths; the legacy fourth offset field is rejected.

The full repository and full Admin suites, Flink SQL runtime and actual Producer writes were not run. The earlier Java 11/core CI failure in RebalanceITCase.testRebalanceForLogTable is outside the Metadata increment and is not fixed or covered by this validation.

API and Format

Uses existing Fluss RPC and storage formats. The optional _kafka_metadata column follows PR03: timestamp TIMESTAMP_LTZ(3), timestamp_type INT and partition INT. Both Kafka UUID namespaces decode to the same native Fluss Table ID.

CreateTopics/DeleteTopics, automatic table creation, Metadata v12+, Produce and record conversion are outside this PR. No PR07 implementation or tests are included. Authentication/session propagation and service-disabled protocol semantics remain in later PR16/19 and PR20 respectively.

Documentation and review

Supported versions, naming, discovery, identity and errors are documented here, in Javadoc and in regression tests.

The exact PR03 baseline is 7bcda8b4a17282b9e956137ea31ae281cbf5795b. Review Metadata alone using the incremental comparison. This PR targets Apache main, so Files changed also contains unmerged prerequisites. Revalidate the stack after prerequisites merge.

Generative AI disclosure: Codex assisted with implementation, testing and commit organization. Human review is required before merge.

gyang94 and others added 12 commits October 14, 2026 13:45
Route requests through the dispatcher and advertise only implemented APIs.
Return version-aware errors for unsupported APIs and invalid requests.

Validated with mvn -o -pl fluss-kafka verify (23 unit tests and 1 IT).

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 313/313
AI-Contributed/UT: 137/137
Exercise future-version decoding, v0 error serialization, correlation IDs,
unknown tagged fields, buffer release, and renegotiation on one connection.
Verify registry-defined ranges, hidden APIs, ordering, and invalid client
software fields across the supported ApiVersions schemas.

Validated with Java 11 reactor clean verify: 37 unit tests and 2 integration
tests passed, with Checkstyle, Spotless, RAT, and git diff checks.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 0/0
AI-Contributed/UT: 238/238
Construct the registry once with all handlers and defer ApiVersions registry
access until request handling. Advertised capabilities and dispatch continue
to share the same immutable registry without a separate capability list.
Update coverage to verify lazy access and handler identity across versions.

Validated with Java 11 reactor clean verify: 44 unit and 2 integration cases
passed in both Maven test executions, including inherited error-mapping and
idle regressions. Kafka main and test sources also compile with --release 8.
Spotless, Checkstyle, RAT, and diff checks passed.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 28/28
AI-Contributed/UT: 33/33
Use the dispatcher-backed handler constructor in the fallback test added by
PR01. Preserve its unsupported-version, listener, response, and buffer checks.

Validated with Java 11 reactor clean verify: 39 unit and 2 integration cases
passed in both Maven test executions. Kafka main and test sources compile
with --release 8; Spotless, Checkstyle, RAT, and diff checks passed.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 0/0
AI-Contributed/UT: 3/3
Check the deferred registry before reading advertised capabilities so an
initialization-order failure reports an explicit diagnostic message.

Validated with Java 11 reactor tests: 16 ApiVersions and request-handler
cases passed, along with Spotless, Checkstyle, RAT, and diff checks.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 4/4
AI-Contributed/UT: 0/0
Extract topic identity and the raw/string table mapping contract before Metadata. Validate table kinds, field projections and metadata columns independently of request handling and record decoding.

Validation: Java 11, mvn -o -pl fluss-kafka clean verify (47 unit tests and 2 integration tests); Checkstyle, Spotless and RAT passed.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 769/769
AI-Contributed/UT: 480/480
Resolve database.table topic names directly to Fluss table paths and return
qualified names for metadata. Validate name boundaries and cover same-named
tables in different databases through native metadata round trips.

Read projected field names directly from DataField to avoid rebuilding the
complete field-name list for every projected column.

Validated on Java 11: 67 Kafka unit tests and 2 integration tests passed,
along with Checkstyle, Spotless, RAT, and git diff --check.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 52/52
AI-Contributed/UT: 167/167
Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 16/16
AI-Contributed/UT: 33/33
Wait for the newly created log table to become ready before acquiring or
releasing snapshot leases. This prevents the coordinator's asynchronous
table-ID registration from masking the expected NonPrimaryKeyTableException.

Validated on Java 11 with the same-worktree reactor:
FlussAdminITCase#testKvSnapshotLeaseForLogTable passed, along with
Checkstyle, Spotless, RAT, and git diff --check.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 0/0
AI-Contributed/UT: 1/1
Register table.kafka options and validate the declared fixed-column mapping
through a shared schema contract. Support binary, string and flat/nested JSON
values with optional key, headers and rescue columns.

Validate CREATE and ALTER before persistence, and fence schema publication
with the table version and coordinator epoch so concurrent schema and
property changes cannot bypass the contract. Resolve bare topic aliases
through kafka.default.database and stop automatically creating that database.

Keep real offset persistence deferred and reject Kafka enablement for tables
that declare offset metadata until that capability is available.

Validation: 146 targeted tests passed on Java 11; Checkstyle, Spotless, RAT
and git diff checks passed.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 1131/1131
AI-Contributed/UT: 1451/1451
Default bare topic names to the native fluss database while preserving
explicit database overrides, canonical names and no automatic Kafka database
creation.

Validate JSON business types recursively before CREATE, ALTER and enablement.
Reject non-STRING map keys at every nesting level and schemas deeper than the
supported limit. Expose the validation entry point and depth constant for
subsequent decoders. Count business fields equally in flat and nested layouts,
without charging a level for the physical _kafka_value ROW container.

Keep disabled tables outside Kafka validation and preserve user schemas and
explicit properties. Cover complex scalar/container types, depth boundaries,
failed DDL state preservation and successful enablement with real RPC tests.

Validation: Java 11 clean reactor verify passed 161 targeted cases, including
snapshot lease and concurrent ALTER regressions. Checkstyle, Spotless, RAT and
git diff checks passed. The five prior PR03 commits were rebased onto PR02
97d20b1 and checked with range-diff.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 92/92
AI-Contributed/UT: 292/292
Allow optional _kafka_metadata with timestamp, timestamp_type and partition,
without a physical offset field. Cover optional fixed-column combinations,
metadata validation and CREATE/ALTER behavior.

Ignore unchanged table registrations when schema ALTER advances the ZK
version. Preserve atomic concurrency fencing and notifications for real
property and bucket changes, with deterministic regression coverage.

Validation: Java 11 reactor verify passed 111 targeted test cases;
Checkstyle, Spotless and git diff --check passed.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 57/57
AI-Contributed/UT: 265/265
@gyang94
gyang94 force-pushed the codex/kafka-metadata-api branch from d65c1fc to de1d43e Compare October 14, 2026 06:50
@gyang94
gyang94 marked this pull request as ready for review October 14, 2026 07:07
gyang94 and others added 5 commits October 14, 2026 17:17
Create the configured Kafka default database when missing and preserve existing
metadata. Fence schema and property ALTER with schema-parent version checks
without rewriting table registrations, restoring the original table watcher.

Remove redundant configuration, Flink conversion and mapping test coverage while
retaining DDL validation, optional system columns and concurrent ALTER checks.

Validation: targeted clean verify passed 173 tests with Checkstyle and Spotless.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 120/120
AI-Contributed/UT: 683/683
Reuse native initialization for the fluss database and create a custom
Kafka default database only when it is missing.

Remove PR03-only schema version and Coordinator epoch checks, preserving
PR02 metadata writes and existing protections. Drop the corresponding
concurrency tests while retaining Kafka DDL mapping validation.

Validation: 121 focused tests passed; Maven verify checks passed.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 132/132
AI-Contributed/UT: 224/224
Integrate the DDL mapping prerequisite and use its resolver for Metadata discovery. Omit unsupported tables from all-topic queries and return per-topic mapping errors for named queries. Preserve metadata for compatible tables in mixed requests.

Validation: Java 11, mvn -o -pl fluss-kafka clean verify (62 unit tests and 2 integration tests); Checkstyle, Spotless and RAT passed.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 742/742
AI-Contributed/UT: 571/571
Route Metadata queries through the database.table mapping from PR03 and
enumerate compatible topics across databases. Preserve brokers and valid
topics when a requested database is absent or disappears during discovery;
propagate other gateway failures.

Cover qualified names, same-named tables across databases, synchronous and
asynchronous lookup failures, and Metadata v0-v11 over a real listener.

Validated on Java 11: 90 unit tests and 4 integration tests passed, along
with Checkstyle, Spotless, RAT, and git diff --check. Five additional
interleaved asynchronous review probes passed.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 129/129
AI-Contributed/UT: 514/514
Keep the ApiVersions wire fallback assertion limited to its retry range,
while successful negotiation verifies both registered API ranges.

Cover Metadata v0-v11 handling of native gateway visibility filtering in
named queries, all-topic discovery, and missing-database retries. Verify
Metadata v12 is rejected before invoking the gateway.

Retain the existing qualified-topic discovery contract on prerequisite
c508de6. New Core-dependent aliases and
persisted table enablement remain deferred.

Validation: Java 11 reactor verify passed 105 unit tests and 5 integration
tests, with Spotless, Checkstyle, RAT, and git diff --check.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 0/0
AI-Contributed/UT: 71/71
gyang94 and others added 5 commits October 14, 2026 20:12
Wait for all server gateways to advertise the restarted coordinator before
acquire, release and drop lease checks. Assert that the client still holds
its cached address so each operation exercises metadata refresh and retry.

Rebased PR04 onto PR03 at 86d2735.
Validation: restart case passed in the full Admin suite and focused rerun;
Kafka 110 tests, RPC retry 6 tests, Spotless and Checkstyle passed. The full
Admin suite passed 46/47; the unchanged rolling-upgrade health test first
observed RED instead of GREEN and passed the subsequent focused rerun.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 0/0
AI-Contributed/UT: 11/11
Use the actual server default database and the PR03 shared mapper/schema
contract. Resolve aliases by TablePath, preserve requested names, and retain
valid aliases when a missing database triggers metadata discovery retry.

Expose only tables with persisted table.kafka.enabled. Return unknown-topic
for disabled or missing tables and invalid-topic for damaged enabled
contracts in named and all-topic requests. Discovery emits canonical names
without duplicate aliases and retains native authorization and routing.

Verify configuration injection, no fallback lookup or database creation,
enablement/reset changes, invalid historical contracts and v0-v11 behavior
through real Kafka listeners. Preserve the coordinator snapshot lease fix.

Validation: Java 11 clean reactor verify passed 160 distinct cases: 118 Kafka
(including 6 Metadata integration cases), 31 shared schema, 3 atomic DDL,
6 RPC retry and 2 snapshot lease cases. Spotless, Checkstyle and RAT passed.
The four existing PR04 commits were rebased unchanged onto PR03
4a9aa6b and checked with range-diff.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 155/155
AI-Contributed/UT: 571/571
Keep canonical topic IDs unchanged and encode alias wire IDs in a separate
namespace using the same Fluss table ID. Kafka clients can then cache both
names and detect table recreation even when the new leader epoch is lower.

Cover Kafka Metadata v10/v11 full and partial updates, recreation from epoch
5 to 0 without a missing-topic response, and native Metadata responses.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 31/31
AI-Contributed/UT: 135/135
Adapt the decoder regression to the configured request handler. Cover
optional three-field metadata columns and legacy offset rejection across
Metadata v0-v11, including native DDL and both real TabletServer listeners.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 0/0
AI-Contributed/UT: 109/109
Pass one RPC service through the request handler and validate its
TabletServerGateway capability inside the Metadata backend.

Consolidate overlapping Metadata tests while retaining protocol-version,
alias identity, client cache, authorization and discovery regressions.
Align the custom default database test with PR03 startup creation and
verify that Metadata does not recreate a deleted default database.

Co-Authored-By: Codex <noreply@openai.com>
AI-Model: gpt-6
AI-Contributed/Feature: 35/35
AI-Contributed/UT: 546/546
@gyang94
gyang94 force-pushed the codex/kafka-metadata-api branch from de1d43e to ecbb368 Compare October 14, 2026 12:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[kafka] Implement Metadata API for pre-created Fluss tables

1 participant