Skip to content

Commit

Permalink
Merge pull request #9 from xenit-eu/DOCKER-437
Browse files Browse the repository at this point in the history
DOCKER-437 add env variables to disable different validation in solr actuators
  • Loading branch information
thijslemmens authored Oct 4, 2023
2 parents 5a22f2b + cc0d017 commit 0aac492
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 43 deletions.
22 changes: 17 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

Readiness endpoint to be used as load balancer check.

Solr is considered ready when it is "almost" ready with tracking alfresco.
This is computed subjectivelly using the lag reported by the SUMMARY screen: solr is ready when the lag is smaller than MAX_LAG.
also it is following the restore status provided by the replication handler
Solr is considered ready when it is "almost" ready with tracking alfresco. and that is done in 3 steps of validation :

* `TX_LAG_VALIDATION` by calculating the Tx lag and verifying that it is smaller than MAX_LAG.
* `CHANGE_SET_LAG_VALIDATION` by calculating the ChangeSet lag and verifying that it is smaller than MAX_LAG.
* `REPLICATION_VALIDATION` by following the restore status provided by the replication handler.

The script is available at:

Expand All @@ -18,9 +20,19 @@ In order to check the health of solr server, the out-of-the-box ping handler can

Status code is to be used for the health check: 200 if ready or 503 if not yet ready.

The output of the script offers additional information if being ready as well as information about current tracker status (when parameter info is appended to the query).
The output of the script offers additional information if being ready as well as information about current tracker
status (when parameter info is appended to the query).

* the MAX_LAG can be set via environment variable `READINESS_MAX_LAG` it is set to default to 1800000 in milliseconds (
30 minutes).
* the `TX_LAG_VALIDATION` can be Disabled via environment variable `READINESS_TX_LAG_VALIDATION_ENABLED` it is set to
default to true.

* the `CHANGE_SET_LAG_VALIDATION` can be Disabled via environment variable `READINESS_CHANGE_SET_LAG_VALIDATION_ENABLED`
it is set to default to true.

the MAX_LAG can be set via environment variable `READINESS_MAX_LAG` it is set to default to 1800000 in milliseconds (30 minutes).
* the `REPLICATION_VALIDATION` can be Disabled via environment variable `READINESS_REPLICATION_VALIDATION_ENABLED` it is
set to default to true.

