Status

Current state: Under Discussion

Discussion thread: TBD

JIRA: KAFKA-18735 - Getting issue details... STATUS

Please keep the discussion on the mailing list rather than commenting on the wiki (wiki discussions get unwieldy fast).

Motivation

ClientQuotaEntity.ConfigEntity#name() returns the placeholder string "<default>" for default quota entities. This is problematic on three counts:

  1. Inconsistent with every other Kafka public API. Across Kafka — Admin client, KRaft records — a default client-quota entity is represented by null, not by a placeholder string. ConfigEntity#name() is the only public surface still returning "<default>", which KAFKA-16411 - Getting issue details... STATUS already designated as a ZooKeeper-internal detail.
  2. Opaque origin. "<default>" is a ZooKeeper-era artifact (znode paths like /config/users/<default>) with no semantic meaning in KRaft-only Kafka.
  3. Javadoc and implementation disagree. The Javadoc claims name() returns "an empty string" for default entities; the implementation has always returned "<default>".

This KIP adds Optional<String> entityName(), which expresses "absent value" in the type system instead of overloading a string literal. The legacy name() is deprecated for removal in the next major release.

Public Interfaces

A new abstract method is added to org.apache.kafka.server.quota.ClientQuotaEntity.ConfigEntity; name() is deprecated for removal in the next major release. (The <release> placeholder below is the release in which this KIP ships.)

/**
 * Returns the name of this entity, or the literal {@code "<default>"} for default quotas.
 *
 * @deprecated Since <release>. Use {@link #entityName()} instead.
 */
@Deprecated(since = "<release>", forRemoval = true)
String name();

/**
 * Returns the name of this entity, or {@link Optional#empty()} for default quotas.
 */
Optional<String> entityName();

ClientQuotaCallback implementations only consume ConfigEntity instances handed in by the broker, so the new abstract method does not affect them at compile time.

The Javadoc for name() is also corrected to document the actual "<default>" return value instead of the previously-claimed "empty string".

Proposed Changes

  • Broker-internal ConfigEntity implementations override entityName(): Optional.empty() for default singletons (DEFAULT_USER_ENTITY, DEFAULT_USER_CLIENT_ID), Optional.of(name) for explicit user/client-id entities.
  • Broker-internal callers migrate from name() to entityName().

Compatibility, Deprecation, and Migration Plan

Upon shipping: Zero runtime break. Calls to name() emit a deprecation warning but continue to return "<default>" for default entities.

Next major release: name() is removed. ClientQuotaCallback implementations that call name() will fail to compile and must migrate to entityName().

Test Plan

Unit tests.

Rejected Alternatives

1. Keep "<default>" and just update the Javadoc to match

This documents the bug instead of fixing it. KAFKA-16411 - Getting issue details... STATUS already designated "<default>" as a ZooKeeper-internal detail and aligned the rest of Kafka on null-for-default; recording the placeholder in the Javadoc would lock the callback interface into the very inconsistency the project has been removing elsewhere.

2. Directly change name() to return null for default entities (no new method, no deprecation cycle)

Returning null without a deprecation cycle silently breaks callers: name().equals(...) and similar dereferences throw NullPointerException, and string-formatted uses (logging, metric tags) emit the literal "null" and corrupt dashboards. The deprecation route preserves runtime behavior and lets callbacks migrate to the type-safe Optional<String> API at their own pace.

  • No labels