diff --git a/FCL/src/main/java/com/tungsten/fcl/setting/DownloadProviders.java b/FCL/src/main/java/com/tungsten/fcl/setting/DownloadProviders.java index 47f49e7c..c275829a 100644 --- a/FCL/src/main/java/com/tungsten/fcl/setting/DownloadProviders.java +++ b/FCL/src/main/java/com/tungsten/fcl/setting/DownloadProviders.java @@ -84,7 +84,7 @@ public final class DownloadProviders { AdaptedDownloadProvider fileProvider = new AdaptedDownloadProvider(); fileProvider.setDownloadProviderCandidates(Arrays.asList(MCBBS, BMCLAPI, MOJANG)); - BalancedDownloadProvider balanced = new BalancedDownloadProvider(Arrays.asList(MCBBS, BMCLAPI, MOJANG)); + BalancedDownloadProvider balanced = new BalancedDownloadProvider(MOJANG, MCBBS, BMCLAPI); providersById = mapOf( pair("official", new AutoDownloadProvider(MOJANG, fileProvider)), diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/download/BalancedDownloadProvider.java b/FCLCore/src/main/java/com/tungsten/fclcore/download/BalancedDownloadProvider.java index 9a068bbd..6da82010 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/download/BalancedDownloadProvider.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/download/BalancedDownloadProvider.java @@ -18,20 +18,17 @@ package com.tungsten.fclcore.download; import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.stream.Collectors; /** * Official Download Provider fetches version list from Mojang and * download files from mcbbs. */ -public class BalancedDownloadProvider implements DownloadProvider { - List candidates; +public final class BalancedDownloadProvider implements DownloadProvider { + private final DownloadProvider[] candidates; + private final Map> versionLists = new HashMap<>(); - Map> versionLists = new HashMap<>(); - - public BalancedDownloadProvider(List candidates) { + public BalancedDownloadProvider(DownloadProvider... candidates) { this.candidates = candidates; } @@ -52,13 +49,13 @@ public class BalancedDownloadProvider implements DownloadProvider { @Override public VersionList getVersionListById(String id) { - if (!versionLists.containsKey(id)) { - versionLists.put(id, new MultipleSourceVersionList( - candidates.stream() - .map(downloadProvider -> downloadProvider.getVersionListById(id)) - .collect(Collectors.toList()))); - } - return versionLists.get(id); + return versionLists.computeIfAbsent(id, value -> { + VersionList[] lists = new VersionList[candidates.length]; + for (int i = 0; i < candidates.length; i++) { + lists[i] = candidates[i].getVersionListById(value); + } + return new MultipleSourceVersionList(lists); + }); } @Override diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/download/MultipleSourceVersionList.java b/FCLCore/src/main/java/com/tungsten/fclcore/download/MultipleSourceVersionList.java index 52924c02..d9f54699 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/download/MultipleSourceVersionList.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/download/MultipleSourceVersionList.java @@ -17,23 +17,26 @@ */ package com.tungsten.fclcore.download; -import java.util.List; +import static com.tungsten.fclcore.util.Logging.LOG; + +import java.util.Arrays; import java.util.concurrent.CompletableFuture; +import java.util.logging.Level; public class MultipleSourceVersionList extends VersionList { - private final List> backends; + private final VersionList[] backends; - MultipleSourceVersionList(List> backends) { + MultipleSourceVersionList(VersionList[] backends) { this.backends = backends; - assert (backends.size() >= 1); + assert (backends.length >= 1); } @Override public boolean hasType() { - boolean hasType = backends.get(0).hasType(); - assert (backends.stream().allMatch(versionList -> versionList.hasType() == hasType)); + boolean hasType = backends[0].hasType(); + assert (Arrays.stream(backends).allMatch(versionList -> versionList.hasType() == hasType)); return hasType; } @@ -47,11 +50,9 @@ public class MultipleSourceVersionList extends VersionList { throw new UnsupportedOperationException("MultipleSourceVersionList does not support loading the entire remote version list."); } - @Override - public CompletableFuture refreshAsync(String gameVersion) { - versions.clear(gameVersion); - return CompletableFuture.anyOf(backends.stream() - .map(versionList -> versionList.refreshAsync(gameVersion) + private CompletableFuture refreshAsync(String gameVersion, int sourceIndex) { + VersionList versionList = backends[sourceIndex]; + CompletableFuture future = versionList.refreshAsync(gameVersion) .thenRunAsync(() -> { lock.writeLock().lock(); @@ -60,7 +61,25 @@ public class MultipleSourceVersionList extends VersionList { } finally { lock.writeLock().unlock(); } - })) - .toArray(CompletableFuture[]::new)); + }); + + if (sourceIndex == backends.length - 1) { + return future; + } else { + return future.>handle((ignore, e) -> { + if (e == null) { + return future; + } + + LOG.log(Level.WARNING, "Failed to fetch versions list and try to fetch from other source", e); + return refreshAsync(gameVersion, sourceIndex + 1); + }).thenCompose(it -> it); + } + } + + @Override + public CompletableFuture refreshAsync(String gameVersion) { + versions.clear(gameVersion); + return refreshAsync(gameVersion, 0); } }