-
Notifications
You must be signed in to change notification settings - Fork 891
CASSJAVA-124: Add GRACEFUL_DISCONNECT support (CEP-59) #2091
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Changes from all commits
a226207
45c5f95
8c5139e
0a95963
1de60ae
3927a33
32fcb1b
85e7c25
442561d
23835de
618a7f8
c146d19
402d1bf
6de6523
4885827
6b9ac8f
3234760
2ae468b
86d0fad
9e1437e
ef912d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -78,7 +78,7 @@ | |
| <dependency> | ||
| <groupId>com.datastax.oss</groupId> | ||
| <artifactId>native-protocol</artifactId> | ||
| <version>1.5.2</version> | ||
| <version>1.5.3-SNAPSHOT</version> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to remember to change it to 1.5.3 after the release of the native protocol
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed — I'll bump this to 1.5.3 as soon as native-protocol releases (tracking it in my native-protocol PR, datastax/native-protocol#61). Related finding while fixing CI: the build had never actually resolved this snapshot — ci/run-tests.sh wasn't running install-snapshots.sh at all, so every CI run failed at dependency resolution. That's fixed now (402d1bf, 4885827, 6b9ac8f) and CI installs the snapshot from the PR #61 branch. One heads-up: I initially pointed it at your fork's cep-59 branch (which the PR description referenced), but that copy has Frame.forResponse stubbed out with UnsupportedOperationException, which failed the graph unit tests — you may want to update or remove that branch so nothing else picks it up.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't worry about CI or
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reverted the CI changes in 3234760. |
||
| </dependency> | ||
| </dependencies> | ||
| </dependencyManagement> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,6 +51,7 @@ public enum DefaultNodeMetric implements NodeMetric { | |
| SPECULATIVE_EXECUTIONS("speculative-executions"), | ||
| CONNECTION_INIT_ERRORS("errors.connection.init"), | ||
| AUTHENTICATION_ERRORS("errors.connection.auth"), | ||
| GRACEFUL_DISCONNECTS("pool.graceful-disconnects"), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done; the counter is now initialized in all three backends (DropwizardNodeMetricUpdater, MicrometerNodeMetricUpdater, MicroProfileNodeMetricUpdater) in 618a7f8, and incremented when a GRACEFUL_DISCONNECT event is received on one of the node's pooled connections (ChannelPool query-connection callback, 442561d). It's documented in reference.conf, covered by the zero-value assertions in the three metrics ITs and by ChannelPoolGracefulDisconnectTest, and the new GracefulDisconnectIT exercises the session-level counter end to end against a real drain. I also verified both counters increment during manual drain runs on 2- and 3-node ccm clusters. |
||
| ; | ||
|
|
||
| private static final Map<String, DefaultNodeMetric> BY_PATH = sortByPath(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,6 +32,7 @@ public enum DefaultSessionMetric implements SessionMetric { | |
| THROTTLING_QUEUE_SIZE("throttling.queue-size"), | ||
| THROTTLING_ERRORS("throttling.errors"), | ||
| CQL_PREPARED_CACHE_SIZE("cql-prepared-cache-size"), | ||
| GRACEFUL_DISCONNECTS("graceful-disconnects"), | ||
|
Shanzita marked this conversation as resolved.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need integration tests and manual testing for metrics
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and the actual implementation of incrementing the metric
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All three parts are done now:
|
||
| ; | ||
|
|
||
| private static final Map<String, DefaultSessionMetric> BY_PATH = sortByPath(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,13 +26,17 @@ | |
| import com.datastax.oss.driver.api.core.loadbalancing.NodeDistance; | ||
| import com.datastax.oss.driver.api.core.metadata.Node; | ||
| import com.datastax.oss.driver.api.core.metadata.NodeState; | ||
| import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; | ||
| import com.datastax.oss.driver.api.core.metrics.DefaultSessionMetric; | ||
| import com.datastax.oss.driver.internal.core.channel.ChannelEvent; | ||
| import com.datastax.oss.driver.internal.core.channel.DriverChannel; | ||
| import com.datastax.oss.driver.internal.core.channel.DriverChannelOptions; | ||
| import com.datastax.oss.driver.internal.core.channel.EventCallback; | ||
| import com.datastax.oss.driver.internal.core.context.InternalDriverContext; | ||
| import com.datastax.oss.driver.internal.core.metadata.DefaultNode; | ||
| import com.datastax.oss.driver.internal.core.metadata.DefaultTopologyMonitor; | ||
| import com.datastax.oss.driver.internal.core.metadata.DistanceEvent; | ||
| import com.datastax.oss.driver.internal.core.metadata.GracefulDisconnectEvent; | ||
| import com.datastax.oss.driver.internal.core.metadata.MetadataManager; | ||
| import com.datastax.oss.driver.internal.core.metadata.NodeStateEvent; | ||
| import com.datastax.oss.driver.internal.core.metadata.TopologyEvent; | ||
|
|
@@ -190,6 +194,9 @@ public void onEvent(Message eventMessage) { | |
| case ProtocolConstants.EventType.SCHEMA_CHANGE: | ||
| processSchemaChange(event); | ||
| break; | ||
| case ProtocolConstants.EventType.GRACEFUL_DISCONNECT: | ||
| processGracefulDisconnect(); | ||
| break; | ||
| default: | ||
| LOG.warn("[{}] Unsupported event type: {}", logPrefix, event.type); | ||
| } | ||
|
|
@@ -242,6 +249,34 @@ private void processSchemaChange(Event event) { | |
| }); | ||
| } | ||
|
|
||
| private void processGracefulDisconnect() { | ||
| LOG.info( | ||
| "[{}] Received GRACEFUL_DISCONNECT event on control connection, " | ||
| + "the server is shutting down gracefully", | ||
| logPrefix); | ||
| context | ||
| .getMetricsFactory() | ||
| .getSessionUpdater() | ||
| .incrementCounter(DefaultSessionMetric.GRACEFUL_DISCONNECTS, null); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not increment DefaultNodeMetric.GRACEFUL_DISCONNECTS?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch, added in 86d0fad along with a unit test asserting both counters increment. |
||
| // Fire an internal event to notify other components (particularly the ChannelPool) | ||
| DriverChannel currentChannel = channel; | ||
| if (currentChannel != null) { | ||
| context | ||
| .getMetadataManager() | ||
| .getMetadata() | ||
| .findNode(currentChannel.getEndPoint()) | ||
| .ifPresent( | ||
| node -> { | ||
| if (node instanceof DefaultNode) { | ||
| ((DefaultNode) node) | ||
| .getMetricUpdater() | ||
| .incrementCounter(DefaultNodeMetric.GRACEFUL_DISCONNECTS, null); | ||
| } | ||
| context.getEventBus().fire(new GracefulDisconnectEvent(node)); | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| private class SingleThreaded { | ||
| private final InternalDriverContext context; | ||
| private final DriverConfig config; | ||
|
|
@@ -292,7 +327,13 @@ private void init( | |
| } | ||
| initWasCalled = true; | ||
| try { | ||
| ImmutableList<String> eventTypes = buildEventTypes(listenToClusterEvents); | ||
| boolean gracefulDisconnectEnabled = | ||
| context | ||
| .getConfig() | ||
| .getDefaultProfile() | ||
| .getBoolean(DefaultDriverOption.GRACEFUL_DISCONNECT_ENABLED, true); | ||
| ImmutableList<String> eventTypes = | ||
| buildEventTypes(listenToClusterEvents, gracefulDisconnectEnabled); | ||
| LOG.debug("[{}] Initializing with event types {}", logPrefix, eventTypes); | ||
| channelOptions = | ||
| DriverChannelOptions.builder() | ||
|
|
@@ -606,14 +647,18 @@ private boolean isAuthFailure(Throwable error) { | |
| return true; | ||
| } | ||
|
|
||
| private static ImmutableList<String> buildEventTypes(boolean listenClusterEvents) { | ||
| private static ImmutableList<String> buildEventTypes( | ||
| boolean listenClusterEvents, boolean gracefulDisconnectEnabled) { | ||
| ImmutableList.Builder<String> builder = ImmutableList.builder(); | ||
| builder.add(ProtocolConstants.EventType.SCHEMA_CHANGE); | ||
| if (listenClusterEvents) { | ||
| builder | ||
| .add(ProtocolConstants.EventType.STATUS_CHANGE) | ||
| .add(ProtocolConstants.EventType.TOPOLOGY_CHANGE); | ||
| } | ||
| if (gracefulDisconnectEnabled) { | ||
| builder.add(ProtocolConstants.EventType.GRACEFUL_DISCONNECT); | ||
| } | ||
| return builder.build(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you 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.driver.internal.core.metadata; | ||
|
|
||
| import com.datastax.oss.driver.api.core.metadata.Node; | ||
| import java.util.Objects; | ||
| import net.jcip.annotations.Immutable; | ||
|
|
||
| /** | ||
| * Indicates that a node announced a graceful shutdown (CEP-59): a {@code GRACEFUL_DISCONNECT} | ||
| * protocol event was received on one of its connections. | ||
| */ | ||
| @Immutable | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pls refer to
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in 86d0fad: the class now lives in internal.core.metadata, EVENT_TYPE is removed, and all usages go through ProtocolConstants.EventType.GRACEFUL_DISCONNECT. |
||
| public class GracefulDisconnectEvent { | ||
|
|
||
| /** The node that is shutting down. */ | ||
| public final Node node; | ||
|
|
||
| public GracefulDisconnectEvent(Node node) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO for myself: |
||
| this.node = node; | ||
| } | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refer to @Override
public int hashCode() {
return Objects.hash(this.node);
}
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added equals and hashCode modeled on TopologyEvent in 86d0fad. |
||
| @Override | ||
| public boolean equals(Object other) { | ||
| if (other == this) { | ||
| return true; | ||
| } else if (other instanceof GracefulDisconnectEvent) { | ||
| GracefulDisconnectEvent that = (GracefulDisconnectEvent) other; | ||
| return Objects.equals(this.node, that.node); | ||
| } else { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Objects.hash(this.node); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return "GracefulDisconnectEvent(" + node + ")"; | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.