Repository navigation
Ensure deletion of snapshot clone propagate state changes - #142192
elasticsearchmachine merged 20 commits into
Conversation
|
Pinging @elastic/es-distributed (Team:Distributed) |
|
Hi @ywangd, I've created a changelog YAML for you. |
| cloneName | ||
| ); | ||
| if (abortSnapshot == false) { | ||
| snapshots.put(cloneName, new TrackedSnapshot(trackedRepository, cloneName)); |
There was a problem hiding this comment.
Add clone to the list of completed snapshots so that it can deleted, restored and cloned again.
| // The clone is running, submit a request to master to FAIL it. | ||
| // It may race with SUCCESS. That's OK, we can take either final state. | ||
| statusUpdater.sendUpdate( | ||
| snapshot, | ||
| null, | ||
| shardEntry.getKey(), | ||
| new ShardSnapshotStatus(nodeId, ShardState.FAILED, status.generation(), "aborted by snapshot deletion"), | ||
| ActionListener.noop() | ||
| ); |
There was a problem hiding this comment.
I chose to not update the state here. So that it will remain as INIT and get updated to FAILED by the update request. The alternative is to update it to ABORTED here as well as sending the update. I didn't do it because (1) A racing SUCCESS update can change ABORTED to SUCESS which is a bit strange. We can avoid it in applyShardSnapshotUpdate but it's extra code. (2) We don't use ABORTED for clones anywhere else. It was not necessary since it runs on the master. So in summary, I decided to keep the state unchanged here which feels overall simpler.
There was a problem hiding this comment.
I think we should be working towards making clones behave more similarly to regular snapshots wherever possible, and this moves us in the opposite direction. We can do away with a fair amount of this special-case handling if the master-as-cluster-state-custodian interacted with the master-as-shard-level-cloner more like how it interacts with data nodes taking shard-level snapshots.
To that end I'd prefer we used the ABORTED state "properly" here. FAILED generally means that nothing is writing to this location in the repository any more (ignoring nodes which left the cluster) but here AIUI we might mark the shard as FAILED even while its clone operation is in progress. In particular I think we could also fix this bug by marking the shard as ABORTED here and then teaching the shard-level cloner to react to this properly and move to FAILED (or SUCCESS) when its work is done.
Moving from ABORTED to SUCCESS is legitimate, we have that transition on non-clone snapshots too. Possibly that deserves a comment somewhere.
There was a problem hiding this comment.
I pushed 3c4f215 based on your suggestion. Does it match what you have in mind? We still need one if/else to handle the clone entry since it uses repoShardId instead of shardId.
Moving from ABORTED to SUCCESS is legitimate
Indeed, I missed it. The method name IndexShardSnapshotStatus#abortIfNotCompleted already indicates that.
DaveCTurner
left a comment
There was a problem hiding this comment.
Thanks Yang, nice catch. I'm not sure this is quite how I'd want to fix this tho - see comments.
| } | ||
|
|
||
| private Runnable createAbortRunnable(boolean abortSnapshot, TrackedRepository trackedRepository, String snapshotName) { | ||
| final boolean isClone = snapshotName.contains("-clone-"); |
There was a problem hiding this comment.
I don't really like this, but it seems it's only there for slightly more refined logs. Yet the log messages contain the snapshot name anyway. I think I'd rather stick with snapshot throughout (a clone is a special kind of snapshot) instead of doing this string-matching.
There was a problem hiding this comment.
Sure I removed it. Added it originally because the logs in startCloner do spell out clone.
| private Runnable createAbortRunnable(boolean abortSnapshot, TrackedRepository trackedRepository, String snapshotName) { | ||
| final boolean isClone = snapshotName.contains("-clone-"); | ||
| final Runnable abortRunnable; | ||
| if (abortSnapshot) { |
There was a problem hiding this comment.
Possible bikeshedding but also not a fan of this. createAbortRunnable sounds like it will create a runnable which aborts the snapshot. Possibly renaming it to maybeCreateAbortRunnable is enough? Or move this branch back out to the callers?
If we do keep it here, could we have a constant NO_OP_ABORT_RUNNABLE = () -> {} and check for equality with that rather than having a separate bool?
There was a problem hiding this comment.
Yeah good point. I renamed the method and used a noop runnable for the check.
| public void onFailure(Exception e) { | ||
| final Throwable cause = ExceptionsHelper.unwrapCause(e); | ||
| if (cause instanceof SnapshotException | ||
| && Regex.simpleMatch("*" + cloneName + "*Snapshot was aborted by deletion", cause.getMessage())) { |
There was a problem hiding this comment.
Bleurgh why is this reported specially? 🤦
Could we use org.elasticsearch.cluster.SnapshotsInProgress#ABORTED_FAILURE_TEXT rather than just the literal message?
Can we also check abortSnapshot in this if condition?
There was a problem hiding this comment.
I used ABORTED_FAILURE_TEXT as suggested. Also add check for the abort runnable.
why is this reported specially
Not sure I follow. Do you mean we should remove the message match or something else?
| // The clone is running, submit a request to master to FAIL it. | ||
| // It may race with SUCCESS. That's OK, we can take either final state. | ||
| statusUpdater.sendUpdate( | ||
| snapshot, | ||
| null, | ||
| shardEntry.getKey(), | ||
| new ShardSnapshotStatus(nodeId, ShardState.FAILED, status.generation(), "aborted by snapshot deletion"), | ||
| ActionListener.noop() | ||
| ); |
There was a problem hiding this comment.
I think we should be working towards making clones behave more similarly to regular snapshots wherever possible, and this moves us in the opposite direction. We can do away with a fair amount of this special-case handling if the master-as-cluster-state-custodian interacted with the master-as-shard-level-cloner more like how it interacts with data nodes taking shard-level snapshots.
To that end I'd prefer we used the ABORTED state "properly" here. FAILED generally means that nothing is writing to this location in the repository any more (ignoring nodes which left the cluster) but here AIUI we might mark the shard as FAILED even while its clone operation is in progress. In particular I think we could also fix this bug by marking the shard as ABORTED here and then teaching the shard-level cloner to react to this properly and move to FAILED (or SUCCESS) when its work is done.
Moving from ABORTED to SUCCESS is legitimate, we have that transition on non-clone snapshots too. Possibly that deserves a comment somewhere.
Co-authored-by: David Turner <david.turner@elastic.co>
| } | ||
| return Entry.createClone( | ||
| snapshot, | ||
| completed(clonesBuilder.values()) ? (hasFailures(clonesBuilder) ? State.FAILED : State.SUCCESS) : State.ABORTED, |
There was a problem hiding this comment.
Do we need to check hasFailures here or could we just say State.FAILED in the completed branch? AIUI State.SUCCESS means we finalize the clone and then delete it, whereas State.FAILED means we skip finalization, which will leak data on any shards that did succeed. We need to be ok with this kind of leak (it gets cleaned up by subsequent deletes) so I think we could make this slightly less branchy here.
There was a problem hiding this comment.
(yet another deviation in behaviour, we should finalize either way so that the follow-up delete does the cleanup, but again no action to take here, just a comment)
There was a problem hiding this comment.
could we just say State.FAILED in the completed branch
Yeah we can do that for simplicity. See a143e80
we should finalize either way
I didn't notice the difference behaviour in finalization. Thanks! Yeah consistency would be better.
Previously, when a clone is running with additional snapshots queued behind it, deleting the clone can leave the snapshots queued without starting the first queued. With this PR, we ensure the state is propogated correctly in such case so that the next inline snapshot or clone can run.
The PR also updates the stress tests to excercise aborting running clones as well as deleting completed ones.