## How to run integration tests

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ plugins {
id 'eu.xenit.docker-compose' version '5.4.0' apply false
}
subprojects {
def baseVersion = System.getenv("TAG_VERSION") ?: 'v0.0.5'
def baseVersion = System.getenv("TAG_VERSION") ?: 'v0.0.7'
version = baseVersion[1..baseVersion.length() - 1]
ext {
junitJupiterVersion = '5.4.2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,48 @@
public class ReadinessConfig {

public static final String READINESS_MAX_LAG = "READINESS_MAX_LAG";
public static final String READINESS_TX_LAG_VALIDATION_ENABLED = "READINESS_TX_LAG_VALIDATION_ENABLED";
public static final String READINESS_CHANGE_SET_LAG_VALIDATION_ENABLED = "READINESS_CHANGE_SET_LAG_VALIDATION_ENABLED";
public static final String READINESS_REPLICATION_VALIDATION_ENABLED = "READINESS_REPLICATION_VALIDATION_ENABLED";

public long getMaxLag() {
return maxLag;
}

private final long maxLag;
private final boolean txValidationEnabled;

public boolean isTxValidationEnabled() {
return txValidationEnabled;
}

public boolean isChangeSetValidationEnabled() {
return changeSetValidationEnabled;
}

public boolean isReplicationValidationEnabled() {
return replicationValidationEnabled;
}

private final boolean changeSetValidationEnabled;
private final boolean replicationValidationEnabled;

public ReadinessConfig() {
Long tmpMaxLag = getLongConfig(READINESS_MAX_LAG);
if (tmpMaxLag == null) {
this.maxLag = 1800000L;
} else {
this.maxLag = tmpMaxLag;
}
maxLag = getLongConfig(READINESS_MAX_LAG, 1800000L);
txValidationEnabled = getBooleanConfig(READINESS_TX_LAG_VALIDATION_ENABLED, true);
changeSetValidationEnabled = getBooleanConfig(READINESS_CHANGE_SET_LAG_VALIDATION_ENABLED, true);
replicationValidationEnabled = getBooleanConfig(READINESS_REPLICATION_VALIDATION_ENABLED, true);
}
private static Long getLongConfig(String property) {

private static long getLongConfig(String property, long defaultValue) {
String envProp = System.getenv().get(property);
if (envProp == null || envProp.isEmpty()) return null;
if (envProp == null || envProp.isEmpty()) return defaultValue;
return Long.parseLong(envProp);
}

private static boolean getBooleanConfig(String property, boolean defaultValue) {
String envProp = System.getenv().get(property);
if (envProp == null || envProp.isEmpty()) return defaultValue;
return Boolean.TRUE.equals(Boolean.parseBoolean(envProp));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,15 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) {
.getCoreContainer()
.getMultiCoreHandler();
boolean setInfo = req.getParams().get("info") != null;
checkTransactionResponse(setInfo, rsp,
coreAdminHandler.getTrackerRegistry(),
solrCore.getName());

checkTransactionResponse(setInfo, rsp, coreAdminHandler.getTrackerRegistry(), solrCore.getName());

checkReplicationHandler(setInfo, rsp);

} catch (SolrException e) {
rsp.add(READY, DOWN);
rsp.setException(e);
log.error("solr readiness probe failed with status :'{}' and message: '{}' ",
e.code(),
e.getMessage());
log.error("solr readiness probe failed with status :'{}' and message: '{}' ", e.code(), e.getMessage());

return;
} catch (Exception e) {
Expand All @@ -69,48 +66,69 @@ private void checkTransactionResponse(boolean setInfo,
SolrQueryResponse rsp,
TrackerRegistry trackerRegistry,
String coreName) {
MetadataTracker metadataTracker = trackerRegistry.getTrackerForCore(coreName, MetadataTracker.class);
AclTracker aclTracker = trackerRegistry.getTrackerForCore(coreName, AclTracker.class);

checkTxResponse(setInfo, rsp, trackerRegistry, coreName);
checkChangeSetResponse(setInfo, rsp, trackerRegistry, coreName);
}

private void checkTxResponse(boolean setInfo,
SolrQueryResponse rsp, TrackerRegistry trackerRegistry,
String coreName) {
if (!config.isTxValidationEnabled()) return;

MetadataTracker metadataTracker = trackerRegistry.getTrackerForCore(coreName, MetadataTracker.class);
TrackerState metadataTrackerState = metadataTracker.getTrackerState();
TrackerState aclsTrackerState = aclTracker.getTrackerState();

long lastTxCommitTimeOnServer = metadataTrackerState.getLastTxCommitTimeOnServer();
long lastChangeSetCommitTimeOnServer = aclsTrackerState.getLastChangeSetCommitTimeOnServer();
long lastIndexTxCommitTime = metadataTrackerState.getLastIndexedTxCommitTime();
long txLag = (lastTxCommitTimeOnServer - lastIndexTxCommitTime);

if ((lastTxCommitTimeOnServer == 0 || lastChangeSetCommitTimeOnServer == 0)) {
if (setInfo) {
rsp.add("txLag", txLag);
rsp.add("lastTxCommitTimeOnServer", lastTxCommitTimeOnServer);
rsp.add("lastIndexTxCommitTime", lastIndexTxCommitTime);
}
if (lastTxCommitTimeOnServer == 0) {
throw new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE,
"Solr did not yet get latest values from alfresco server");
"Solr did not yet get latest Tx values from alfresco server");
}
if (txLag >= config.getMaxLag()) {
throw new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE,
MessageFormat.format("Tx lag is larger than permitted: txLag={0}, MAX_LAG={1}"
, txLag, config.getMaxLag()));
}

checkMaxLag(setInfo, rsp,
lastTxCommitTimeOnServer,
lastChangeSetCommitTimeOnServer,
metadataTrackerState.getLastIndexedTxCommitTime(),
aclsTrackerState.getLastIndexedChangeSetCommitTime());
}

private void checkMaxLag(boolean setInfo, SolrQueryResponse rsp,
long lastTxCommitTimeOnServer,
long lastChangeSetCommitTimeOnServer,
long lastIndexTxCommitTime,
long lastIndexChangeSetCommitTime) {
long txLag = (lastTxCommitTimeOnServer - lastIndexTxCommitTime);
private void checkChangeSetResponse(boolean setInfo,
SolrQueryResponse rsp,
TrackerRegistry trackerRegistry,
String coreName) {
if (!config.isChangeSetValidationEnabled()) return;
AclTracker aclTracker = trackerRegistry.getTrackerForCore(coreName, AclTracker.class);
TrackerState aclsTrackerState = aclTracker.getTrackerState();

long lastChangeSetCommitTimeOnServer = aclsTrackerState.getLastChangeSetCommitTimeOnServer();
long lastIndexChangeSetCommitTime = aclsTrackerState.getLastIndexedChangeSetCommitTime();
long changeSetLag = (lastChangeSetCommitTimeOnServer - lastIndexChangeSetCommitTime);

if (setInfo) {
rsp.add("txLag", txLag);
rsp.add("lastTxCommitTimeOnServer", lastTxCommitTimeOnServer);
rsp.add("changeSetLag", changeSetLag);
rsp.add("lastChangeSetCommitTimeOnServer", lastChangeSetCommitTimeOnServer);
rsp.add("lastIndexChangeSetCommitTime", lastIndexChangeSetCommitTime);
}
if (lastChangeSetCommitTimeOnServer == 0) {
throw new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE,
"Solr did not yet get latest change set values from alfresco server");
}
if (txLag >= config.getMaxLag() || changeSetLag >= config.getMaxLag()) {
if (changeSetLag >= config.getMaxLag()) {
throw new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE,
MessageFormat.format("Lag is larger than permitted: txLag={0}, changeSetLag={1}, MAX_LAG={2}"
, txLag, changeSetLag, config.getMaxLag()));
MessageFormat.format("Change set lag is larger than permitted: changeSetLag={0}, MAX_LAG={1}"
, changeSetLag, config.getMaxLag()));
}
}

private void checkReplicationHandler(boolean setInfo, SolrQueryResponse rsp) throws Exception {
if (!config.isReplicationValidationEnabled()) return;
SolrRequestHandler handler = core.getRequestHandler(ReplicationHandler.PATH);
RequestHandlerBase replicationHandler = (RequestHandlerBase) handler;
NamedList<Object> query = new SimpleOrderedMap<>();
Expand Down

0 comments on commit 0aac492

Please sign in to comment.