From c1c3e919c6f1cf7225920ee5d28d958ead04b6f3 Mon Sep 17 00:00:00 2001
From: hechmi-dammak-xenit
<107396375+hechmi-dammak-xenit@users.noreply.github.com>
Date: Thu, 9 Mar 2023 15:25:19 +0100
Subject: [PATCH] DOCKER-431 add backup restore status validation for readiness
* DOCKER-431 remove solr4 support and update gradle
* DOCKER-431 add backup restore status validation for readiness
---
.github/workflows/ci.yml | 57 +
Jenkinsfile | 39 -
README.md | 3 +
build.gradle | 23 +-
gradle/wrapper/gradle-wrapper.properties | 2 +-
integration-tests/build.gradle | 50 +-
integration-tests/solr4/overload.gradle | 7 -
integration-tests/solr6/overload.gradle | 6 +-
.../integrationtesting/SolrSmokeTests.java | 56 +-
.../test/resources/compose/docker-compose.yml | 13 +-
.../src/test/resources/solr4/solrconfig.xml | 1980 -----------------
publish.gradle | 47 +-
settings.gradle | 2 +-
solr-actuators/build.gradle | 9 +-
.../actuators/handler/ReadinessConfig.java | 26 +
.../actuators/handler/ReadinessHandler.java | 162 +-
16 files changed, 281 insertions(+), 2201 deletions(-)
create mode 100644 .github/workflows/ci.yml
delete mode 100644 Jenkinsfile
delete mode 100644 integration-tests/solr4/overload.gradle
delete mode 100644 integration-tests/src/test/resources/solr4/solrconfig.xml
create mode 100644 solr-actuators/src/main/java/eu/xenit/actuators/handler/ReadinessConfig.java
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..4e859fb
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,57 @@
+name: build
+on:
+ push:
+ workflow_dispatch:
+env:
+ ORG_GRADLE_PROJECT_alfresco_nexus_username: ${{ secrets.ALFRESCO_NEXUS_USERNAME }}
+ ORG_GRADLE_PROJECT_alfresco_nexus_password: ${{ secrets.ALFRESCO_NEXUS_PASSWORD }}
+jobs:
+ integration-tests:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+ - uses: actions/setup-java@v1
+ with:
+ java-version: 11
+ - name: Login to Docker
+ run: |
+ echo "${{ secrets.CLOUDSMITH_APIKEY }}" | docker login private.docker.xenit.eu --username "${{ secrets.CLOUDSMITH_USER }}" --password-stdin
+ - name: Test
+ uses: gradle/gradle-build-action@v2
+ with:
+ cache-read-only: false
+ arguments: |
+ integrationTest
+ - name: Upload Test Artifact
+ if: success() || failure()
+ uses: actions/upload-artifact@v3
+ with:
+ name: test-result
+ path: /home/runner/work/**/build/reports
+ retention-days: 2
+ publish:
+ needs: [ integration-tests ]
+ runs-on: ubuntu-latest
+ if: ${{ startsWith(github.ref, 'refs/tags/v') }}
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+ - uses: actions/setup-java@v1
+ with:
+ java-version: 11
+ - name: Add TAG_VERSION env property
+ run: echo "TAG_VERSION=`echo ${GITHUB_REF#refs/tags/}`" >> $GITHUB_ENV
+ - name: Publish
+ uses: gradle/gradle-build-action@v2
+ env:
+ ORG_GRADLE_PROJECT_signingKey: ${{ secrets.MAVEN_CENTRAL_GPG_KEY }}
+ ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.MAVEN_CENTRAL_GPG_PASSWORD }}
+ ORG_GRADLE_PROJECT_sonatype_username: ${{ secrets.SONATYPE_S01_USERNAME }}
+ ORG_GRADLE_PROJECT_sonatype_password: ${{ secrets.SONATYPE_S01_PASSWORD }}
+ with:
+ cache-read-only: false
+ arguments: |
+ publish -PsigningKeyId=CDE3528F -i
diff --git a/Jenkinsfile b/Jenkinsfile
deleted file mode 100644
index 3684162..0000000
--- a/Jenkinsfile
+++ /dev/null
@@ -1,39 +0,0 @@
-pipeline {
- agent any
-
- stages {
- stage("Integration test") {
- steps {
- sh "./gradlew integrationTest"
- }
- }
-
-
- stage('Publish') {
- when {
- anyOf {
- branch "master*"
- branch "release*"
- }
- }
- environment {
- SONATYPE_CREDENTIALS = credentials('sonatype')
- GPGPASSPHRASE = credentials('gpgpassphrase')
- }
- steps {
- script {
- sh "./gradlew publish -Ppublish_username=${SONATYPE_CREDENTIALS_USR} -Ppublish_password=${SONATYPE_CREDENTIALS_PSW} -PkeyId=DF8285F0 -Ppassword=${GPGPASSPHRASE} -PsecretKeyRingFile=/var/jenkins_home/secring.gpg"
- }
- }
- }
- }
-
- post {
- always {
- sh "./gradlew composeDownForced"
- script {
- junit '**/build/**/TEST-*.xml'
- }
- }
- }
-}
diff --git a/README.md b/README.md
index b5877ec..75dfa4a 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,7 @@ 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
The script is available at:
@@ -19,6 +20,8 @@ Status code is to be used for the health check: 200 if ready or 503 if not yet r
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).
+
## How to run integration tests
./gradlew integrationTest
diff --git a/build.gradle b/build.gradle
index 6266d10..00e0316 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,16 +1,21 @@
plugins {
- id 'eu.xenit.docker' version '5.1.1' apply false
- id 'eu.xenit.docker-compose' version '5.1.1' apply false
- id 'de.marcphilipp.nexus-publish' version '0.4.0' apply false
+ id 'eu.xenit.docker' version '5.4.0' apply false
+ id 'eu.xenit.docker-compose' version '5.4.0' apply false
+}
+def copyPropertyValueIfExists(sourcePropertyName, targetPropertyName) {
+ if (project.hasProperty(sourcePropertyName)) {
+ project.ext[targetPropertyName] = project.property(sourcePropertyName)
+ }
}
-
subprojects {
- version = '0.0.3'
+ def baseVersion = System.getenv("TAG_VERSION") ?: 'v0.0.4'
+ version = baseVersion[1..baseVersion.length() - 1]
+
+
+ copyPropertyValueIfExists('alfresco_nexus_username', 'org.alfresco.maven.nexus.username')
+ copyPropertyValueIfExists('alfresco_nexus_password', 'org.alfresco.maven.nexus.password')
- boolean isRelease = System.env.BRANCH_NAME?.startsWith("release")
- if (!isRelease)
- version += "-SNAPSHOT"
repositories {
mavenCentral()
@@ -25,6 +30,4 @@ subprojects {
}
}
}
-
- apply from: "${rootProject.projectDir}/publish.gradle"
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 12d38de..070cb70 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/integration-tests/build.gradle b/integration-tests/build.gradle
index a040d3d..3aaa0a0 100644
--- a/integration-tests/build.gradle
+++ b/integration-tests/build.gradle
@@ -2,7 +2,21 @@ plugins {
id 'java'
id 'idea'
}
-
+dependencies {
+ testImplementation group: 'io.rest-assured', name: 'rest-assured', version: '3.0.1'
+ testImplementation group: 'io.rest-assured', name: 'json-path', version: '3.0.1'
+ testImplementation group: 'io.rest-assured', name: 'rest-assured-common', version: '3.0.1'
+ testImplementation "org.junit.jupiter:junit-jupiter-engine:5.4.2"
+ testImplementation "org.junit.jupiter:junit-jupiter-params:5.4.2"
+ testRuntimeOnly group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '2.3.2'
+}
+test {
+ enabled = false
+ useJUnitPlatform()
+ testLogging {
+ events "passed", "skipped", "failed"
+ }
+}
subprojects {
apply plugin: 'java'
apply plugin: 'eu.xenit.docker'
@@ -11,43 +25,20 @@ subprojects {
description = "Solr ${flavor} with Actuators"
- sourceSets {
- integrationTest {
- java {
- compileClasspath += main.output + test.output
- runtimeClasspath += main.output + test.output
- srcDirs = ["${project.parent.projectDir}/src/test/java"]
- }
- }
- }
-
configurations {
actuatorsJar
- integrationTestCompile.extendsFrom testCompile
- integrationTestRuntime.extendsFrom testRuntime
}
dependencies {
- integrationTestCompile group: 'io.rest-assured', name: 'rest-assured', version: '3.0.1'
- integrationTestCompile group: 'io.rest-assured', name: 'json-path', version: '3.0.1'
- integrationTestCompile group: 'io.rest-assured', name: 'rest-assured-common', version: '3.0.1'
- integrationTestCompile group: 'junit', name: 'junit', version: '4.11'
- integrationTestRuntime group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '2.3.2'
-
-
actuatorsJar project(path: ":solr-actuators", configuration: "sharedJar")
}
task integrationTest(type: Test, group: "verification") {
- testClassesDirs = sourceSets.integrationTest.output.classesDirs
- classpath = sourceSets.integrationTest.runtimeClasspath
+ useJUnitPlatform()
+ testClassesDirs = project.parent.sourceSets.test.output.classesDirs
+ classpath = project.parent.sourceSets.test.runtimeClasspath
outputs.upToDateWhen { false }
-
- doFirst {
- dockerCompose.exposeAsSystemProperties(integrationTest)
- systemProperty("flavor", flavor)
- }
}
@@ -56,12 +47,9 @@ subprojects {
dependsOn(configurations.actuatorsJar)
- if(flavor == "solr6") {
+ if (flavor == "solr6") {
smartCopy "${project.parent.projectDir}/src/test/resources/solr6/solrconfig_insight.xml", "/opt/alfresco-search-services/solrhome/templates/rerank/conf/solrconfig_insight.xml"
smartCopy configurations.actuatorsJar.singleFile, "/opt/alfresco-search-services/solrhome/lib/"
- } else {
- smartCopy "${project.parent.projectDir}/src/test/resources/solr4/solrconfig.xml", "/opt/alfresco/solr4/workspace-SpacesStore/conf/solrconfig.xml"
- smartCopy configurations.actuatorsJar.singleFile, "/opt/alfresco/solr4/lib/"
}
}
diff --git a/integration-tests/solr4/overload.gradle b/integration-tests/solr4/overload.gradle
deleted file mode 100644
index dd9a749..0000000
--- a/integration-tests/solr4/overload.gradle
+++ /dev/null
@@ -1,7 +0,0 @@
-ext {
- solrVersion = '4.10.3'
- alfrescoVersion = '5.2.g'
- solrBaseImage = 'hub.xenit.eu/public/alfresco-solr4:5.2'
- alfrescoimage ='docker.io/xenit/alfresco-repository-community:5.2.g'
- flavor = 'solr4'
-}
diff --git a/integration-tests/solr6/overload.gradle b/integration-tests/solr6/overload.gradle
index 3259759..88432d3 100644
--- a/integration-tests/solr6/overload.gradle
+++ b/integration-tests/solr6/overload.gradle
@@ -1,7 +1,7 @@
ext {
solrVersion = '6.6.5'
- assVersion = '2.0.0'
- solrBaseImage = 'hub.xenit.eu/public/alfresco-solr6:2.0.1'
- alfrescoimage ='docker.io/xenit/alfresco-repository-community:6.1.2-ga'
+ assVersion = '2.0.6'
+ solrBaseImage = 'private.docker.xenit.eu/alfresco-enterprise/alfresco-solr6:2.0.6'
+ alfrescoimage ='docker.io/xenit/alfresco-repository-community:7.3.0'
flavor = 'solr6'
}
diff --git a/integration-tests/src/test/java/eu/xenit/actuators/integrationtesting/SolrSmokeTests.java b/integration-tests/src/test/java/eu/xenit/actuators/integrationtesting/SolrSmokeTests.java
index e2d2e32..7292b49 100644
--- a/integration-tests/src/test/java/eu/xenit/actuators/integrationtesting/SolrSmokeTests.java
+++ b/integration-tests/src/test/java/eu/xenit/actuators/integrationtesting/SolrSmokeTests.java
@@ -2,33 +2,33 @@
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.specification.RequestSpecification;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static java.lang.Thread.sleep;
-import static org.hamcrest.core.StringContains.containsString;
public class SolrSmokeTests {
static RequestSpecification spec;
+ private static final Log log = LogFactory.getLog(SolrSmokeTests.class);
- @BeforeClass
+ @BeforeAll
public static void setup() {
String flavor = System.getProperty("flavor");
String basePathSolr = "solr/alfresco/xenit/actuators/readiness";
- if("solr4".equals(flavor))
- basePathSolr = "solr4/alfresco/xenit/actuators/readiness";
+
String solrHost = System.getProperty("solr.host");
int solrPort = 0;
try {
solrPort = Integer.parseInt(System.getProperty("solr.tcp.8080"));
- } catch(NumberFormatException e) {
+ } catch (NumberFormatException e) {
System.out.println("Solr port 8080 is not exposed, probably ssl is enabled");
}
- System.out.println("Looking at " + solrHost + ":" + solrPort + "/" + basePathSolr + " where flavor=" + flavor);
+ System.out.println("Looking at " + solrHost + ":" + solrPort + "/" + basePathSolr + " where flavor=" + flavor);
String baseURISolr = "http://" + solrHost;
spec = new RequestSpecBuilder()
@@ -40,24 +40,28 @@ public static void setup() {
@Test
- public void testActuatorsEndpoint() {
- // wait until solr tracks
- long sleepTime = 30000;
- try {
- sleep(sleepTime);
- } catch (InterruptedException e) {
- e.printStackTrace();
+ void testActuatorsEndpoint() {
+ System.out.println("Ready test triggered, will wait maximum 30 seconds");
+ String status = "";
+ long timeout = 30000;
+ long elapsed = 0;
+ while ("UP".equals(status) && elapsed < timeout) {
+ status = given()
+ .spec(spec)
+ .when()
+ .get()
+ .then()
+ .statusCode(200)
+ .extract()
+ .path("ready");
+ System.out.println("elapsed =" + elapsed);
+ try {
+ sleep(1000);
+ elapsed += 1000;
+ } catch (InterruptedException e) {
+ log.error(e);
+ }
}
-
- given()
- .spec(spec)
- .when()
- .get()
- .then()
- .statusCode(200)
- .body(containsString("UP"))
- .toString();
-
}
}
diff --git a/integration-tests/src/test/resources/compose/docker-compose.yml b/integration-tests/src/test/resources/compose/docker-compose.yml
index 3f8695b..880a8b8 100644
--- a/integration-tests/src/test/resources/compose/docker-compose.yml
+++ b/integration-tests/src/test/resources/compose/docker-compose.yml
@@ -8,7 +8,8 @@ services:
- 8080
environment:
- INDEX
- - SOLR_SSL=none
+ - SOLR_SSL=secret
+ - GLOBAL_solr.sharedSecret=mysolrsecret
- GLOBAL_local.transform.service.enabled=false
- JAVA_XMX=2048M
@@ -25,7 +26,13 @@ services:
restart: unless-stopped
hostname: solr
ports:
- - 8080
+ - 8080:8080
+ - 8000:8000
+ - 5000:5000
environment:
- ALFRESCO_SSL=none
- - JAVA_XMX=1024M
\ No newline at end of file
+ - DEBUG=true
+ - JMX_ENABLED=true
+ - READINESS_MAX_LAG=1300000
+ - JAVA_XMX=1024M
+ - JAVA_OPTS_SSL=-Dalfresco.secureComms=secret -Dalfresco.secureComms.secret=mysolrsecret
\ No newline at end of file
diff --git a/integration-tests/src/test/resources/solr4/solrconfig.xml b/integration-tests/src/test/resources/solr4/solrconfig.xml
deleted file mode 100644
index 6a65bd7..0000000
--- a/integration-tests/src/test/resources/solr4/solrconfig.xml
+++ /dev/null
@@ -1,1980 +0,0 @@
-
-
-
-
-
-
-
-
- 4.9
-
-
-
-
-
-
-
- ${data.dir.root}/${data.dir.store}
-
-
-
-
-
-
-
- ${solr.hdfs.home:}
-
- ${solr.hdfs.confdir:}
-
- ${solr.hdfs.blockcache.enabled:true}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${merger.maxMergeCount:6}
- ${merger.maxThreadCount:3}
-
-
-
-
- ${solr.lock.type:native}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${solr.autoCommit.maxTime:-1}
- false
-
-
-
-
-
- ${solr.autoSoftCommit.maxTime:-1}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${solr.maxBooleanClauses:10000}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- true
-
-
-
-
-
- ${solr.queryResultWindowSize:512}
-
-
- ${solr.queryResultMaxDocsCached:2048}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- false
-
-
- 2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- afts
- explicit
- 10
- suggest
-
-
- setLocale
- ensureModels
- rewriteFacetParameters
- query
- facet
- mlt
- highlight
- stats
- debug
- clearLocale
- rewriteFacetCounts
-
- spellcheck
- setProcessedDenies
-
-
-
-
-
-
-
- explicit
- 10
- suggest
-
-
-
-
- setLocale
- ensureModels
- rewriteFacetParameters
- query
- facet
- mlt
- highlight
- stats
- debug
- clearLocale
- rewriteFacetCounts
-
- setProcessedDenies
-
-
-
-
-
-
-
-
- explicit
- json
- true
- suggest
-
-
-
-
-
-
-
-
- true
- json
- true
-
-
-
-
-
-
-
- explicit
-
-
- velocity
- browse
- layout
- Solritas
-
-
- edismax
-
- text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
- title^10.0 description^5.0 keywords^5.0 author^2.0 resourcename^1.0
-
- text
- 100%
- *:*
- 10
- *,score
-
-
- text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
- title^10.0 description^5.0 keywords^5.0 author^2.0 resourcename^1.0
-
- text,features,name,sku,id,manu,cat,title,description,keywords,author,resourcename
- 3
-
-
- on
- cat
- manu_exact
- content_type
- author_s
- ipod
- GB
- 1
- cat,inStock
- after
- price
- 0
- 600
- 50
- popularity
- 0
- 10
- 3
- manufacturedate_dt
- NOW/YEAR-10YEARS
- NOW
- +1YEAR
- before
- after
-
-
- on
- content features title name
- html
- <b>
- </b>
- 0
- title
- 0
- name
- 3
- 200
- content
- 750
-
-
- on
- false
- 5
- 2
- 5
- true
- true
- 5
- 3
-
-
-
-
- spellcheck
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- application/json
-
-
-
-
- application/csv
-
-
-
-
-
-
- true
- ignored_
-
-
- true
- links
- ignored_
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- solrpingquery
-
-
- all
-
-
-
-
-
-
-
-
- explicit
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text_shingle
-
-
-
-
-
- default
- suggest
- solr.DirectSolrSpellChecker
-
- internal
-
- 0.5
-
- 2
-
- 1
-
- 5
-
- 4
-
- 0.01
-
-
-
-
-
- wordbreak
- suggest
- solr.WordBreakSolrSpellChecker
- true
- true
- 10
- 5
-
-
-
-
-
-
-
- suggest
-
- default
- wordbreak
- on
- true
- 10
- 5
- 5
- true
- true
- 10
- 5
-
-
- spellcheck
-
-
-
-
-
- shingleBasedSuggestions
- ${solr.suggester.enabled:true}
-
- org.apache.solr.spelling.suggest.fst.WFSTLookupFactory
- suggest
- text_shingle
- true
-
-
-
-
-
- true
- 10
- shingleBasedSuggestions
-
-
- suggest
-
-
-
-
-
-
-
-
-
-
-
-
- text
- true
-
-
- tvComponent
-
-
-
-
-
-
- lingo
-
-
- org.carrot2.clustering.lingo.LingoClusteringAlgorithm
-
-
- clustering/carrot2
-
-
-
-
- stc
- org.carrot2.clustering.stc.STCClusteringAlgorithm
-
-
-
-
- kmeans
- org.carrot2.clustering.kmeans.BisectingKMeansClusteringAlgorithm
-
-
-
-
-
-
- true
- true
-
- mltext@m___t@{http://www.alfresco.org/model/content/1.0}title
-
- id
-
- content@s___t@{http://www.alfresco.org/model/content/1.0}content
-
- true
-
-
-
- false
-
-
- edismax
-
- text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
-
- *:*
- 10
- *,score
-
-
- clustering
-
-
-
-
-
-
-
-
-
- true
- false
-
-
- terms
-
-
-
-
-
-
-
- text___
- elevate.xml
-
-
-
-
-
- explicit
- suggest
-
-
- elevator
-
-
-
-
-
-
-
-
-
-
- 100
-
-
-
-
-
-
-
- 70
-
- 0.5
-
- [-\w ,/\n\"']{20,200}
-
-
-
-
-
-
- ]]>
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ,,
- ,,
- ,,
- ,,
- ,]]>
- ]]>
-
-
-
-
-
- 10
- .,!?
-
-
-
-
-
-
- WORD
-
-
- en
- US
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/plain; charset=UTF-8
-
-
-
-
-
-
-
-
- 5
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- *:*
-
-
-
-
-
-
- alfresco
-
-
- setLocale
- ensureModels
- rewriteFacetParameters
- query
- facet
- mlt
- highlight
- stats
- debug
- clearLocale
- rewriteFacetCounts
-
- setProcessedDenies
-
-
-
-
-
-
-
- afts
-
- false
- false
- 5
- 2
- 5
- true
- true
- 5
- 3
-
- mltext@m___t@{http://www.alfresco.org/model/content/1.0}title
- id
- content@s___t@{http://www.alfresco.org/model/content/1.0}content
- true
- false
-
-
-
- setLocale
- ensureModels
- rewriteFacetParameters
- query
- facet
- mlt
- highlight
- stats
- debug
- clearLocale
- rewriteFacetCounts
-
- spellcheck
- setProcessedDenies
-
- clustering
-
-
-
-
-
-
- cmis
-
-
- setLocale
- ensureModels
- rewriteFacetParameters
- query
- facet
- mlt
- highlight
- stats
- debug
- clearLocale
- rewriteFacetCounts
-
- setProcessedDenies
-
-
-
-
-
-
-
-
-
-
- conf/mime_types.csv
-
-
-
- 1
- 10
-
-
-
-
-
-
-
-
-
-
-
diff --git a/publish.gradle b/publish.gradle
index 38b8946..3e6289d 100644
--- a/publish.gradle
+++ b/publish.gradle
@@ -1,8 +1,12 @@
apply plugin: 'maven-publish'
apply plugin: 'signing'
-apply plugin: 'de.marcphilipp.nexus-publish'
publishing {
+ publications {
+ mavenJava(MavenPublication) {
+ from components.java
+ }
+ }
publications {
all {
pom {
@@ -31,36 +35,23 @@ publishing {
}
}
}
-}
-
-nexusPublishing {
repositories {
- sonatype {
- username = project.hasProperty('publish_username') ? project.publish_username : ''
- password = project.hasProperty('publish_password') ? project.publish_password : ''
+ maven {
+ def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
+ def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
+ url = version.toString().endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
+
+ credentials {
+ username = project.findProperty('sonatype_username')
+ password = project.findProperty('sonatype_password')
+ }
}
}
}
-afterEvaluate {
- signing {
- required { !version.endsWith('SNAPSHOT') && gradle.taskGraph.hasTask("publish") }
- sign publishing.publications
- }
-}
-
-gradle.taskGraph.whenReady { graph ->
- if (graph.hasTask(publish)) {
- if (!project.hasProperty('keyId') || !project.hasProperty('secretKeyRingFile') || !project.hasProperty('password')) {
- throw new GradleException('You need to provide signing params in order to sign artifacts')
- }
- def id = project.hasProperty('keyId') ? project.keyId : ''
- def file = project.hasProperty('secretKeyRingFile') ? project.secretKeyRingFile : ''
- def password = project.hasProperty('password') ? project.password : ''
-
- ext."signing.keyId" = id
- ext."signing.secretKeyRingFile" = file
- ext."signing.password" = password
- }
-}
+signing {
+ required { !version.toString().endsWith("SNAPSHOT") }
+ useInMemoryPgpKeys(findProperty("signingKeyId"), findProperty("signingKey"), findProperty("signingPassword"))
+ sign publishing.publications
+}
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index 96fc20f..4b2ef52 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -3,7 +3,7 @@ rootProject.name = 'solr-actuators'
include ':solr-actuators'
include ':integration-tests'
-["solr4","solr6"].each { version ->
+["solr6"].each { version ->
include ":integration-tests:${version}"
include ":integration-tests:${version}"
}
\ No newline at end of file
diff --git a/solr-actuators/build.gradle b/solr-actuators/build.gradle
index 228a1c8..923a4ea 100644
--- a/solr-actuators/build.gradle
+++ b/solr-actuators/build.gradle
@@ -31,10 +31,5 @@ dependencies {
artifacts.add('sharedJar', jar)
-publishing {
- publications {
- mavenJava(MavenPublication) {
- from components.java
- }
- }
-}
+
+apply from: "${rootProject.projectDir}/publish.gradle"
\ No newline at end of file
diff --git a/solr-actuators/src/main/java/eu/xenit/actuators/handler/ReadinessConfig.java b/solr-actuators/src/main/java/eu/xenit/actuators/handler/ReadinessConfig.java
new file mode 100644
index 0000000..81363bd
--- /dev/null
+++ b/solr-actuators/src/main/java/eu/xenit/actuators/handler/ReadinessConfig.java
@@ -0,0 +1,26 @@
+package eu.xenit.actuators.handler;
+
+public class ReadinessConfig {
+
+ public static final String READINESS_MAX_LAG = "READINESS_MAX_LAG";
+
+ public long getMaxLag() {
+ return maxLag;
+ }
+
+ private final long maxLag;
+
+ public ReadinessConfig() {
+ Long tmpMaxLag = getLongConfig(READINESS_MAX_LAG);
+ if (tmpMaxLag == null) {
+ this.maxLag = 1800000L;
+ } else {
+ this.maxLag = tmpMaxLag;
+ }
+ }
+ private static Long getLongConfig(String property) {
+ String envProp = System.getenv().get(property);
+ if (envProp == null || envProp.isEmpty()) return null;
+ return Long.parseLong(envProp);
+ }
+}
\ No newline at end of file
diff --git a/solr-actuators/src/main/java/eu/xenit/actuators/handler/ReadinessHandler.java b/solr-actuators/src/main/java/eu/xenit/actuators/handler/ReadinessHandler.java
index be06a3f..1055242 100644
--- a/solr-actuators/src/main/java/eu/xenit/actuators/handler/ReadinessHandler.java
+++ b/solr-actuators/src/main/java/eu/xenit/actuators/handler/ReadinessHandler.java
@@ -7,94 +7,121 @@
import org.alfresco.solr.tracker.MetadataTracker;
import org.alfresco.solr.tracker.TrackerRegistry;
import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.handler.ReplicationHandler;
import org.apache.solr.handler.RequestHandlerBase;
+import org.apache.solr.request.LocalSolrQueryRequest;
import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.SolrQueryResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.solr.util.plugin.SolrCoreAware;
-import java.lang.reflect.Method;
+import java.text.MessageFormat;
-public class ReadinessHandler extends RequestHandlerBase {
- private static final Logger logger = LoggerFactory.getLogger(ReadinessHandler.class);
- private static final long MAX_LAG = 1800L;
+public class ReadinessHandler extends RequestHandlerBase implements SolrCoreAware {
- Object invokeMethods(Object target, String... methods) throws Exception {
- for (String methodName : methods) {
- Method method = target.getClass().getMethod(methodName);
- target = method.invoke(target);
+ private static final String READY = "ready";
+ private static final String DOWN = "DOWN";
+ private static final String UP = "UP";
+ private static final ReadinessConfig config = new ReadinessConfig();
+ SolrCore core;
+
+ @Override
+ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) {
+ try {
+ SolrCore solrCore = req.getCore();
+ AlfrescoCoreAdminHandler
+ coreAdminHandler = (AlfrescoCoreAdminHandler) solrCore
+ .getCoreContainer()
+ .getMultiCoreHandler();
+ boolean setInfo = req.getParams().get("info") != null;
+ checkTransactionResponse(setInfo, rsp,
+ coreAdminHandler.getTrackerRegistry(),
+ solrCore.getName());
+
+ checkReplicationHandler(setInfo, rsp);
+
+ } catch (SolrException e) {
+ rsp.add(READY, DOWN);
+ rsp.setException(e);
+ return;
+ } catch (Exception e) {
+ rsp.add(READY, DOWN);
+ rsp.setException(new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE, e.getMessage(), e));
+ return;
}
- return target;
+ rsp.add(READY, UP);
}
+ 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);
- @Override
- public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
- AlfrescoCoreAdminHandler coreAdminHandler = null;
- if(isSolr6(req)) {
- coreAdminHandler = (AlfrescoCoreAdminHandler) invokeMethods(req,"getCore","getCoreContainer","getMultiCoreHandler");
- } else {
- coreAdminHandler = (AlfrescoCoreAdminHandler) invokeMethods(req,"getCore","getCoreDescriptor","getCoreContainer","getMultiCoreHandler");
- }
+ TrackerState metadataTrackerState = metadataTracker.getTrackerState();
+ TrackerState aclsTrackerState = aclTracker.getTrackerState();
- long lastTxCommitTimeOnServer = 0;
- long lastChangeSetCommitTimeOnServer = 0;
- TrackerState metadataTrackerState = null;
- TrackerState aclsTrackerState = null;
+ long lastTxCommitTimeOnServer = metadataTrackerState.getLastTxCommitTimeOnServer();
+ long lastChangeSetCommitTimeOnServer = aclsTrackerState.getLastChangeSetCommitTimeOnServer();
- try {
- TrackerRegistry trackerRegistry = coreAdminHandler.getTrackerRegistry();
- String coreName = req.getCore().getName();
-
- MetadataTracker metadataTracker = trackerRegistry.getTrackerForCore(coreName, MetadataTracker.class);
- AclTracker aclTracker = trackerRegistry.getTrackerForCore(coreName, AclTracker.class);
-
- metadataTrackerState = metadataTracker.getTrackerState();
- aclsTrackerState = aclTracker.getTrackerState();
- lastTxCommitTimeOnServer = metadataTrackerState.getLastTxCommitTimeOnServer();
- lastChangeSetCommitTimeOnServer = aclsTrackerState.getLastChangeSetCommitTimeOnServer();
- } catch (Exception e) {
- rsp.add("ready", "DOWN");
- rsp.setException(new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE, e.getMessage()));
- return;
+ if ((lastTxCommitTimeOnServer == 0 || lastChangeSetCommitTimeOnServer == 0)) {
+ throw new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE,
+ "Solr did not yet get latest values from server");
}
- if((lastTxCommitTimeOnServer == 0 || lastChangeSetCommitTimeOnServer == 0)) {
- rsp.add("ready","DOWN");
- rsp.setException(new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE,"Solr did not yet get latest values from server"));
- return;
- }
+ checkMaxLag(setInfo, rsp,
+ lastTxCommitTimeOnServer,
+ lastChangeSetCommitTimeOnServer,
+ metadataTrackerState.getLastIndexedTxCommitTime(),
+ aclsTrackerState.getLastIndexedChangeSetCommitTime());
+ }
- long lastIndexChangeSetCommitTime = aclsTrackerState.getLastIndexedChangeSetCommitTime();
- long lastIndexTxCommitTime = metadataTrackerState.getLastIndexedTxCommitTime();
- long txLagSeconds = (lastTxCommitTimeOnServer - lastIndexTxCommitTime) / 1000;
- if(req.getParams().get("info")!=null) {
- rsp.add("txLag", txLagSeconds);
+ private void checkMaxLag(boolean setInfo, SolrQueryResponse rsp,
+ long lastTxCommitTimeOnServer,
+ long lastChangeSetCommitTimeOnServer,
+ long lastIndexTxCommitTime,
+ long lastIndexChangeSetCommitTime) {
+ long txLag = (lastTxCommitTimeOnServer - lastIndexTxCommitTime);
+ long changeSetLag = (lastChangeSetCommitTimeOnServer - lastIndexChangeSetCommitTime);
+ if (setInfo) {
+ rsp.add("txLag", txLag);
rsp.add("lastTxCommitTimeOnServer", lastTxCommitTimeOnServer);
- }
- long changeSetLagSeconds = (lastChangeSetCommitTimeOnServer - lastIndexChangeSetCommitTime) / 1000;
- if(req.getParams().get("info")!=null) {
- rsp.add("changeSetLag", changeSetLagSeconds);
+ rsp.add("changeSetLag", changeSetLag);
rsp.add("lastChangeSetCommitTimeOnServer", lastChangeSetCommitTimeOnServer);
}
-
- if(txLagSeconds >= MAX_LAG || changeSetLagSeconds >= MAX_LAG) {
- rsp.add("ready","NO");
- rsp.setException(new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE,"Lag is larger than permitted: txLag=" + txLagSeconds + ", changeSetLag=" + changeSetLagSeconds + ", MAX_LAG=" + MAX_LAG));
- return;
- } else {
- rsp.add("ready","UP");
+ if (txLag >= config.getMaxLag() || 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()));
}
}
- private boolean isSolr6(SolrQueryRequest req) {
- try {
- invokeMethods(req,"getCore","getCoreContainer");
- } catch (Exception e) {
- return false;
+ private void checkReplicationHandler(boolean setInfo, SolrQueryResponse rsp) throws Exception {
+ SolrRequestHandler handler = core.getRequestHandler(ReplicationHandler.PATH);
+ ReplicationHandler replicationHandler = (ReplicationHandler) handler;
+ NamedList