From 24bcdd0d28cca1c69a95e49e390a8fcf4a805e4e Mon Sep 17 00:00:00 2001 From: Shanzita Date: Tue, 18 Aug 2026 11:35:59 -0700 Subject: [PATCH 1/2] Add GRACEFUL_DISCONNECT event support (CEP-59) Adds the GRACEFUL_DISCONNECT event type and its codec, allowing clients to be notified in-band when a node begins draining connections for shutdown. The event has an empty body; the type string alone carries the signal. Part of CEP-59: Graceful Disconnect - In-Band Connection Draining for Node Shutdown. Driver-side handling: CASSJAVA-124. --- .../protocol/internal/ProtocolConstants.java | 1 + .../oss/protocol/internal/response/Event.java | 4 +- .../event/GracefulDisconnectEvent.java | 54 +++++++++++++++++ .../event/GracefulDisconnectEventTest.java | 60 +++++++++++++++++++ 4 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/datastax/oss/protocol/internal/response/event/GracefulDisconnectEvent.java create mode 100644 src/test/java/com/datastax/oss/protocol/internal/response/event/GracefulDisconnectEventTest.java diff --git a/src/main/java/com/datastax/oss/protocol/internal/ProtocolConstants.java b/src/main/java/com/datastax/oss/protocol/internal/ProtocolConstants.java index d6902e5..4151d97 100644 --- a/src/main/java/com/datastax/oss/protocol/internal/ProtocolConstants.java +++ b/src/main/java/com/datastax/oss/protocol/internal/ProtocolConstants.java @@ -148,6 +148,7 @@ public static class EventType { public static final String TOPOLOGY_CHANGE = "TOPOLOGY_CHANGE"; public static final String STATUS_CHANGE = "STATUS_CHANGE"; public static final String SCHEMA_CHANGE = "SCHEMA_CHANGE"; + public static final String GRACEFUL_DISCONNECT = "GRACEFUL_DISCONNECT"; } public static class SchemaChangeType { diff --git a/src/main/java/com/datastax/oss/protocol/internal/response/Event.java b/src/main/java/com/datastax/oss/protocol/internal/response/Event.java index 1e1c4e0..92ff1ff 100644 --- a/src/main/java/com/datastax/oss/protocol/internal/response/Event.java +++ b/src/main/java/com/datastax/oss/protocol/internal/response/Event.java @@ -20,6 +20,7 @@ import com.datastax.oss.protocol.internal.PrimitiveSizes; import com.datastax.oss.protocol.internal.ProtocolConstants; import com.datastax.oss.protocol.internal.ProtocolErrors; +import com.datastax.oss.protocol.internal.response.event.GracefulDisconnectEvent; import com.datastax.oss.protocol.internal.response.event.SchemaChangeEvent; import com.datastax.oss.protocol.internal.response.event.StatusChangeEvent; import com.datastax.oss.protocol.internal.response.event.TopologyChangeEvent; @@ -54,7 +55,8 @@ public Codec(int protocolVersion) { protocolVersion, new TopologyChangeEvent.SubCodec(protocolVersion), new StatusChangeEvent.SubCodec(protocolVersion), - new SchemaChangeEvent.SubCodec(protocolVersion)); + new SchemaChangeEvent.SubCodec(protocolVersion), + new GracefulDisconnectEvent.SubCodec(protocolVersion)); } @Override diff --git a/src/main/java/com/datastax/oss/protocol/internal/response/event/GracefulDisconnectEvent.java b/src/main/java/com/datastax/oss/protocol/internal/response/event/GracefulDisconnectEvent.java new file mode 100644 index 0000000..c2dc895 --- /dev/null +++ b/src/main/java/com/datastax/oss/protocol/internal/response/event/GracefulDisconnectEvent.java @@ -0,0 +1,54 @@ +/* + * Copyright DataStax, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.datastax.oss.protocol.internal.response.event; + +import com.datastax.oss.protocol.internal.Message; +import com.datastax.oss.protocol.internal.PrimitiveCodec; +import com.datastax.oss.protocol.internal.ProtocolConstants; +import com.datastax.oss.protocol.internal.response.Event; + +public class GracefulDisconnectEvent extends Event { + public GracefulDisconnectEvent() { + super(ProtocolConstants.EventType.GRACEFUL_DISCONNECT); + } + + @Override + public String toString() { + return "EVENT GRACEFUL_DISCONNECT"; + } + + public static class SubCodec extends Event.SubCodec { + + public SubCodec(int protocolVersion) { + super(ProtocolConstants.EventType.GRACEFUL_DISCONNECT, protocolVersion); + } + + @Override + public void encode(B dest, Message message, PrimitiveCodec encoder) { + // no-op: the event has no body, the type string is enough + } + + @Override + public int encodedSize(Message message) { + return 0; + } + + @Override + public Message decode(B source, PrimitiveCodec decoder) { + return new GracefulDisconnectEvent(); + } + } +} diff --git a/src/test/java/com/datastax/oss/protocol/internal/response/event/GracefulDisconnectEventTest.java b/src/test/java/com/datastax/oss/protocol/internal/response/event/GracefulDisconnectEventTest.java new file mode 100644 index 0000000..2620f94 --- /dev/null +++ b/src/test/java/com/datastax/oss/protocol/internal/response/event/GracefulDisconnectEventTest.java @@ -0,0 +1,60 @@ +/* + * Copyright DataStax, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.datastax.oss.protocol.internal.response.event; + +import static com.datastax.oss.protocol.internal.Assertions.assertThat; + +import com.datastax.oss.protocol.internal.Message; +import com.datastax.oss.protocol.internal.MessageTestBase; +import com.datastax.oss.protocol.internal.PrimitiveSizes; +import com.datastax.oss.protocol.internal.ProtocolConstants; +import com.datastax.oss.protocol.internal.TestDataProviders; +import com.datastax.oss.protocol.internal.binary.MockBinaryString; +import com.datastax.oss.protocol.internal.response.Event; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(DataProviderRunner.class) +public class GracefulDisconnectEventTest extends MessageTestBase { + + public GracefulDisconnectEventTest() { + super(GracefulDisconnectEvent.class); + } + + @Override + protected Message.Codec newCodec(int protocolVersion) { + return new Event.Codec(protocolVersion); + } + + @Test + @UseDataProvider(location = TestDataProviders.class, value = "protocolV3OrAbove") + public void should_encode_and_decode(int protocolVersion) { + GracefulDisconnectEvent initial = new GracefulDisconnectEvent(); + + MockBinaryString encoded = encode(initial, protocolVersion); + + assertThat(encoded) + .isEqualTo(new MockBinaryString().string(ProtocolConstants.EventType.GRACEFUL_DISCONNECT)); + assertThat(encodedSize(initial, protocolVersion)) + .isEqualTo(PrimitiveSizes.SHORT + ProtocolConstants.EventType.GRACEFUL_DISCONNECT.length()); + + GracefulDisconnectEvent decoded = decode(encoded, protocolVersion); + + assertThat(decoded.type).isEqualTo(ProtocolConstants.EventType.GRACEFUL_DISCONNECT); + } +} From 62d0dfc95ad9e5774500b9a8a7f8b76e92718fb0 Mon Sep 17 00:00:00 2001 From: Shanzita Date: Wed, 26 Aug 2026 10:49:57 -0500 Subject: [PATCH 2/2] Use protocolV5OrAbove data provider in GracefulDisconnectEventTest GRACEFUL_DISCONNECT is only supported from protocol v5, per review feedback. --- .../internal/response/event/GracefulDisconnectEventTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/datastax/oss/protocol/internal/response/event/GracefulDisconnectEventTest.java b/src/test/java/com/datastax/oss/protocol/internal/response/event/GracefulDisconnectEventTest.java index 2620f94..7ee7e5a 100644 --- a/src/test/java/com/datastax/oss/protocol/internal/response/event/GracefulDisconnectEventTest.java +++ b/src/test/java/com/datastax/oss/protocol/internal/response/event/GracefulDisconnectEventTest.java @@ -42,7 +42,7 @@ protected Message.Codec newCodec(int protocolVersion) { } @Test - @UseDataProvider(location = TestDataProviders.class, value = "protocolV3OrAbove") + @UseDataProvider(location = TestDataProviders.class, value = "protocolV5OrAbove") public void should_encode_and_decode(int protocolVersion) { GracefulDisconnectEvent initial = new GracefulDisconnectEvent();