Skip to content
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

Added wait_for_metadata_version parameter to cluster state api. #35535

Merged
merged 19 commits into from Nov 26, 2018

Conversation

martijnvg
Copy link
Member

The wait_for_metadata_version parameter will instruct the cluster state
api to return a cluster state until the metadata's version is equal or
greater than the version specified in wait_for_metadata_version or wait
until till the specified wait_for_timeout has expired, in this case the
cluster state is returned and time_out field is set to true.

In the case metadata's version is equal or higher than wait_for_metadata_version
then this api will immediately return.

This feature is useful to avoid external components from constantly
polling the cluster state to whether somethings have changed in the
cluster state's metadata.

I'm not sure what the best feature label for this issue is, so I labelled it as :Core/Core. I'm happy to change the label.

The `wait_for_metadata_version` parameter will instruct the cluster state
api to return a cluster state until the metadata's version is equal or
greater than the version specified in `wait_for_metadata_version` or wait
until till the specified `wait_for_timeout` has expired. In  the case
metadata's version is equal or higher than  `wait_for_metadata_version`
then the api will immediately return.

This feature is useful to avoid external components from constantly
polling the cluster state to whether somethings have changed in the
cluster state's metadata.
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-core-infra

Copy link
Member

@jasontedor jasontedor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change looks good overall. I left a few minor comments.

The only thing I am doubting is whether or not to return the last known state after a timeout. If we don't do that, we don't need to change the ClusterStateObserver.Listener interface. What is your thinking behind sending back a cluster state in this case as opposed to an empty response that would more clearly indicate the request timed out?

I'll do another quick pass after we come to a decision on this point.

* Returns whether waiting for a cluster state wait a metadata version equal or higher than the specified
* metadata version timed out.
*/
public boolean isTimedOut() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Javadocs are clear but I think the name could be clearer and reflect the name of the parameter on the request: isWaitForTimedOut


public ClusterStateResponse() {
}

