feat(inkless:control_plane): add dynamic diskless.control.plane.availability config - #759
Open
gqmelo wants to merge 3 commits into
Open
feat(inkless:control_plane): add dynamic diskless.control.plane.availability config#759gqmelo wants to merge 3 commits into
gqmelo wants to merge 3 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new dynamic cluster-wide broker config (diskless.control.plane.availability) that allows an external management plane to signal control plane availability, and uses that signal to proactively gate diskless operations (control-plane calls, produce/fetch hot paths, and periodic background tasks) to reduce timeouts and make failures immediately retriable.
Changes:
- Introduces
ControlPlaneAvailability+AvailabilityGatedControlPlane, and wires them into broker/controller startup and dynamic reconfiguration. - Gates diskless produce/fetch and skips periodic diskless background jobs when the control plane is reported unavailable.
- Adds metrics and documentation for control plane availability/gated-call counts, plus unit/integration tests for gating and dynamic updates.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| storage/inkless/src/test/java/io/aiven/inkless/produce/AppendHandlerTest.java | Updates produce handler tests for availability gating and new constructor signature. |
| storage/inkless/src/test/java/io/aiven/inkless/delete/FileCleanerIntegrationTest.java | Passes ControlPlaneAvailability into SharedState initialization for integration coverage. |
| storage/inkless/src/test/java/io/aiven/inkless/control_plane/ControlPlaneAvailabilityTest.java | New unit tests for availability state handling, config parsing, and listener behavior. |
| storage/inkless/src/test/java/io/aiven/inkless/control_plane/AvailabilityGatedControlPlaneTest.java | New unit tests for gating semantics and delegate lifecycle behavior. |
| storage/inkless/src/test/java/io/aiven/inkless/consume/FetchHandlerTest.java | Updates fetch handler tests for availability gating and retriable error behavior. |
| storage/inkless/src/test/java/io/aiven/inkless/common/SharedStateTest.java | Updates SharedState.initialize calls to include control plane availability. |
| storage/inkless/src/main/java/io/aiven/inkless/produce/AppendHandler.java | Gates diskless produce when control plane is reported unavailable. |
| storage/inkless/src/main/java/io/aiven/inkless/doc/MetricsDocs.java | Adds generated docs output for control plane availability metrics. |
| storage/inkless/src/main/java/io/aiven/inkless/control_plane/ControlPlaneAvailabilityMetrics.java | New Yammer/JMX metrics for reported availability and gated-call count. |
| storage/inkless/src/main/java/io/aiven/inkless/control_plane/ControlPlaneAvailability.java | New availability state holder with dynamic updates, metrics, and listener hook. |
| storage/inkless/src/main/java/io/aiven/inkless/control_plane/AvailabilityGatedControlPlane.java | New wrapper that rejects calls while unavailable and lazily manages delegate lifecycle. |
| storage/inkless/src/main/java/io/aiven/inkless/consume/FetchHandler.java | Gates diskless fetch when control plane is reported unavailable. |
| storage/inkless/src/main/java/io/aiven/inkless/common/SharedState.java | Threads ControlPlaneAvailability through shared state so handlers can gate consistently. |
| server-common/src/main/java/org/apache/kafka/server/config/ServerConfigs.java | Defines new config key, allowed values, default, and docs; marks it dynamically updatable. |
| docs/inkless/metrics.rst | Documents the new control plane availability metrics in Inkless docs. |
| core/src/test/scala/unit/kafka/server/ReplicaManagerTest.scala | Adds coverage for runIfControlPlaneAvailable gating helper. |
| core/src/test/scala/unit/kafka/server/DynamicConfigChangeTest.scala | Adds test ensuring dynamic updates propagate into ControlPlaneAvailability. |
| core/src/test/scala/unit/kafka/server/DynamicBrokerConfigTest.scala | Adds tests for dynamic-config startup catch-up and config validation/update mode. |
| core/src/main/scala/kafka/server/SharedServer.scala | Creates and wires availability + availability-gated control plane during SharedServer start. |
| core/src/main/scala/kafka/server/ReplicaManager.scala | Skips periodic diskless tasks when gated; passes availability to fetch handler. |
| core/src/main/scala/kafka/server/KafkaConfig.scala | Exposes disklessControlPlaneAvailability on KafkaConfig. |
| core/src/main/scala/kafka/server/DynamicBrokerConfig.scala | Registers dynamic reconfigurable to update availability; adds startup catch-up logic. |
| core/src/main/scala/kafka/server/BrokerServer.scala | Passes availability into SharedState.initialize. |
Suppressed comments (1)
storage/inkless/src/test/java/io/aiven/inkless/produce/AppendHandlerTest.java:201
- This test creates an
AppendHandlerbut does not close it, and it doesn't wait for the returned future. Closing via try-with-resources and awaiting the future makes the test more robust and avoids leaking any resources managed byAppendHandler.
@Test
void availableAppendDelegatesToWriter() {
final Writer writer = Mockito.mock(Writer.class);
Mockito.when(writer.write(Mockito.any(), Mockito.any(), Mockito.any()))
.thenReturn(CompletableFuture.completedFuture(Map.of()));
final AppendHandler appendHandler = new AppendHandler(
writer, topic -> new LogConfig(Map.of()), AVAILABLE);
appendHandler.handle(Map.of(T0P0, MemoryRecords.EMPTY), RequestLocal.noCaching());
Mockito.verify(writer).write(Mockito.any(), Mockito.any(), Mockito.any());
}
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
gqmelo
force-pushed
the
gqmelo/control-plane-availability
branch
2 times, most recently
from
August 19, 2026 13:08
6e2bd93 to
2f46c4f
Compare
…ability config This new config is intended to allow a management plane report the state of the control plane coordinator service. The config should be dynamicaly updated whenever the service becomes unavailable or available. Inkless can then use this state to avoid trying to connect to the control plane coordinator, reducing the noise in logs and metrics, and replying with retriable errors when appropriate. [KC-419]
gqmelo
force-pushed
the
gqmelo/control-plane-availability
branch
from
August 20, 2026 07:30
2f46c4f to
c410814
Compare
… reported unavailable ControlPlane.create() built and configured the real delegate (running migrations, opening Hikari pools) unconditionally at startup, before AvailabilityGatedControlPlane could gate anything. So a broker started with diskless.control.plane.availability=offline still tried to reach Postgres, and a delegate created while available kept its pool (and Hikari's background reconnect attempts) alive after going offline. AvailabilityGatedControlPlane now takes a delegate factory and creates the delegate lazily on first use while AVAILABLE, closing it via a new ControlPlaneAvailability.onChange listener as soon as availability leaves AVAILABLE. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> [KC-419]
…ntrol plane is unavailable FetchHandler had no pre-check for control-plane availability, so ControlPlaneException from FindBatchesJob fell through to the generic catch-all in FetchHandler.handle(), which logs an ERROR-level stack trace and returns UNKNOWN_SERVER_ERROR — not retriable, so clients don't retry. Mirror the existing AppendHandler pattern: check availability before touching the reader, and return KAFKA_STORAGE_ERROR (retriable, same code the produce path already uses) per partition with a WARN log. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> [KC-419]
gqmelo
force-pushed
the
gqmelo/control-plane-availability
branch
from
August 20, 2026 08:39
c410814 to
be219d1
Compare
gqmelo
marked this pull request as ready for review
August 20, 2026 09:55
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This new config is intended to allow a management plane report the state of the control plane coordinator service.
The config should be dynamicaly updated whenever the service becomes unavailable or available.
With that information, we then check for control plane availability before any control plane method, fetch requests and open/close the connection pool when the state changes.
KC-419