From 9e302ddda2a15fce23d38be77b2931d1af95e84d Mon Sep 17 00:00:00 2001 From: agazzarini Date: Wed, 15 Apr 2020 09:33:06 +0200 Subject: [PATCH 1/4] [ SEARCH-2187 ] First draft on wrapping callRepository with a Callable statement --- .../alfresco/solr/client/SOLRAPIClient.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/search-services/alfresco-solrclient-lib/src/main/java/org/alfresco/solr/client/SOLRAPIClient.java b/search-services/alfresco-solrclient-lib/src/main/java/org/alfresco/solr/client/SOLRAPIClient.java index 34ed2623d..d5cec7812 100644 --- a/search-services/alfresco-solrclient-lib/src/main/java/org/alfresco/solr/client/SOLRAPIClient.java +++ b/search-services/alfresco-solrclient-lib/src/main/java/org/alfresco/solr/client/SOLRAPIClient.java @@ -25,6 +25,7 @@ */ package org.alfresco.solr.client; +import static java.util.Collections.singletonList; import static java.util.Optional.ofNullable; import java.io.Closeable; @@ -42,6 +43,12 @@ import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.httpclient.AlfrescoHttpClient; @@ -75,6 +82,7 @@ import org.alfresco.util.Pair; import org.apache.commons.codec.EncoderException; import org.apache.commons.codec.net.URLCodec; import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.SimpleHttpConnectionManager; import org.apache.commons.httpclient.util.DateUtil; import org.json.JSONArray; import org.json.JSONException; @@ -1579,6 +1587,58 @@ public class SOLRAPIClient public void close() { repositoryHttpClient.close(); + executor.shutdown(); + } + + final ExecutorService executor = Executors.newSingleThreadExecutor(); + + private JSONObject callRepositoryWithTimeout(String msgId, Request req) throws IOException, AuthenticationException, InterruptedException, TimeoutException, ExecutionException { + List> result = executor.invokeAll(singletonList(() -> { + Response response = null; + LookAheadBufferedReader reader = null; + JSONObject json; + try + { + response = repositoryHttpClient.sendRequest(req); + if (response.getStatus() != HttpStatus.SC_OK) + { + throw new AlfrescoRuntimeException(msgId + " return status:" + response.getStatus()); + } + + reader = new LookAheadBufferedReader(new InputStreamReader(response.getContentAsStream(), StandardCharsets.UTF_8), LOGGER); + json = new JSONObject(new JSONTokener(reader)); + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug(json.toString(3)); + } + return json; + } + catch (JSONException exception) + { + String message = "Received a malformed JSON payload. Request was \"" + + req.getFullUri() + + "Data: " + + ofNullable(reader) + .map(LookAheadBufferedReader::lookAheadAndGetBufferedContent) + .orElse("Not available"); + LOGGER.error(message); + throw exception; + } + finally + { + ofNullable(response).ifPresent(Response::release); + ofNullable(reader).ifPresent(this::silentlyClose); + } + }), 5, TimeUnit.SECONDS); + + Future response = result.iterator().next(); + if(response.isCancelled()) + { + throw new TimeoutException("Request " + req + "has timed out. It has taken more than 5 seconds to respond"); + } + + return response.get(); } private JSONObject callRepository(String msgId, Request req) throws IOException, AuthenticationException From cb50bab3572135b51eb9e5e93176b674ce7f86fe Mon Sep 17 00:00:00 2001 From: agazzarini Date: Wed, 15 Apr 2020 14:26:48 +0200 Subject: [PATCH 2/4] [ SEARCH-2187 ] acquire lock max wait time, configuration property --- .../alfresco/solr/SolrInformationServer.java | 8 ++- .../templates/rerank/conf/solrcore.properties | 2 + .../alfresco/solr/client/SOLRAPIClient.java | 52 ------------------- 3 files changed, 8 insertions(+), 54 deletions(-) diff --git a/search-services/alfresco-search/src/main/java/org/alfresco/solr/SolrInformationServer.java b/search-services/alfresco-search/src/main/java/org/alfresco/solr/SolrInformationServer.java index 7991889a6..f8f617118 100644 --- a/search-services/alfresco-search/src/main/java/org/alfresco/solr/SolrInformationServer.java +++ b/search-services/alfresco-search/src/main/java/org/alfresco/solr/SolrInformationServer.java @@ -296,6 +296,8 @@ public class SolrInformationServer implements InformationServer private String skippingDocsQueryString; private boolean isSkippingDocsInitialized; + private long maxAllowedTimeForAcquiringDbIdLock; + protected enum FTSStatus {New, Dirty, Clean} static class DocListCollector implements Collector, LeafCollector @@ -461,6 +463,8 @@ public class SolrInformationServer implements InformationServer holeRetention = Integer.parseInt(p.getProperty("alfresco.hole.retention", "3600000")); minHash = Boolean.parseBoolean(p.getProperty("alfresco.fingerprint", "true")); + maxAllowedTimeForAcquiringDbIdLock = Long.parseLong(p.getProperty("alfresco.tracker.maxNodeLockMs", "120000")); + dataModel = AlfrescoSolrDataModel.getInstance(); contentStreamLimit = Integer.parseInt(p.getProperty("alfresco.contentStreamLimit", "10000000")); @@ -3182,9 +3186,9 @@ public class SolrInformationServer implements InformationServer // I don't think we are concerned with this exception. } - if (System.currentTimeMillis() - startTime > 120000) + if (System.currentTimeMillis() - startTime > maxAllowedTimeForAcquiringDbIdLock) { - throw new AlfrescoLockException("Unable to acquire lock on nodeId " + id + " after " + 120000 + " msecs."); + throw new AlfrescoLockException("Unable to acquire lock on nodeId " + id + " after " + maxAllowedTimeForAcquiringDbIdLock + " msecs."); } } } diff --git a/search-services/alfresco-search/src/main/resources/solr/instance/templates/rerank/conf/solrcore.properties b/search-services/alfresco-search/src/main/resources/solr/instance/templates/rerank/conf/solrcore.properties index 1d33062d9..b9771edb8 100644 --- a/search-services/alfresco-search/src/main/resources/solr/instance/templates/rerank/conf/solrcore.properties +++ b/search-services/alfresco-search/src/main/resources/solr/instance/templates/rerank/conf/solrcore.properties @@ -30,6 +30,8 @@ alfresco.hole.check.after=300000 alfresco.batch.count=5000 alfresco.recordUnindexedNodes=false +# max time (in msecs) a given tracker instance will try to acquire a lock on a given DBID +alfresco.tracker.maxNodeLockMs=120000 # encryption # none, https diff --git a/search-services/alfresco-solrclient-lib/src/main/java/org/alfresco/solr/client/SOLRAPIClient.java b/search-services/alfresco-solrclient-lib/src/main/java/org/alfresco/solr/client/SOLRAPIClient.java index d5cec7812..760eba485 100644 --- a/search-services/alfresco-solrclient-lib/src/main/java/org/alfresco/solr/client/SOLRAPIClient.java +++ b/search-services/alfresco-solrclient-lib/src/main/java/org/alfresco/solr/client/SOLRAPIClient.java @@ -1587,58 +1587,6 @@ public class SOLRAPIClient public void close() { repositoryHttpClient.close(); - executor.shutdown(); - } - - final ExecutorService executor = Executors.newSingleThreadExecutor(); - - private JSONObject callRepositoryWithTimeout(String msgId, Request req) throws IOException, AuthenticationException, InterruptedException, TimeoutException, ExecutionException { - List> result = executor.invokeAll(singletonList(() -> { - Response response = null; - LookAheadBufferedReader reader = null; - JSONObject json; - try - { - response = repositoryHttpClient.sendRequest(req); - if (response.getStatus() != HttpStatus.SC_OK) - { - throw new AlfrescoRuntimeException(msgId + " return status:" + response.getStatus()); - } - - reader = new LookAheadBufferedReader(new InputStreamReader(response.getContentAsStream(), StandardCharsets.UTF_8), LOGGER); - json = new JSONObject(new JSONTokener(reader)); - - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug(json.toString(3)); - } - return json; - } - catch (JSONException exception) - { - String message = "Received a malformed JSON payload. Request was \"" + - req.getFullUri() + - "Data: " - + ofNullable(reader) - .map(LookAheadBufferedReader::lookAheadAndGetBufferedContent) - .orElse("Not available"); - LOGGER.error(message); - throw exception; - } - finally - { - ofNullable(response).ifPresent(Response::release); - ofNullable(reader).ifPresent(this::silentlyClose); - } - }), 5, TimeUnit.SECONDS); - - Future response = result.iterator().next(); - if(response.isCancelled()) - { - throw new TimeoutException("Request " + req + "has timed out. It has taken more than 5 seconds to respond"); - } - - return response.get(); } private JSONObject callRepository(String msgId, Request req) throws IOException, AuthenticationException From abc0cb2195b8cd51bab497bdec454adcc4175d32 Mon Sep 17 00:00:00 2001 From: agazzarini Date: Wed, 15 Apr 2020 14:29:34 +0200 Subject: [PATCH 3/4] [ SEARCH-2187 ] removed unused import on SOLRAPIClient --- .../alfresco/solr/client/SOLRAPIClient.java | 49 ++++++++----------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/search-services/alfresco-solrclient-lib/src/main/java/org/alfresco/solr/client/SOLRAPIClient.java b/search-services/alfresco-solrclient-lib/src/main/java/org/alfresco/solr/client/SOLRAPIClient.java index 760eba485..b141929d4 100644 --- a/search-services/alfresco-solrclient-lib/src/main/java/org/alfresco/solr/client/SOLRAPIClient.java +++ b/search-services/alfresco-solrclient-lib/src/main/java/org/alfresco/solr/client/SOLRAPIClient.java @@ -25,31 +25,9 @@ */ package org.alfresco.solr.client; -import static java.util.Collections.singletonList; -import static java.util.Optional.ofNullable; - -import java.io.Closeable; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.httpclient.AlfrescoHttpClient; import org.alfresco.httpclient.AuthenticationException; @@ -82,7 +60,6 @@ import org.alfresco.util.Pair; import org.apache.commons.codec.EncoderException; import org.apache.commons.codec.net.URLCodec; import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.httpclient.SimpleHttpConnectionManager; import org.apache.commons.httpclient.util.DateUtil; import org.json.JSONArray; import org.json.JSONException; @@ -92,9 +69,23 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.extensions.surf.util.URLEncoder; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import static java.util.Optional.ofNullable; // TODO error handling, including dealing with a repository that is not responsive (ConnectException in sendRemoteRequest) // TODO get text content transform status handling From 527586fa3fdac18b8e9e611e66a3311e9eafb33c Mon Sep 17 00:00:00 2001 From: agazzarini Date: Wed, 15 Apr 2020 14:41:31 +0200 Subject: [PATCH 4/4] [ SEARCH-2187 ] same configuration property on noRerank template --- .../solr/instance/templates/noRerank/conf/solrcore.properties | 3 +++ .../solr/instance/templates/rerank/conf/solrcore.properties | 1 + 2 files changed, 4 insertions(+) diff --git a/search-services/alfresco-search/src/main/resources/solr/instance/templates/noRerank/conf/solrcore.properties b/search-services/alfresco-search/src/main/resources/solr/instance/templates/noRerank/conf/solrcore.properties index 189c181e0..33b09117e 100644 --- a/search-services/alfresco-search/src/main/resources/solr/instance/templates/noRerank/conf/solrcore.properties +++ b/search-services/alfresco-search/src/main/resources/solr/instance/templates/noRerank/conf/solrcore.properties @@ -30,6 +30,9 @@ alfresco.hole.check.after=300000 alfresco.batch.count=5000 alfresco.recordUnindexedNodes=false +# max time (in msecs) a given tracker instance will try to acquire a lock on a given DBID +alfresco.tracker.maxNodeLockMs=120000 + # encryption # none, https diff --git a/search-services/alfresco-search/src/main/resources/solr/instance/templates/rerank/conf/solrcore.properties b/search-services/alfresco-search/src/main/resources/solr/instance/templates/rerank/conf/solrcore.properties index b9771edb8..6209e74cf 100644 --- a/search-services/alfresco-search/src/main/resources/solr/instance/templates/rerank/conf/solrcore.properties +++ b/search-services/alfresco-search/src/main/resources/solr/instance/templates/rerank/conf/solrcore.properties @@ -32,6 +32,7 @@ alfresco.recordUnindexedNodes=false # max time (in msecs) a given tracker instance will try to acquire a lock on a given DBID alfresco.tracker.maxNodeLockMs=120000 + # encryption # none, https