-
Notifications
You must be signed in to change notification settings - Fork 25.1k
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
Include last-committed data in publication #92259
Changes from 3 commits
ad1574f
226591b
c95a33e
768a864
88c729d
b910c87
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 |
---|---|---|
@@ -0,0 +1,6 @@ | ||
pr: 92259 | ||
summary: Include last-committed data in publication | ||
area: Cluster Coordination | ||
type: bug | ||
issues: | ||
- 90158 |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -556,27 +556,18 @@ public interface PersistedState extends Closeable { | |||||
* marked as committed. | ||||||
*/ | ||||||
default void markLastAcceptedStateAsCommitted() { | ||||||
final ClusterState lastAcceptedState = getLastAcceptedState(); | ||||||
Metadata.Builder metadataBuilder = null; | ||||||
if (lastAcceptedState.getLastAcceptedConfiguration().equals(lastAcceptedState.getLastCommittedConfiguration()) == false) { | ||||||
final CoordinationMetadata coordinationMetadata = CoordinationMetadata.builder(lastAcceptedState.coordinationMetadata()) | ||||||
.lastCommittedConfiguration(lastAcceptedState.getLastAcceptedConfiguration()) | ||||||
.build(); | ||||||
metadataBuilder = Metadata.builder(lastAcceptedState.metadata()); | ||||||
metadataBuilder.coordinationMetadata(coordinationMetadata); | ||||||
} | ||||||
assert lastAcceptedState.metadata().clusterUUID().equals(Metadata.UNKNOWN_CLUSTER_UUID) == false | ||||||
: "received cluster state with empty cluster uuid: " + lastAcceptedState; | ||||||
if (lastAcceptedState.metadata().clusterUUID().equals(Metadata.UNKNOWN_CLUSTER_UUID) == false | ||||||
&& lastAcceptedState.metadata().clusterUUIDCommitted() == false) { | ||||||
if (metadataBuilder == null) { | ||||||
metadataBuilder = Metadata.builder(lastAcceptedState.metadata()); | ||||||
} | ||||||
metadataBuilder.clusterUUIDCommitted(true); | ||||||
final var lastAcceptedState = getLastAcceptedState(); | ||||||
final var hasClusterUuid = lastAcceptedState.metadata().clusterUUID().equals(Metadata.UNKNOWN_CLUSTER_UUID) == false; | ||||||
assert hasClusterUuid : "received cluster state with empty cluster uuid: " + lastAcceptedState; | ||||||
|
||||||
if (hasClusterUuid && lastAcceptedState.metadata().clusterUUIDCommitted() == false) { | ||||||
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. Feels odd to protect the logging by something we assert on above?
Suggested change
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. Ehh I just kept the same logic as before but I don't think I've ever seen this assertion trip. I'd be ok to drop it. |
||||||
logger.info("cluster UUID set to [{}]", lastAcceptedState.metadata().clusterUUID()); | ||||||
} | ||||||
if (metadataBuilder != null) { | ||||||
setLastAcceptedState(ClusterState.builder(lastAcceptedState).metadata(metadataBuilder).build()); | ||||||
|
||||||
final var adjustedMetadata = lastAcceptedState.metadata() | ||||||
.withLastCommittedValues(hasClusterUuid, lastAcceptedState.getLastAcceptedConfiguration()); | ||||||
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. Should we pass in |
||||||
if (adjustedMetadata != lastAcceptedState.metadata()) { | ||||||
setLastAcceptedState(ClusterState.builder(lastAcceptedState).metadata(adjustedMetadata).build()); | ||||||
} | ||||||
} | ||||||
|
||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -86,6 +86,8 @@ public class PublicationTransportHandler { | |
TransportRequestOptions.Type.STATE | ||
); | ||
|
||
public static final Version INCLUDES_LAST_COMMITTED_DATA_VERSION = Version.V_8_7_0; | ||
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. @DaveCTurner should this be 8.6.0 since it's intended to be backported? 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. I'll adjust that while backporting. If I set this to 8.6.0 now then the BwC test suite would fail on this PR, but it's important for those tests to pass because they tell us whether there are any other more subtle BwC problems here. 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. Joining the dots here:
|
||
|
||
private final SerializationStatsTracker serializationStatsTracker = new SerializationStatsTracker(); | ||
|
||
public PublicationTransportHandler( | ||
|
@@ -131,6 +133,7 @@ private PublishWithJoinResponse handleIncomingPublishRequest(BytesTransportReque | |
// Close early to release resources used by the de-compression as early as possible | ||
try (StreamInput input = in) { | ||
incomingState = ClusterState.readFrom(input, transportService.getLocalNode()); | ||
assert input.read() == -1; | ||
} catch (Exception e) { | ||
logger.warn("unexpected error while deserializing an incoming cluster state", e); | ||
assert false : e; | ||
|
@@ -151,11 +154,30 @@ private PublishWithJoinResponse handleIncomingPublishRequest(BytesTransportReque | |
ClusterState incomingState; | ||
try { | ||
final Diff<ClusterState> diff; | ||
final boolean includesLastCommittedData = request.version().onOrAfter(INCLUDES_LAST_COMMITTED_DATA_VERSION); | ||
final boolean clusterUuidCommitted; | ||
final CoordinationMetadata.VotingConfiguration lastCommittedConfiguration; | ||
|
||
// Close stream early to release resources used by the de-compression as early as possible | ||
try (StreamInput input = in) { | ||
diff = ClusterState.readDiffFrom(input, lastSeen.nodes().getLocalNode()); | ||
if (includesLastCommittedData) { | ||
clusterUuidCommitted = in.readBoolean(); | ||
lastCommittedConfiguration = new CoordinationMetadata.VotingConfiguration(in); | ||
} else { | ||
clusterUuidCommitted = false; | ||
lastCommittedConfiguration = null; | ||
} | ||
assert input.read() == -1; | ||
} | ||
incomingState = diff.apply(lastSeen); // might throw IncompatibleClusterStateVersionException | ||
if (includesLastCommittedData) { | ||
final var adjustedMetadata = incomingState.metadata() | ||
.withLastCommittedValues(clusterUuidCommitted, lastCommittedConfiguration); | ||
if (adjustedMetadata != incomingState.metadata()) { | ||
incomingState = ClusterState.builder(incomingState).metadata(adjustedMetadata).build(); | ||
} | ||
} | ||
} catch (IncompatibleClusterStateVersionException e) { | ||
incompatibleClusterStateDiffReceivedCount.incrementAndGet(); | ||
throw e; | ||
|
@@ -239,7 +261,8 @@ private ReleasableBytesReference serializeFullClusterState(ClusterState clusterS | |
} | ||
} | ||
|
||
private ReleasableBytesReference serializeDiffClusterState(long clusterStateVersion, Diff<ClusterState> diff, DiscoveryNode node) { | ||
private ReleasableBytesReference serializeDiffClusterState(ClusterState newState, Diff<ClusterState> diff, DiscoveryNode node) { | ||
final long clusterStateVersion = newState.version(); | ||
final Version nodeVersion = node.getVersion(); | ||
final RecyclerBytesStreamOutput bytesStream = transportService.newNetworkBytesStream(); | ||
boolean success = false; | ||
|
@@ -253,6 +276,10 @@ private ReleasableBytesReference serializeDiffClusterState(long clusterStateVers | |
stream.setVersion(nodeVersion); | ||
stream.writeBoolean(false); | ||
diff.writeTo(stream); | ||
if (nodeVersion.onOrAfter(INCLUDES_LAST_COMMITTED_DATA_VERSION)) { | ||
stream.writeBoolean(newState.metadata().clusterUUIDCommitted()); | ||
newState.getLastCommittedConfiguration().writeTo(stream); | ||
} | ||
uncompressedBytes = stream.position(); | ||
} catch (IOException e) { | ||
throw new ElasticsearchException("failed to serialize cluster state diff for publishing to node {}", e, node); | ||
|
@@ -316,7 +343,7 @@ void buildDiffAndSerializeStates() { | |
} else { | ||
serializedDiffs.computeIfAbsent( | ||
node.getVersion(), | ||
v -> serializeDiffClusterState(newState.version(), diffSupplier.getOrCompute(), node) | ||
v -> serializeDiffClusterState(newState, diffSupplier.getOrCompute(), node) | ||
); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the code is cleaner, but I failed to spot the important difference, is it just the logging you wanted out of this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this does anything different, there's just no need to use a
Metadata.Builder
here any more.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. In that case, let us revert this and move this to a follow-up, where we can also assume that assertions are held (i.e., use
true
instead ofhasClusterUuid
later in the code).