An incomplete shard snapshot will prevent a shard from moving away from a node (see `SnapshotInProgressAllocationDecider`). That means that when a shard snapshot completes it may become possible to perform some shard movements that previously were not possible, so we should trigger a reroute to start those movements. AFAICT we do not trigger such a reroute today.
server/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java
.collect(Collectors.toSet());
                    for (SnapshotsInProgress.Entry entry : finishedSnapshots) {
                        if (reposWithRunningDeletes.contains(entry.repository()) == false) {
                            endSnapshot(entry, newState.metadata(), null);
                        }
                    }
                }
                startExecutableClones(SnapshotsInProgress.get(newState), null);
                
                for (SnapshotDeletionsInProgress.Entry entry : deletionsToExecute) {
                    if (tryEnterRepoLoop(entry.repository())) {
                        deleteSnapshotsFromRepository(entry, newState.nodes().getMaxDataNodeCompatibleIndexVersion());
                    }
                }
            }
        });
    }
    private static ImmutableOpenMap<ShardId, ShardSnapshotStatus> processWaitingShardsAndRemovedNodes(
        SnapshotsInProgress.Entry entry,
        RoutingTable routingTable,
        DiscoveryNodes nodes,
        Map<RepositoryShardId, ShardSnapshotStatus> knownFailures
    ) {
        assert entry.isClone() == false : "clones take a different path";
        boolean snapshotChanged = false;
        ImmutableOpenMap.Builder<ShardId, ShardSnapshotStatus> shards = ImmutableOpenMap.builder();
        for (Map.Entry<RepositoryShardId, ShardSnapshotStatus> shardEntry : entry.shardsByRepoShardId().entrySet()) {
            ShardSnapshotStatus shardStatus = shardEntry.getValue();
            ShardId shardId = entry.shardId(shardEntry.getKey());
            if (shardStatus.equals(ShardSnapshotStatus.UNASSIGNED_QUEUED)) {