forked from Qortal/qortal
Fixed issues relating to using a separate repository instance when determining the latest status of a resource.
This commit is contained in:
parent
633f73aa86
commit
f5f82dc3f6
@ -3,6 +3,8 @@ package org.qortal.api.gateway.resource;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.qortal.api.ApiError;
|
||||
import org.qortal.api.ApiExceptionFactory;
|
||||
import org.qortal.api.Security;
|
||||
import org.qortal.arbitrary.ArbitraryDataFile;
|
||||
import org.qortal.arbitrary.ArbitraryDataFile.ResourceIdType;
|
||||
@ -11,6 +13,9 @@ import org.qortal.arbitrary.ArbitraryDataRenderer;
|
||||
import org.qortal.arbitrary.ArbitraryDataResource;
|
||||
import org.qortal.arbitrary.misc.Service;
|
||||
import org.qortal.data.arbitrary.ArbitraryResourceStatus;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
import org.qortal.repository.RepositoryManager;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -31,30 +36,6 @@ public class GatewayResource {
|
||||
@Context HttpServletResponse response;
|
||||
@Context ServletContext context;
|
||||
|
||||
/**
|
||||
* We need to allow resource status checking (and building) via the gateway, as the node's API port
|
||||
* may not be forwarded and will almost certainly not be authenticated. Since gateways allow for
|
||||
* all resources to be loaded except those that are blocked, there is no need for authentication.
|
||||
*/
|
||||
@GET
|
||||
@Path("/arbitrary/resource/status/{service}/{name}")
|
||||
public ArbitraryResourceStatus getDefaultResourceStatus(@PathParam("service") Service service,
|
||||
@PathParam("name") String name,
|
||||
@QueryParam("build") Boolean build) {
|
||||
|
||||
return this.getStatus(service, name, null, build);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/arbitrary/resource/status/{service}/{name}/{identifier}")
|
||||
public ArbitraryResourceStatus getResourceStatus(@PathParam("service") Service service,
|
||||
@PathParam("name") String name,
|
||||
@PathParam("identifier") String identifier,
|
||||
@QueryParam("build") Boolean build) {
|
||||
|
||||
return this.getStatus(service, name, identifier, build);
|
||||
}
|
||||
|
||||
private ArbitraryResourceStatus getStatus(Service service, String name, String identifier, Boolean build) {
|
||||
|
||||
// If "build=true" has been specified in the query string, build the resource before returning its status
|
||||
@ -69,8 +50,13 @@ public class GatewayResource {
|
||||
}
|
||||
}
|
||||
|
||||
ArbitraryDataResource resource = new ArbitraryDataResource(name, ResourceIdType.NAME, service, identifier);
|
||||
return resource.getStatus();
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
ArbitraryDataResource resource = new ArbitraryDataResource(name, ResourceIdType.NAME, service, identifier);
|
||||
return resource.getStatus(repository);
|
||||
|
||||
} catch (DataException e) {
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -531,8 +531,14 @@ public class ArbitraryResource {
|
||||
@PathParam("identifier") String identifier) {
|
||||
|
||||
Security.checkApiCallAllowed(request);
|
||||
ArbitraryDataResource resource = new ArbitraryDataResource(name, ResourceIdType.NAME, service, identifier);
|
||||
return resource.delete(false);
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
ArbitraryDataResource resource = new ArbitraryDataResource(name, ResourceIdType.NAME, service, identifier);
|
||||
return resource.delete(repository, false);
|
||||
|
||||
} catch (DataException e) {
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
|
@ -59,28 +59,34 @@ public class ArbitraryDataResource {
|
||||
}
|
||||
|
||||
public ArbitraryResourceStatus getStatusAndUpdateCache(boolean updateCache) {
|
||||
ArbitraryResourceStatus arbitraryResourceStatus = this.getStatus();
|
||||
ArbitraryResourceStatus arbitraryResourceStatus = null;
|
||||
|
||||
if (updateCache) {
|
||||
// Update cache if possible
|
||||
ArbitraryResourceStatus.Status status = arbitraryResourceStatus != null ? arbitraryResourceStatus.getStatus() : null;
|
||||
ArbitraryResourceData arbitraryResourceData = new ArbitraryResourceData(this.service, this.resourceId, this.identifier);
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
arbitraryResourceStatus = this.getStatus(repository);
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
if (updateCache) {
|
||||
// Update cache if possible
|
||||
ArbitraryResourceStatus.Status status = arbitraryResourceStatus != null ? arbitraryResourceStatus.getStatus() : null;
|
||||
ArbitraryResourceData arbitraryResourceData = new ArbitraryResourceData(this.service, this.resourceId, this.identifier);
|
||||
repository.getArbitraryRepository().setStatus(arbitraryResourceData, status);
|
||||
repository.saveChanges();
|
||||
|
||||
} catch (DataException e) {
|
||||
LOGGER.info("Unable to update status cache for resource {}: {}", arbitraryResourceData, e.getMessage());
|
||||
}
|
||||
} catch (DataException e) {
|
||||
LOGGER.info("Unable to update status cache for resource {}: {}", this.toString(), e.getMessage());
|
||||
}
|
||||
|
||||
return arbitraryResourceStatus;
|
||||
}
|
||||
|
||||
public ArbitraryResourceStatus getStatus() {
|
||||
/**
|
||||
* Get current status of resource
|
||||
*
|
||||
* @param repository
|
||||
* @return the resource's status
|
||||
*/
|
||||
public ArbitraryResourceStatus getStatus(Repository repository) {
|
||||
// Calculate the chunk counts
|
||||
this.calculateChunkCounts();
|
||||
this.calculateChunkCounts(repository);
|
||||
|
||||
if (!this.exists) {
|
||||
return new ArbitraryResourceStatus(Status.NOT_PUBLISHED, this.localChunkCount, this.totalChunkCount);
|
||||
@ -111,11 +117,11 @@ public class ArbitraryDataResource {
|
||||
}
|
||||
|
||||
// Check if we have all data locally for this resource
|
||||
if (!this.allFilesDownloaded()) {
|
||||
if (this.isDownloading()) {
|
||||
if (!this.allFilesDownloaded(repository)) {
|
||||
if (this.isDownloading(repository)) {
|
||||
return new ArbitraryResourceStatus(Status.DOWNLOADING, this.localChunkCount, this.totalChunkCount);
|
||||
}
|
||||
else if (this.isDataPotentiallyAvailable()) {
|
||||
else if (this.isDataPotentiallyAvailable(repository)) {
|
||||
return new ArbitraryResourceStatus(Status.PUBLISHED, this.localChunkCount, this.totalChunkCount);
|
||||
}
|
||||
return new ArbitraryResourceStatus(Status.MISSING_DATA, this.localChunkCount, this.totalChunkCount);
|
||||
@ -157,9 +163,9 @@ public class ArbitraryDataResource {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean delete(boolean deleteMetadata) {
|
||||
public boolean delete(Repository repository, boolean deleteMetadata) {
|
||||
try {
|
||||
this.fetchTransactions();
|
||||
this.fetchTransactions(repository);
|
||||
if (this.transactions == null) {
|
||||
return false;
|
||||
}
|
||||
@ -208,7 +214,7 @@ public class ArbitraryDataResource {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean allFilesDownloaded() {
|
||||
private boolean allFilesDownloaded(Repository repository) {
|
||||
// Use chunk counts to speed things up if we can
|
||||
if (this.localChunkCount != null && this.totalChunkCount != null &&
|
||||
this.localChunkCount >= this.totalChunkCount) {
|
||||
@ -216,7 +222,7 @@ public class ArbitraryDataResource {
|
||||
}
|
||||
|
||||
try {
|
||||
this.fetchTransactions();
|
||||
this.fetchTransactions(repository);
|
||||
if (this.transactions == null) {
|
||||
return false;
|
||||
}
|
||||
@ -236,9 +242,14 @@ public class ArbitraryDataResource {
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateChunkCounts() {
|
||||
/**
|
||||
* Calculate chunk counts of a resource
|
||||
*
|
||||
* @param repository optional - a new instance will be created if null
|
||||
*/
|
||||
private void calculateChunkCounts(Repository repository) {
|
||||
try {
|
||||
this.fetchTransactions();
|
||||
this.fetchTransactions(repository);
|
||||
if (this.transactions == null) {
|
||||
this.exists = false;
|
||||
this.localChunkCount = 0;
|
||||
@ -263,9 +274,9 @@ public class ArbitraryDataResource {
|
||||
} catch (DataException e) {}
|
||||
}
|
||||
|
||||
private boolean isRateLimited() {
|
||||
private boolean isRateLimited(Repository repository) {
|
||||
try {
|
||||
this.fetchTransactions();
|
||||
this.fetchTransactions(repository);
|
||||
if (this.transactions == null) {
|
||||
return true;
|
||||
}
|
||||
@ -289,9 +300,9 @@ public class ArbitraryDataResource {
|
||||
* This is only used to give an indication to the user of progress
|
||||
* @return - whether data might be available on the network
|
||||
*/
|
||||
private boolean isDataPotentiallyAvailable() {
|
||||
private boolean isDataPotentiallyAvailable(Repository repository) {
|
||||
try {
|
||||
this.fetchTransactions();
|
||||
this.fetchTransactions(repository);
|
||||
if (this.transactions == null) {
|
||||
return false;
|
||||
}
|
||||
@ -324,9 +335,9 @@ public class ArbitraryDataResource {
|
||||
* This is only used to give an indication to the user of progress
|
||||
* @return - whether we are trying to download the resource
|
||||
*/
|
||||
private boolean isDownloading() {
|
||||
private boolean isDownloading(Repository repository) {
|
||||
try {
|
||||
this.fetchTransactions();
|
||||
this.fetchTransactions(repository);
|
||||
if (this.transactions == null) {
|
||||
return false;
|
||||
}
|
||||
@ -357,15 +368,19 @@ public class ArbitraryDataResource {
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void fetchTransactions() throws DataException {
|
||||
/**
|
||||
* Fetch relevant arbitrary transactions for resource
|
||||
*
|
||||
* @param repository
|
||||
* @throws DataException
|
||||
*/
|
||||
private void fetchTransactions(Repository repository) throws DataException {
|
||||
if (this.transactions != null && !this.transactions.isEmpty()) {
|
||||
// Already fetched
|
||||
return;
|
||||
}
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
|
||||
try {
|
||||
// Get the most recent PUT
|
||||
ArbitraryTransactionData latestPut = repository.getArbitraryRepository()
|
||||
.getLatestTransaction(this.resourceId, this.service, ArbitraryTransactionData.Method.PUT, this.identifier);
|
||||
|
@ -407,7 +407,7 @@ public class ArbitraryTransaction extends Transaction {
|
||||
|
||||
// Update status
|
||||
ArbitraryDataResource resource = new ArbitraryDataResource(name, ArbitraryDataFile.ResourceIdType.NAME, service, identifier);
|
||||
ArbitraryResourceStatus arbitraryResourceStatus = resource.getStatus();
|
||||
ArbitraryResourceStatus arbitraryResourceStatus = resource.getStatus(repository);
|
||||
ArbitraryResourceStatus.Status status = arbitraryResourceStatus != null ? arbitraryResourceStatus.getStatus() : null;
|
||||
repository.getArbitraryRepository().setStatus(arbitraryResourceData, status);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user