Browse Source

Fixed bug caused by multiple concurrent builds of the same resource.

Several parts of the code request resources to be loaded/built, and these separate threads were tripping over each other and causing build failures. This has been avoided by making sure the resource isn't already building before requesting it.
qdn
CalDescent 3 years ago
parent
commit
361dc79ede
  1. 2
      src/main/java/org/qortal/api/gateway/resource/GatewayResource.java
  2. 7
      src/main/java/org/qortal/api/resource/ArbitraryResource.java
  3. 4
      src/main/java/org/qortal/arbitrary/ArbitraryDataReader.java
  4. 19
      src/main/java/org/qortal/arbitrary/ArbitraryDataRenderer.java

2
src/main/java/org/qortal/api/gateway/resource/GatewayResource.java

@ -56,7 +56,9 @@ public class GatewayResource {
if (build != null && build == true) {
ArbitraryDataReader reader = new ArbitraryDataReader(name, ArbitraryDataFile.ResourceIdType.NAME, service, null);
try {
if (!reader.isBuilding()) {
reader.loadSynchronously(false);
}
} catch (Exception e) {
// No need to handle exception, as it will be reflected in the status
}

7
src/main/java/org/qortal/api/resource/ArbitraryResource.java

@ -938,6 +938,7 @@ public class ArbitraryResource {
// Loop until we have data
while (!Controller.isStopping()) {
attempts++;
if (!arbitraryDataReader.isBuilding()) {
try {
arbitraryDataReader.loadSynchronously(rebuild);
break;
@ -946,10 +947,10 @@ public class ArbitraryResource {
// Give up after 5 attempts
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_CRITERIA, "Data unavailable. Please try again later.");
}
Thread.sleep(3000L);
}
}
Thread.sleep(3000L);
}
java.nio.file.Path outputPath = arbitraryDataReader.getFilePath();
if (filepath == null || filepath.isEmpty()) {
@ -986,7 +987,9 @@ public class ArbitraryResource {
if (build != null && build == true) {
ArbitraryDataReader reader = new ArbitraryDataReader(name, ArbitraryDataFile.ResourceIdType.NAME, service, null);
try {
if (!reader.isBuilding()) {
reader.loadSynchronously(false);
}
} catch (Exception e) {
// No need to handle exception, as it will be reflected in the status
}

4
src/main/java/org/qortal/arbitrary/ArbitraryDataReader.java

@ -107,6 +107,10 @@ public class ArbitraryDataReader {
return false;
}
public boolean isBuilding() {
return ArbitraryDataBuildManager.getInstance().isInBuildQueue(this.createQueueItem());
}
private ArbitraryDataBuildQueueItem createQueueItem() {
return new ArbitraryDataBuildQueueItem(this.resourceId, this.resourceIdType, this.service, this.identifier);
}

19
src/main/java/org/qortal/arbitrary/ArbitraryDataRenderer.java

@ -6,7 +6,9 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.qortal.api.HTMLParser;
import org.qortal.arbitrary.ArbitraryDataFile.*;
import org.qortal.arbitrary.exception.MissingDataException;
import org.qortal.arbitrary.misc.Service;
import org.qortal.controller.Controller;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
@ -72,8 +74,23 @@ public class ArbitraryDataRenderer {
return this.getLoadingResponse(service, resourceId);
}
// Otherwise, hang the request until the build completes
// Otherwise, loop until we have data
int attempts = 0;
while (!Controller.isStopping()) {
attempts++;
if (!arbitraryDataReader.isBuilding()) {
try {
arbitraryDataReader.loadSynchronously(false);
break;
} catch (MissingDataException e) {
if (attempts > 5) {
// Give up after 5 attempts
return ArbitraryDataRenderer.getResponse(response, 404, "Data unavailable. Please try again later.");
}
}
}
Thread.sleep(3000L);
}
}
} catch (Exception e) {

Loading…
Cancel
Save