When a shard is to be snapshotted, we acquire a store ref (wrapped in an index commit) and then enqueue the shard snapshot task for execution by the repository:

https://github.com/elastic/elasticsearch/blob/b124763772748d8993911e4a7ba94b17472a9539/server/src/main/java/org/elasticsearch/snapshots/SnapshotShardsService.java#L369-L384

If the shard is closed while its snapshot is in the queue then it looks like we do not release the store ref promptly. Instead, we keep hold of it until it reaches the front of the queue, which could be many minutes later. During this time the shard cannot fully shut down and release the shard lock, leading to a `ShardLockObtainFailedException` being thrown on attempts to reinitialise the shard.
server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java
public boolean supportURLRepo() {
        return supportURLRepo;
    }
    /**
     * @return whether this repository perms overwrites atomically. In practice we only overwrite the `index.latest` blob so this
     * is not very important, but the repository analyzer does test that overwrites happen atomically. It will skip those tests if the
     * repository overrides this method to indicate that it does not support atomic overwrites.
     */
    public boolean hasAtomicOverwrites() {
        return true;
    }
    public int getReadBufferSizeInBytes() {
        return bufferSize;
    }
    /**
     * The result of removing a snapshot from a shard folder in the repository.
     *
     * @param indexId       Index that the snapshot was removed from
     * @param shardId       Shard id that the snapshot was removed from
     * @param newGeneration Id of the new index-${uuid} blob that does not include the snapshot any more
     * @param blobsToDelete Blob names in the shard directory that have become unreferenced in the new shard generation
     */
    private record ShardSnapshotMetaDeleteResult(
        IndexId indexId,
        int shardId,
        ShardGeneration newGeneration,
        Collection<String> blobsToDelete
    ) {}
}