public ClusterStateResponse(ClusterName clusterName, ClusterState clusterState, long sizeInBytes) {
public ClusterStateResponse(ClusterName clusterName, ClusterState clusterState, long sizeInBytes, boolean timedOut) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

timedOut -> waitForTimedOut (to clarify that it's not a generic timeout)

@@ -40,14 +41,16 @@
// the total compressed size of the full cluster state, not just
// the parts included in this response
private ByteSizeValue totalCompressedSize;
private boolean timedOut = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

timedOut -> waitForTimedOut


@Override
public int hashCode() {
// Best effort for testing. Left out cluster state, because it doesn't implement equals() and hashcode()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe hash the version and the master node ID (that's what an observer considers to be the same for purposes of comparing cluster states)?

ClusterStateResponse response = (ClusterStateResponse) o;
return timedOut == response.timedOut &&
Objects.equals(clusterName, response.clusterName) &&
// Best effort. Left out cluster state, because it doesn't implement equals() and hashcode()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe compare the version and the master node ID (that's what an observer considers to the same for purposes of comparing cluster states)?


private void buildResponse(final ClusterStateRequest request,
final ClusterState currentState,
final boolean timedOut,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

waitForTimedOut

@martijnvg
Copy link
Member Author

Thanks for reviewing @jasontedor

The only thing I am doubting is whether or not to return the last known state after a timeout. If we don't do that, we don't need to change the ClusterStateObserver.Listener interface. What is your thinking behind sending back a cluster state in this case as opposed to an empty response that would more clearly indicate the request timed out?

I wanted it to be similar to the shard changes api. In this case when it times out waiting for new ops, it returns a response with potential updated mapping / settings version and no ops. In the case of cluster state api, other things outside metadata may have changed and so it made sense to me to return the cluster state with a timed out flag.

@martijnvg
Copy link
Member Author

After talking to @jasontedor, it made sense to not return a cluster state when wait for metadata version has timed out, so I made that change. This also means the change to ClusterStateObserver.Listener has been reverted.

Copy link
Member

@jasontedor jasontedor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good. I left a few more minors.

}

@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
clusterName.writeTo(out);
if (out.getVersion().onOrAfter(Version.V_6_3_0)) {
clusterState.writeTo(out);
if (out.getVersion().onOrAfter(Version.V_7_0_0)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: 6.6.0

@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
clusterName = new ClusterName(in);
clusterState = ClusterState.readFrom(in, null);
if (in.getVersion().onOrAfter(Version.V_7_0_0)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: 6.6.0

@@ -56,6 +67,10 @@ public void testSerialization() throws Exception {
assertThat(deserializedCSRequest.blocks(), equalTo(clusterStateRequest.blocks()));
assertThat(deserializedCSRequest.indices(), equalTo(clusterStateRequest.indices()));
assertOptionsMatch(deserializedCSRequest.indicesOptions(), clusterStateRequest.indicesOptions());
if (testVersion.onOrAfter(Version.V_7_0_0)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: 6.6.0

}

public ClusterStateRequest waitForMetaDataVersion(long expectedMetaDataVersion) {
this.waitForMetaDataVersion = expectedMetaDataVersion;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we require this be >= 1?

@@ -94,6 +98,7 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
@Override
public RestResponse buildResponse(ClusterStateResponse response, XContentBuilder builder) throws Exception {
builder.startObject();
builder.field(Fields.TIMED_OUT, response.isWaitForTimedOut());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this field should be called wait_for_timed_out? And I wonder if we should only include it if wait_for_metadata_version was set on the request?

@martijnvg
Copy link
Member Author

@jasontedor I've updated the PR.


public ClusterStateRequest waitForMetaDataVersion(long waitForMetaDataVersion) {
if (waitForMetaDataVersion < 1) {
throw new IllegalArgumentException("waitForMetaDataVersion should be >= 1");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include the invalid value?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@martijnvg What do you think about including the default value here?

},
"wait_for_timeout" : {
"type": "time",
"description": "The maximum time to wait for wait_for_metadata_version before stop waiting and then the last observed cluster state is returned"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This documentation comment is stale now.

@@ -75,11 +79,24 @@ public ByteSizeValue getTotalCompressedSize() {
return totalCompressedSize;
}

/**
* Returns whether waiting for a cluster state wait a metadata version equal or higher than the specified
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returns whether -> Returns whether the request timed out waiting... and remove timed out from the end of the sentence.

assertThat(future2.isDone(), is(true));
});
ClusterStateResponse response = future2.actionGet();
assertThat(response.isWaitForTimedOut(), is(false));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a really slow or overloaded machine, this can timeout in a second and cause spurious build failures. How about setting the timeout really high here (e.g., one hour). Then, in the test when you test that the timeout works, set the timeout low again.

@jasontedor
Copy link
Member

I left a few comments, no need for another round.

@martijnvg martijnvg merged commit 7624734 into elastic:master Nov 26, 2018
martijnvg added a commit to martijnvg/elasticsearch that referenced this pull request Nov 26, 2018
…tic#35535)

The `wait_for_metadata_version` parameter will instruct the cluster state
api to only return a cluster state until the metadata's version is equal or
greater than the version specified in `wait_for_metadata_version`. If
the specified `wait_for_timeout` has expired then a timed out response
is returned. (a response with no cluster state and wait for timed out flag set to true)
In  the case metadata's version is equal or higher than  `wait_for_metadata_version`
then the api will immediately return.

This feature is useful to avoid external components from constantly
polling the cluster state to whether somethings have changed in the
cluster state's metadata.
martijnvg added a commit that referenced this pull request Nov 27, 2018
The `wait_for_metadata_version` parameter will instruct the cluster state
api to only return a cluster state until the metadata's version is equal or
greater than the version specified in `wait_for_metadata_version`. If
the specified `wait_for_timeout` has expired then a timed out response
is returned. (a response with no cluster state and wait for timed out flag set to true)
In  the case metadata's version is equal or higher than  `wait_for_metadata_version`
then the api will immediately return.

This feature is useful to avoid external components from constantly
polling the cluster state to whether somethings have changed in the
cluster state's metadata.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants