-
Notifications
You must be signed in to change notification settings - Fork 25.6k
[Zen2] Storage layer WriteStateException propagation #36052
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
Conversation
|
Pinging @elastic/es-distributed |
|
Pinging @elastic/es-core-infra |
|
I think this is how it should work, but I would like opinions from @elastic/es-core-infra too. To that end here is a high-level description of what's going on here: It is important not to lose any metadata updates. The consequences of losing a metadata update include forgetting that a shard copy was marked out-of-sync so it erroneously gets promoted to primary on restart, losing acked writes. "Don't lose any metadata updates" is one of the goals of the Zen2 project, and the solution is only to consider a metadata update to be successful when it has been written to disk (i.e. Zen2 is happiest if its writes to disk actually succeed (of course) but is also tolerant of failures which leaves the on-disk metadata untouched. However, if an The change proposed here is to throw an
I think the most common situation that'll yield these kinds of errors will be running out of storage, but even then most out-of-storage problems will manifest as earlier failures. It's a bit rude of the filesystem to wait for the The main alternative we discussed is simply to retry on this kind of failure. The argument against this is that the world is kinda broken if |
|
run gradle build tests 1 |
|
We discussed this issue as a team today and concluded that we are ok with the node shutting down with an exception in these situations. |
DaveCTurner
left a comment
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.
Asked for a couple of simplifications.
| // IOError is the best thing we have in java library to indicate that serious IO problem has occurred. | ||
| // IOError will be caught by ElasticsearchUncaughtExceptionHandler and JVM will be halted. | ||
| // Sadly, it has no constructor that accepts error message, so we first wrap WriteStateException with IOException. | ||
| throw new IOError(new IOException(msg + ", storage is dirty", 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 think we do not need the message here: the message indicates the calling method but this is also in the stack trace (and the previous log line) and we would know that the storage was dirty if we have an IOError caused by a WriteStateException.
| // Sadly, it has no constructor that accepts error message, so we first wrap WriteStateException with IOException. | ||
| throw new IOError(new IOException(msg + ", storage is dirty", this)); | ||
| } else { | ||
| throw new UncheckedIOException(msg, 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.
Similarly I think we don't need to add this message.
| } catch (WriteStateException e) { | ||
| logger.warn("Exception occurred when setting current term", e); | ||
| //TODO re-throw exception | ||
| logger.error("Failed to set current term to {}", currentTerm); |
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.
Could we log the exception and stack trace too? logger.error(new ParameterizedMessage("Failed to set current term to {}", currentTerm), e);
| } catch (WriteStateException e) { | ||
| logger.warn("Exception occurred when setting last accepted state", e); | ||
| //TODO re-throw exception | ||
| logger.error("Failed to set last accepted state with version {}", clusterState.version()); |
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.
Could we log the exception and stack trace too?
|
@DaveCTurner I've finished with the changes, could you please take a look? |
DaveCTurner
left a comment
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.
LGTM, thanks @andrershov
|
@DaveCTurner thanks for your reviewing efforts and bringing it up on the team meeting! |
Currently, we only log that
WriteStateExceptionhas occurred, inGatewayMetaState.This PR goal is to re-throw
WriteStateExceptionto upper layers.If
dirtyflag is set to false, we wrapWriteStateExceptioninUncheckedIOException, we prefer unchecked exception not to addexplicit
throwsin the multitude of layers.If
dirtyflag is set to true - the world is broken. And we need tohalt the JVM. Instead of explicit halting in
GatewayMetaState, weprefer to throw
IOError, which will be subsequently handled byElasticsearchUncaughtExceptionHandlerand JVM will be halted. Sadly,IOError accepts no message argument, that's why we first wrap
WriteStateExceptionwithIOExceptionand then withIOError.This PR also adds tests for
WriteStateException.