forked from Qortal/qortal
Added "async" and "attempts" parameters to GET /arbitrary/{service}/{name}* endpoints.
async = fail immediately with 404 if missing, and request in the background attempts = the number of times to request the data (synchronous mode only for now)
This commit is contained in:
parent
3c526db52e
commit
2740543abf
@ -576,14 +576,16 @@ public class ArbitraryResource {
|
|||||||
@PathParam("service") Service service,
|
@PathParam("service") Service service,
|
||||||
@PathParam("name") String name,
|
@PathParam("name") String name,
|
||||||
@QueryParam("filepath") String filepath,
|
@QueryParam("filepath") String filepath,
|
||||||
@QueryParam("rebuild") boolean rebuild) {
|
@QueryParam("rebuild") boolean rebuild,
|
||||||
|
@QueryParam("async") boolean async,
|
||||||
|
@QueryParam("attempts") Integer attempts) {
|
||||||
|
|
||||||
// Authentication can be bypassed in the settings, for those running public QDN nodes
|
// Authentication can be bypassed in the settings, for those running public QDN nodes
|
||||||
if (!Settings.getInstance().isQDNAuthBypassEnabled()) {
|
if (!Settings.getInstance().isQDNAuthBypassEnabled()) {
|
||||||
Security.checkApiCallAllowed(request);
|
Security.checkApiCallAllowed(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.download(service, name, null, filepath, rebuild);
|
return this.download(service, name, null, filepath, rebuild, async, attempts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@ -609,14 +611,16 @@ public class ArbitraryResource {
|
|||||||
@PathParam("name") String name,
|
@PathParam("name") String name,
|
||||||
@PathParam("identifier") String identifier,
|
@PathParam("identifier") String identifier,
|
||||||
@QueryParam("filepath") String filepath,
|
@QueryParam("filepath") String filepath,
|
||||||
@QueryParam("rebuild") boolean rebuild) {
|
@QueryParam("rebuild") boolean rebuild,
|
||||||
|
@QueryParam("async") boolean async,
|
||||||
|
@QueryParam("attempts") Integer attempts) {
|
||||||
|
|
||||||
// Authentication can be bypassed in the settings, for those running public QDN nodes
|
// Authentication can be bypassed in the settings, for those running public QDN nodes
|
||||||
if (!Settings.getInstance().isQDNAuthBypassEnabled()) {
|
if (!Settings.getInstance().isQDNAuthBypassEnabled()) {
|
||||||
Security.checkApiCallAllowed(request);
|
Security.checkApiCallAllowed(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.download(service, name, identifier, filepath, rebuild);
|
return this.download(service, name, identifier, filepath, rebuild, async, attempts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1027,14 +1031,23 @@ public class ArbitraryResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpServletResponse download(Service service, String name, String identifier, String filepath, boolean rebuild) {
|
private HttpServletResponse download(Service service, String name, String identifier, String filepath, boolean rebuild, boolean async, Integer maxAttempts) {
|
||||||
|
|
||||||
ArbitraryDataReader arbitraryDataReader = new ArbitraryDataReader(name, ArbitraryDataFile.ResourceIdType.NAME, service, identifier);
|
ArbitraryDataReader arbitraryDataReader = new ArbitraryDataReader(name, ArbitraryDataFile.ResourceIdType.NAME, service, identifier);
|
||||||
try {
|
try {
|
||||||
|
|
||||||
int attempts = 0;
|
int attempts = 0;
|
||||||
|
if (maxAttempts == null) {
|
||||||
|
maxAttempts = 5;
|
||||||
|
}
|
||||||
|
|
||||||
// Loop until we have data
|
// Loop until we have data
|
||||||
|
if (async) {
|
||||||
|
// Asynchronous
|
||||||
|
arbitraryDataReader.loadAsynchronously(false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Synchronous
|
||||||
while (!Controller.isStopping()) {
|
while (!Controller.isStopping()) {
|
||||||
attempts++;
|
attempts++;
|
||||||
if (!arbitraryDataReader.isBuilding()) {
|
if (!arbitraryDataReader.isBuilding()) {
|
||||||
@ -1042,7 +1055,7 @@ public class ArbitraryResource {
|
|||||||
arbitraryDataReader.loadSynchronously(rebuild);
|
arbitraryDataReader.loadSynchronously(rebuild);
|
||||||
break;
|
break;
|
||||||
} catch (MissingDataException e) {
|
} catch (MissingDataException e) {
|
||||||
if (attempts > 5) {
|
if (attempts > maxAttempts) {
|
||||||
// Give up after 5 attempts
|
// Give up after 5 attempts
|
||||||
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_CRITERIA, "Data unavailable. Please try again later.");
|
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_CRITERIA, "Data unavailable. Please try again later.");
|
||||||
}
|
}
|
||||||
@ -1050,7 +1063,13 @@ public class ArbitraryResource {
|
|||||||
}
|
}
|
||||||
Thread.sleep(3000L);
|
Thread.sleep(3000L);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
java.nio.file.Path outputPath = arbitraryDataReader.getFilePath();
|
java.nio.file.Path outputPath = arbitraryDataReader.getFilePath();
|
||||||
|
if (outputPath == null) {
|
||||||
|
// Assume the resource doesn't exist
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.FILE_NOT_FOUND, "File not found");
|
||||||
|
}
|
||||||
|
|
||||||
if (filepath == null || filepath.isEmpty()) {
|
if (filepath == null || filepath.isEmpty()) {
|
||||||
// No file path supplied - so check if this is a single file resource
|
// No file path supplied - so check if this is a single file resource
|
||||||
|
@ -122,9 +122,19 @@ public class ArbitraryDataReader {
|
|||||||
* This adds the build task to a queue, and the result will be cached when complete
|
* This adds the build task to a queue, and the result will be cached when complete
|
||||||
* To check the status of the build, periodically call isCachedDataAvailable()
|
* To check the status of the build, periodically call isCachedDataAvailable()
|
||||||
* Once it returns true, you can then use getFilePath() to access the data itself.
|
* Once it returns true, you can then use getFilePath() to access the data itself.
|
||||||
|
*
|
||||||
|
* @param overwrite - set to true to force rebuild an existing cache
|
||||||
* @return true if added or already present in queue; false if not
|
* @return true if added or already present in queue; false if not
|
||||||
*/
|
*/
|
||||||
public boolean loadAsynchronously() {
|
public boolean loadAsynchronously(boolean overwrite) {
|
||||||
|
ArbitraryDataCache cache = new ArbitraryDataCache(this.uncompressedPath, overwrite,
|
||||||
|
this.resourceId, this.resourceIdType, this.service, this.identifier);
|
||||||
|
if (cache.isCachedDataAvailable()) {
|
||||||
|
// Use cached data
|
||||||
|
this.filePath = this.uncompressedPath;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return ArbitraryDataBuildManager.getInstance().addToBuildQueue(this.createQueueItem());
|
return ArbitraryDataBuildManager.getInstance().addToBuildQueue(this.createQueueItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ public class ArbitraryDataRenderer {
|
|||||||
if (!arbitraryDataReader.isCachedDataAvailable()) {
|
if (!arbitraryDataReader.isCachedDataAvailable()) {
|
||||||
// If async is requested, show a loading screen whilst build is in progress
|
// If async is requested, show a loading screen whilst build is in progress
|
||||||
if (async) {
|
if (async) {
|
||||||
arbitraryDataReader.loadAsynchronously();
|
arbitraryDataReader.loadAsynchronously(false);
|
||||||
return this.getLoadingResponse(service, resourceId);
|
return this.getLoadingResponse(service, resourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user