org.elasticsearch.indices.recovery.RecoveryTarget#restoreFileFromSnapshot does not check for cancellation during the download of a file. This means that if a recovery is cancelled mid-way, we will still not release the store/shard-lock until the file is fully downloaded.
For large files or slow downloads this can lead to problems when the shard is (re-)allocated to a node that is still executing such an interrupted recovery.

-> we need to add some checks for cancellation here like we have for other recovery modes.
x-pack/plugin/snapshot-based-recoveries/src/internalClusterTest/java/org/elasticsearch/xpack/snapshotbasedrecoveries/recovery/SnapshotBasedIndexRecoveryIT.java
.put(INDICES_RECOVERY_INTERNAL_ACTION_RETRY_TIMEOUT_SETTING.getKey(), TimeValue.ZERO)
                .put(INDICES_RECOVERY_MAX_CONCURRENT_SNAPSHOT_FILE_DOWNLOADS.getKey(), 1)
                .put(INDICES_RECOVERY_MAX_CONCURRENT_FILE_CHUNKS_SETTING.getKey(), 1)
                .put(INDICES_RECOVERY_MAX_CONCURRENT_OPERATIONS_SETTING.getKey(), 1)
        );
        int numDocs = randomIntBetween(300, 1000);
        indexDocs(indexName, 0, numDocs);
        
        
        flush(indexName);
        String repoName = "repo";
        createRepo(repoName, TestRepositoryPlugin.FILTER_TYPE);
        createSnapshot(repoName, "snap", Collections.singletonList(indexName));
        ClusterState clusterState = client().admin().cluster().prepareState().get().getState();
        String primaryNodeId = clusterState.routingTable().index(indexName).shard(0).primaryShard().currentNodeId();
        String primaryNodeName = clusterState.nodes().resolveNode(primaryNodeId).getName();
        String replicaNodeId = clusterState.routingTable().index(indexName).shard(0).replicaShards().get(0).currentNodeId();
        String replicaNodeName = clusterState.nodes().resolveNode(replicaNodeId).getName();
        String newReplicaNodeName = dataNodes.stream()
            .filter(nodeName -> nodeName.equals(primaryNodeName) == false)
            .filter(nodeName -> nodeName.equals(replicaNodeName) == false)
            .findFirst()
            .orElseThrow();
        MockTransportService sourceMockTransportService = (MockTransportService) internalCluster().getInstance(
            TransportService.class,
            replicaNodeName
        );
        MockTransportService targetMockTransportService = (MockTransportService) internalCluster().getInstance(
            TransportService.class,