This commit is contained in:
Glavo
2024-01-30 12:31:14 +08:00
committed by GitHub
parent d286f93a7e
commit 4102029d6d
3 changed files with 44 additions and 28 deletions

View File

@@ -78,7 +78,7 @@ public final class DownloadProviders {
AdaptedDownloadProvider fileProvider = new AdaptedDownloadProvider(); AdaptedDownloadProvider fileProvider = new AdaptedDownloadProvider();
fileProvider.setDownloadProviderCandidates(Arrays.asList(MCBBS, BMCLAPI, MOJANG)); 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( providersById = mapOf(
pair("official", new AutoDownloadProvider(MOJANG, fileProvider)), pair("official", new AutoDownloadProvider(MOJANG, fileProvider)),

View File

@@ -18,9 +18,7 @@
package org.jackhuang.hmcl.download; package org.jackhuang.hmcl.download;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
/** /**
* Official Download Provider fetches version list from Mojang and * Official Download Provider fetches version list from Mojang and
@@ -28,12 +26,11 @@ import java.util.stream.Collectors;
* *
* @author huangyuhui * @author huangyuhui
*/ */
public class BalancedDownloadProvider implements DownloadProvider { public final class BalancedDownloadProvider implements DownloadProvider {
List<DownloadProvider> candidates; private final DownloadProvider[] candidates;
private final Map<String, VersionList<?>> versionLists = new HashMap<>();
Map<String, VersionList<?>> versionLists = new HashMap<>(); public BalancedDownloadProvider(DownloadProvider... candidates) {
public BalancedDownloadProvider(List<DownloadProvider> candidates) {
this.candidates = candidates; this.candidates = candidates;
} }
@@ -54,13 +51,13 @@ public class BalancedDownloadProvider implements DownloadProvider {
@Override @Override
public VersionList<?> getVersionListById(String id) { public VersionList<?> getVersionListById(String id) {
if (!versionLists.containsKey(id)) { return versionLists.computeIfAbsent(id, value -> {
versionLists.put(id, new MultipleSourceVersionList( VersionList<?>[] lists = new VersionList<?>[candidates.length];
candidates.stream() for (int i = 0; i < candidates.length; i++) {
.map(downloadProvider -> downloadProvider.getVersionListById(id)) lists[i] = candidates[i].getVersionListById(value);
.collect(Collectors.toList())));
} }
return versionLists.get(id); return new MultipleSourceVersionList(lists);
});
} }
@Override @Override

View File

@@ -17,23 +17,26 @@
*/ */
package org.jackhuang.hmcl.download; package org.jackhuang.hmcl.download;
import java.util.List; import java.util.Arrays;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import static org.jackhuang.hmcl.util.Logging.LOG;
public class MultipleSourceVersionList extends VersionList<RemoteVersion> { public class MultipleSourceVersionList extends VersionList<RemoteVersion> {
private final List<VersionList<?>> backends; private final VersionList<?>[] backends;
MultipleSourceVersionList(List<VersionList<?>> backends) { MultipleSourceVersionList(VersionList<?>[] backends) {
this.backends = backends; this.backends = backends;
assert (backends.size() >= 1); assert (backends.length >= 1);
} }
@Override @Override
public boolean hasType() { public boolean hasType() {
boolean hasType = backends.get(0).hasType(); boolean hasType = backends[0].hasType();
assert (backends.stream().allMatch(versionList -> versionList.hasType() == hasType)); assert (Arrays.stream(backends).allMatch(versionList -> versionList.hasType() == hasType));
return hasType; return hasType;
} }
@@ -47,11 +50,9 @@ public class MultipleSourceVersionList extends VersionList<RemoteVersion> {
throw new UnsupportedOperationException("MultipleSourceVersionList does not support loading the entire remote version list."); throw new UnsupportedOperationException("MultipleSourceVersionList does not support loading the entire remote version list.");
} }
@Override private CompletableFuture<?> refreshAsync(String gameVersion, int sourceIndex) {
public CompletableFuture<?> refreshAsync(String gameVersion) { VersionList<?> versionList = backends[sourceIndex];
versions.clear(gameVersion); CompletableFuture<Void> future = versionList.refreshAsync(gameVersion)
return CompletableFuture.anyOf(backends.stream()
.map(versionList -> versionList.refreshAsync(gameVersion)
.thenRunAsync(() -> { .thenRunAsync(() -> {
lock.writeLock().lock(); lock.writeLock().lock();
@@ -60,7 +61,25 @@ public class MultipleSourceVersionList extends VersionList<RemoteVersion> {
} finally { } finally {
lock.writeLock().unlock(); lock.writeLock().unlock();
} }
})) });
.toArray(CompletableFuture[]::new));
if (sourceIndex == backends.length - 1) {
return future;
} else {
return future.<CompletableFuture<?>>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);
} }
} }