Simplify threading and networking in download suggester (#1512)

* Simplify threading in download suggester
This also makes it more robust against race conditions

* Simplify network requests around app store
This commit is contained in:
altrisi authored and GitHub committed 2022-07-25 21:59:50 +02:00
1 parent c08d857821
commit 97c4cc9c7d
1 file changed
+7 -58
@@ -18,14 +18,9 @@ import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.commands.CommandRuntimeException;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.world.level.storage.LevelResource;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -36,9 +31,10 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;
import org.apache.commons.io.IOUtils;
/**
* A class used to save scarpet app store scripts to disk
*/
@@ -85,7 +81,6 @@ public class AppStoreManager
public Map<String, StoreNode> children;
public boolean sealed;
public String value;
private CountDownLatch childrenProgress;
public static StoreNode folder(StoreNode parent, String name)
{
StoreNode node = new StoreNode(parent, name);
@@ -127,38 +122,23 @@ public class AppStoreManager
this.sealed = false;
}
public void fillChildren() throws IOException
public synchronized void fillChildren() throws IOException
{
if (sealed) return;
if (scarpetRepoLink == null) throw new IOException("Accessing scarpet app repo is disabled");
try
{
if (childrenProgress != null)
{
childrenProgress.await();
if (sealed) return;
else throw new IOException("Problems fetching suggestions. Check more details in previous exceptions.");
}
}
catch (InterruptedException e)
{
throw new IOException("Suggestion provider thread was interrupted, unexpected!", e);
}
childrenProgress = new CountDownLatch(1);
String queryPath = scarpetRepoLink + getPath();
String response;
try
{
response = AppStoreManager.getStringFromStream(queryPath);
response = IOUtils.toString(new URL(queryPath), StandardCharsets.UTF_8);
}
catch (IOException e)
{
childrenProgress.countDown();
childrenProgress = null; // Reset to allow retrying
// Not sealing to allow retrying
throw new IOException("Problems fetching " + queryPath, e);
}
JsonArray files = new JsonParser().parse(response).getAsJsonArray();
JsonArray files = JsonParser.parseString(response).getAsJsonArray();
for(JsonElement je : files)
{
JsonObject jo = je.getAsJsonObject();
@@ -174,7 +154,6 @@ public class AppStoreManager
}
}
sealed = true;
childrenProgress.countDown();
}
/**
@@ -265,7 +244,7 @@ public class AppStoreManager
String code;
try
{
code = getStringFromStream(nodeInfo.url());
code = IOUtils.toString(new URL(nodeInfo.url()), StandardCharsets.UTF_8);
}
catch (IOException e)
{
@@ -350,36 +329,6 @@ public class AppStoreManager
return true;
}
/** Returns the string from the inputstream gotten from the html request.
* Thanks to App Shah in <a href="https://crunchify.com/in-java-how-to-read-github-file-contents-using-httpurlconnection-convert-stream-to-string-utility/">this post</a>
* for this code.
*
* @return the string input from the InputStream
* @throws IOException if an I/O error occurs
*/
public static String getStringFromStream(String url) throws IOException
{
InputStream inputStream = new URL(url).openStream();
if (inputStream == null)
throw new IOException("No app to be found on the appstore");
Writer stringWriter = new StringWriter();
char[] charBuffer = new char[2048];
try
{
Reader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
int counter;
while ((counter = reader.read(charBuffer)) != -1)
stringWriter.write(charBuffer, 0, counter);
}
finally
{
inputStream.close();
}
return stringWriter.toString();
}
public static void writeUrlToFile(String url, Path destination) throws IOException
{
try (final InputStream in = new URL(url).openStream())