Repository navigation
SOLR-18538: CREATESNAPSHOT reports success when a shard has no active replica - #5114
SpookyJumpyBeans wants to merge 2 commits into
Conversation
… replica CreateSnapshotCmd only evaluated failures for shards it sent a core snapshot request to. A shard whose replicas were all inactive received no request and was never checked, so the collection snapshot was recorded as Successful without a core snapshot for that shard. Failures were also compared against every replica in the shard, including the skipped ones, so a shard whose only active replica failed was counted as captured too. Require every active shard to have at least one replica that reported a core snapshot.
| * A collection snapshot must not be recorded as successful when a shard has no active replica to | ||
| * take a core snapshot. | ||
| */ | ||
| @LuceneTestCase.SuppressCodecs({"SimpleText"}) |
There was a problem hiding this comment.
Is there any good reason for codec suppression? This test does not seem to depend on it.
There was a problem hiding this comment.
Good catch, there’s no reason for it. I copied it from TestSolrCloudSnapshots, which needs it for backups, but this test doesn’t index or back up anything. Removed.
| } | ||
| DocCollection collectionStatus = | ||
| ccc.getZkStateReader().getClusterState().getCollection(collectionName); | ||
| for (Slice slice : collectionStatus.getActiveSlices()) { |
There was a problem hiding this comment.
We iterate only over active slices, while the initial loop to get all replicas (near line 102) considers all slices, not just active ones.
This seems inconsistent. If we don't consider the non active shards as part of the success/failure criteria, we could skip them initially.
There was a problem hiding this comment.
Agreed. BackupCmd only uses active slices anyway, so there’s no reason to snapshot inactive ones. The request loop now iterates getActiveSlices() too, so both steps use the same set.
| shardsWithSnapshot.add(replica.getShardId()); | ||
| } | ||
| DocCollection collectionStatus = | ||
| ccc.getZkStateReader().getClusterState().getCollection(collectionName); |
There was a problem hiding this comment.
I'd rather we don't read the collection state a second time. We should use same version we previously read. Second call is done after processResponses(), which is blocking and can take a while. The collection state might have slightly changed.
The old code had the same double read, but it only ran on the failure path.
There was a problem hiding this comment.
Makes sense. The collection state is now read once before sending the requests, and the same DocCollection is used for the success check, so it can’t change between the two.
…es, drop codec suppression
https://issues.apache.org/jira/browse/SOLR-18538
Description
CreateSnapshotCmdskips replicas that are not ACTIVE and only evaluates failures for shards it sent a core snapshot request to. If every replica of a shard is inactive, that shard is never checked and the collection snapshot is recorded asSuccessfulwith no core snapshot for it.The same happens when a shard's only active replica fails, because the failure count was compared against all of the shard's replicas, including the inactive ones that were skipped. In both cases the snapshot is reported as successful even though it can't be used to back up the missing shard.
Solution
Replace the per-shard failure counting with the check the existing comment describes: after collecting the successful core snapshots, every active slice must have at least one replica that reported a snapshot.
Any active slice without a snapshot is added to
failedShards, so the command recordsFailedand throws, as it already did for other failures.Tests
Added
TestSolrCloudSnapshotInactiveShard, which creates a single-shard, single-replica collection, stops the only node hosting it, and checks that CREATESNAPSHOT fails with "Failed to create snapshot on shards" and the snapshot is recorded asFailedwith no core snapshots. The test fails without the fix (the request succeeds) and passes with it.The second case (a shard whose only active replica fails) goes through the same new check, but isn't covered by a separate test, since making a single core snapshot fail on demand isn't straightforward in a cloud test. Happy to add one if there's a preferred way to inject that failure.
Also ran the existing snapshot tests (
TestSolrCloudSnapshotswith-Ptests.nightly=true,TestSolrCoreSnapshots,CreateCollectionSnapshotAPITest) and./gradlew :solr:core:check -x test.Checklist
mainbranch../gradlew check.