Skip to content

Commit

Permalink
Merge pull request #118 from aodn/features/5277-avoid-flooding-system
Browse files Browse the repository at this point in the history
Avoid flooding and cause geonetwork too busy error
  • Loading branch information
utas-raymondng authored Aug 28, 2024
2 parents 45e1728 + 50ec435 commit effa6b6
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package au.org.aodn.esindexer.configuration;

import au.org.aodn.esindexer.utils.VocabsUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@Configuration
@EnableRetry
@EnableAsync
public class IndexerConfig {
/**
* We need to create component here because we do not want to run test with real http connection
Expand All @@ -20,4 +26,22 @@ public class IndexerConfig {
public VocabsUtils createVocabsUtils() {
return new VocabsUtils();
}
/**
* This executor is used to limit the number of concurrent call to index metadata so not to flood the
* geonetwork. This is useful because the geonetwork do not care about re-index call it invoke, hence
* the elastic of geonetwork may be flooded by its re-index call.
* @return - An async task executor
*/
@Bean(name = "asyncIndexMetadata")
public Executor taskExecutor(
@Value("${app.indexing.pool.core:5}") Integer coreSize,
@Value("${app.indexing.pool.max:10}") Integer coreMax) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(coreSize); // Number of concurrent threads
executor.setMaxPoolSize(coreMax); // Max number of concurrent threads
executor.setQueueCapacity(5000); // Size of the queue
executor.setThreadNamePrefix("Async-");
executor.initialize();
return executor;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,6 @@ public class IndexerController {
@Autowired
GeoNetworkService geonetworkResourceService;

// @GetMapping(path="/gn_records/{uuid}", produces = "application/json")
// @Operation(description = "Get a document from GeoNetwork Elasticsearch by UUID")
// public ResponseEntity getMetadataRecordFromGeoNetworkElasticsearchByUUID(@PathVariable("uuid") String uuid) {
// logger.info("getting a document by UUID: " + uuid);
// JSONObject response = geonetworkResourceService.searchMetadataBy(uuid);
// return ResponseEntity.status(HttpStatus.OK).body(response.toString());
// }

@GetMapping(path="/records/{uuid}", produces = "application/json")
@Operation(description = "Get a document from GeoNetwork by UUID directly - JSON format response")
public ResponseEntity<String> getMetadataRecordFromGeoNetworkByUUID(@PathVariable("uuid") String uuid) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.List;

public interface IndexerService {
// Event call back to notify caller, this avoid gateway timeout as we have message back to browser
interface Callback {
void onProgress(Object update);
void onComplete(Object result);
Expand All @@ -20,4 +21,6 @@ interface Callback {
ResponseEntity<String> deleteDocumentByUUID(String uuid) throws IOException;
List<BulkResponse> indexAllMetadataRecordsFromGeoNetwork(boolean confirm, Callback callback) throws IOException;
Hit<ObjectNode> getDocumentByUUID(String uuid) throws IOException;
boolean isMetadataPublished(String uuid);
boolean isGeoNetworkInstanceReinstalled(long portalIndexDocumentsCount);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import au.org.aodn.esindexer.configuration.AppConstants;
import au.org.aodn.esindexer.exception.*;
import au.org.aodn.esindexer.utils.JaxbUtils;
import au.org.aodn.esindexer.utils.StringUtil;
import au.org.aodn.metadata.iso19115_3_2018.MDMetadataType;
import au.org.aodn.stac.model.RecordSuggest;
import au.org.aodn.stac.model.StacCollectionModel;
Expand All @@ -29,6 +28,7 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
Expand Down Expand Up @@ -101,15 +101,17 @@ public Hit<ObjectNode> getDocumentByUUID(String uuid) throws IOException {
}
}

protected boolean isGeoNetworkInstanceReinstalled(long portalIndexDocumentsCount) {
@Override
public boolean isGeoNetworkInstanceReinstalled(long portalIndexDocumentsCount) {
/**
* compare if GeoNetwork has 1 only metadata (the recently added one which triggered the indexer)
* and the portal index has more than 0 documents (the most recent metadata yet indexed to portal index at this point)
*/
return geoNetworkResourceService.isMetadataRecordsCountLessThan(2) && portalIndexDocumentsCount > 0;
}

protected boolean isMetadataPublished(String uuid) {
@Override
public boolean isMetadataPublished(String uuid) {
/* read for the published status from GN Elasticsearch index, the flag is not part of the XML body */
try {
geoNetworkResourceService.searchRecordBy(uuid);
Expand Down Expand Up @@ -170,7 +172,13 @@ protected StacCollectionModel getMappedMetadataValues(String metadataValues) thr

return stacCollectionModel;
}

/**
* Use to index a particular UUID, the async is used to limit the number of same function call to avoid flooding
* the system.
* @param metadataValues - The XML of the metadata
* @return - The STAC doc in string format.
*/
@Async("asyncIndexMetadata")
public ResponseEntity<String> indexMetadata(String metadataValues) {
try {
StacCollectionModel mappedMetadataValues = this.getMappedMetadataValues(metadataValues);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class IndexerServiceTests extends BaseTestClass {
protected GeoNetworkServiceImpl geoNetworkService;

@Autowired
protected IndexerServiceImpl indexerService;
protected IndexerService indexerService;

@Autowired
protected ObjectMapper indexerObjectMapper;
Expand Down
4 changes: 4 additions & 0 deletions indexer/src/test/resources/application-test.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Client calling the Indexer API must provide this token in the Authorization header
app:
indexing:
pool:
core: 1
max: 1
http:
authToken: sample-auth-token

Expand Down

0 comments on commit effa6b6

Please sign in to comment.