Skip to content

Commit

Permalink
Add a scheduler for reindexing
Browse files Browse the repository at this point in the history
  • Loading branch information
marko-bekhta committed Dec 14, 2023
1 parent 62a246a commit 98a748a
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 1 deletion.
4 changes: 4 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-jib</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-scheduler</artifactId>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@
interface IndexingConfig {
OnStartup onStartup();

Scheduled scheduled();

interface OnStartup {
@WithDefault("true")
boolean enabled();

@WithDefault("3s")
Duration waitInterval();
}

interface Scheduled {
String cron();
}
}
14 changes: 14 additions & 0 deletions src/main/java/io/quarkus/search/app/indexing/IndexingService.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import io.quarkus.logging.Log;
import io.quarkus.narayana.jta.QuarkusTransaction;
import io.quarkus.runtime.StartupEvent;
import io.quarkus.scheduler.Scheduled;
import io.quarkus.vertx.http.ManagementInterface;

import org.hibernate.Session;
Expand Down Expand Up @@ -86,6 +87,19 @@ void indexOnStartup(@Observes StartupEvent ev) {
t -> Log.errorf(t, "Reindexing on startup failed: %s", t.getMessage()));
}

@Scheduled(cron = "{indexing.scheduled.cron}")
void indexOnTime() {
try {
Log.infof("Scheduled reindex starting...");
reindex();
Log.infof("Scheduled reindex finished.");
} catch (ReindexingAlreadyInProgressException e) {
Log.infof("Indexing was already started by some other process.");
} catch (Exception e) {
Log.errorf(e, "Failed to start scheduled reindex: %s", e.getMessage());
}
}

private boolean isSearchBackendAccessible() {
try {
searchMapping.backend().unwrap(ElasticsearchBackend.class).client(RestClient.class)
Expand Down
6 changes: 5 additions & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ quarkus.application.name=search-quarkus-io

# Application defaults
quarkusio.git-uri=https://github.com/quarkusio/quarkusio.github.io.git

# Scheduler configuration
# At 19:00:00 every day
indexing.scheduled.cron=0 0 19 * * ?
# More secure HTTP defaults
quarkus.http.cors=true
quarkus.http.cors.origins=https://quarkus.io,/https://.*\.quarkus\.io/,/https://quarkus-(web)?site-pr-[0-9]+-preview\.surge\.sh/
Expand Down Expand Up @@ -37,6 +39,8 @@ quarkus.test.integration-test-profile=integrationtest
# - for tests we use QuarkusIOSample to use a customized sample based on the one included in the test resources
# so this property should never be used.
%test,integrationtest.quarkusio.git-uri=file:tests-should-use-quarkus-io-sample-setup-annotation
# disable scheduled indexing for dev/tests to not mess up anything with an unexpected reindexing:
%dev,test,integrationtest.indexing.scheduled.cron=off
## Logging
quarkus.log.category."io.quarkus.search.app".min-level=TRACE
%dev,test,integrationtest.quarkus.log.category."io.quarkus.search.app".level=TRACE
Expand Down
66 changes: 66 additions & 0 deletions src/test/java/io/quarkus/search/app/indexing/SchedulerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.quarkus.search.app.indexing;

import static io.restassured.RestAssured.given;
import static org.assertj.core.api.Assertions.assertThat;

import java.time.Duration;
import java.util.Map;

import io.quarkus.search.app.SearchService;
import io.quarkus.search.app.dto.GuideSearchHit;
import io.quarkus.search.app.dto.SearchResult;
import io.quarkus.search.app.testsupport.QuarkusIOSample;

import io.quarkus.test.common.http.TestHTTPEndpoint;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.QuarkusTestProfile;
import io.quarkus.test.junit.TestProfile;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;

import org.awaitility.Awaitility;

import io.restassured.common.mapper.TypeRef;

@QuarkusTest
@TestProfile(SchedulerTest.Profile.class)
@TestHTTPEndpoint(SearchService.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@QuarkusIOSample.Setup(filter = QuarkusIOSample.SearchServiceFilterDefinition.class)
class SchedulerTest {
public static class Profile implements QuarkusTestProfile {
@Override
public Map<String, String> getConfigOverrides() {
return Map.of("indexing.on-startup.enabled", "false",
// Every 10 seconds starting at second 00, every minute starting at minute :00, of every hour:
"indexing.scheduled.cron", "0/10 0/1 * ? * * *");
}
}

private static final TypeRef<SearchResult<GuideSearchHit>> SEARCH_RESULT_SEARCH_HITS = new TypeRef<>() {
};
private static final String GUIDES_SEARCH = "/guides/search";

protected int managementPort() {
if (getClass().getName().endsWith("IT")) {
return 9000;
} else {
return 9001;
}
}

@Test
void scheduler() {
// since we've disabled the index-on-start there should be no indexes until the scheduler kicks in:
Awaitility.await().timeout(Duration.ofMinutes(1)).pollDelay(Duration.ofSeconds(15)).untilAsserted(() -> {
assertThat(given()
.when().get(GUIDES_SEARCH)
.then()
.statusCode(200)
.extract().body().as(SEARCH_RESULT_SEARCH_HITS)
.total()).isPositive();
});
}

}

0 comments on commit 98a748a

Please sign in to comment.