Merge pull request #4791 from apache/nouveau-indexmanager-improvements
Nouveau indexmanager improvements
diff --git a/nouveau/src/main/java/org/apache/couchdb/nouveau/NouveauApplication.java b/nouveau/src/main/java/org/apache/couchdb/nouveau/NouveauApplication.java
index 3039214..89b2b85 100644
--- a/nouveau/src/main/java/org/apache/couchdb/nouveau/NouveauApplication.java
+++ b/nouveau/src/main/java/org/apache/couchdb/nouveau/NouveauApplication.java
@@ -13,10 +13,12 @@
package org.apache.couchdb.nouveau;
+import com.github.benmanes.caffeine.cache.Scheduler;
import io.dropwizard.core.Application;
import io.dropwizard.core.setup.Environment;
import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource;
import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ScheduledExecutorService;
import org.apache.couchdb.nouveau.core.IndexManager;
import org.apache.couchdb.nouveau.health.AnalyzeHealthCheck;
import org.apache.couchdb.nouveau.health.IndexHealthCheck;
@@ -25,7 +27,6 @@
import org.apache.couchdb.nouveau.resources.AnalyzeResource;
import org.apache.couchdb.nouveau.resources.IndexResource;
import org.apache.couchdb.nouveau.tasks.CloseAllIndexesTask;
-import org.apache.lucene.search.SearcherFactory;
public class NouveauApplication extends Application<NouveauApplicationConfiguration> {
@@ -40,17 +41,20 @@
@Override
public void run(NouveauApplicationConfiguration configuration, Environment environment) throws Exception {
+
// configure index manager
final IndexManager indexManager = new IndexManager();
indexManager.setCommitIntervalSeconds(configuration.getCommitIntervalSeconds());
indexManager.setIdleSeconds(configuration.getIdleSeconds());
indexManager.setMaxIndexesOpen(configuration.getMaxIndexesOpen());
indexManager.setMetricRegistry(environment.metrics());
- indexManager.setScheduler(environment
+ final ScheduledExecutorService schedulerExecutorService = environment
.lifecycle()
.scheduledExecutorService("index-manager-%d")
- .threads(5)
- .build());
+ .threads(configuration.getSchedulerThreadCount())
+ .build();
+ indexManager.setScheduler(Scheduler.forScheduledExecutorService(schedulerExecutorService));
+ indexManager.setSearcherFactory(new ParallelSearcherFactory(ForkJoinPool.commonPool()));
indexManager.setObjectMapper(environment.getObjectMapper());
indexManager.setRootDir(configuration.getRootDir());
environment.lifecycle().manage(indexManager);
@@ -63,8 +67,7 @@
environment.jersey().register(analyzeResource);
// IndexResource
- final SearcherFactory searcherFactory = new ParallelSearcherFactory(ForkJoinPool.commonPool());
- final IndexResource indexResource = new IndexResource(indexManager, searcherFactory);
+ final IndexResource indexResource = new IndexResource(indexManager);
environment.jersey().register(indexResource);
// Health checks
diff --git a/nouveau/src/main/java/org/apache/couchdb/nouveau/NouveauApplicationConfiguration.java b/nouveau/src/main/java/org/apache/couchdb/nouveau/NouveauApplicationConfiguration.java
index 50d3201..dce6fe6 100644
--- a/nouveau/src/main/java/org/apache/couchdb/nouveau/NouveauApplicationConfiguration.java
+++ b/nouveau/src/main/java/org/apache/couchdb/nouveau/NouveauApplicationConfiguration.java
@@ -33,6 +33,9 @@
@NotNull
private Path rootDir = null;
+ @Min(2)
+ private int schedulerThreadCount = 5;
+
@JsonProperty
public void setMaxIndexesOpen(int maxIndexesOpen) {
this.maxIndexesOpen = maxIndexesOpen;
@@ -68,4 +71,12 @@
public Path getRootDir() {
return rootDir;
}
+
+ public int getSchedulerThreadCount() {
+ return schedulerThreadCount;
+ }
+
+ public void setSchedulerThreadCount(int schedulerThreadCount) {
+ this.schedulerThreadCount = schedulerThreadCount;
+ }
}
diff --git a/nouveau/src/main/java/org/apache/couchdb/nouveau/core/Index.java b/nouveau/src/main/java/org/apache/couchdb/nouveau/core/Index.java
index 740e7ea..bc56cd7 100644
--- a/nouveau/src/main/java/org/apache/couchdb/nouveau/core/Index.java
+++ b/nouveau/src/main/java/org/apache/couchdb/nouveau/core/Index.java
@@ -18,7 +18,6 @@
import java.io.Closeable;
import java.io.IOException;
import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
import org.apache.couchdb.nouveau.api.DocumentDeleteRequest;
import org.apache.couchdb.nouveau.api.DocumentUpdateRequest;
import org.apache.couchdb.nouveau.api.IndexInfo;
@@ -40,8 +39,6 @@
private long updateSeq;
private long purgeSeq;
private boolean deleteOnClose = false;
- private long lastCommit = now();
- private volatile boolean closed;
private final Semaphore permits = new Semaphore(Integer.MAX_VALUE);
protected Index(final long updateSeq, final long purgeSeq) {
@@ -50,25 +47,7 @@
}
public final boolean tryAcquire() {
- if (permits.tryAcquire() == false) {
- return false;
- }
- if (closed) {
- permits.release();
- return false;
- }
- return true;
- }
-
- public final boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException {
- if (permits.tryAcquire(timeout, unit) == false) {
- return false;
- }
- if (closed) {
- permits.release();
- return false;
- }
- return true;
+ return permits.tryAcquire();
}
public final void release() {
@@ -117,17 +96,13 @@
final long updateSeq;
final long purgeSeq;
synchronized (this) {
+ if (deleteOnClose) {
+ return false;
+ }
updateSeq = this.updateSeq;
purgeSeq = this.purgeSeq;
}
- final boolean result = doCommit(updateSeq, purgeSeq);
- if (result) {
- final long now = now();
- synchronized (this) {
- this.lastCommit = now;
- }
- }
- return result;
+ return doCommit(updateSeq, purgeSeq);
}
protected abstract boolean doCommit(final long updateSeq, final long purgeSeq) throws IOException;
@@ -154,28 +129,24 @@
@Override
public final void close() throws IOException {
- synchronized (this) {
- closed = true;
- }
// Ensures exclusive access to the index before closing.
permits.acquireUninterruptibly(Integer.MAX_VALUE);
- try {
- doClose();
- } finally {
- permits.release(Integer.MAX_VALUE);
- }
+ doClose();
+ // Never release permits.
}
protected abstract void doClose() throws IOException;
- public boolean isDeleteOnClose() {
+ public synchronized boolean isDeleteOnClose() {
return deleteOnClose;
}
- public void setDeleteOnClose(final boolean deleteOnClose) {
- synchronized (this) {
- this.deleteOnClose = deleteOnClose;
- }
+ public synchronized void setDeleteOnClose(final boolean deleteOnClose) {
+ this.deleteOnClose = deleteOnClose;
+ }
+
+ public final boolean isActive() {
+ return permits.availablePermits() < Integer.MAX_VALUE || permits.hasQueuedThreads();
}
protected final void assertUpdateSeqProgress(final long matchSeq, final long updateSeq)
@@ -211,15 +182,4 @@
assertPurgeSeqProgress(matchSeq, purgeSeq);
this.purgeSeq = purgeSeq;
}
-
- public boolean needsCommit(final long duration, final TimeUnit unit) {
- final long commitNeededSince = now() - unit.toNanos(duration);
- synchronized (this) {
- return this.lastCommit < commitNeededSince;
- }
- }
-
- private long now() {
- return System.nanoTime();
- }
}
diff --git a/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexLoader.java b/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexLoader.java
deleted file mode 100644
index b5def16..0000000
--- a/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexLoader.java
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.couchdb.nouveau.core;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import org.apache.couchdb.nouveau.api.IndexDefinition;
-
-@FunctionalInterface
-public interface IndexLoader {
-
- Index apply(final Path path, final IndexDefinition indexDefinition) throws IOException;
-}
diff --git a/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java b/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java
index fb8cf2d..5d10c59 100644
--- a/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java
+++ b/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java
@@ -17,13 +17,14 @@
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.caffeine.MetricsStatsCounter;
-import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.AsyncCacheLoader;
+import com.github.benmanes.caffeine.cache.AsyncLoadingCache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.RemovalCause;
import com.github.benmanes.caffeine.cache.RemovalListener;
import com.github.benmanes.caffeine.cache.Scheduler;
+import com.github.benmanes.caffeine.cache.Weigher;
import io.dropwizard.lifecycle.Managed;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Response.Status;
@@ -34,12 +35,23 @@
import java.nio.file.StandardCopyOption;
import java.time.Duration;
import java.util.List;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
import java.util.concurrent.locks.Lock;
import java.util.stream.Stream;
import org.apache.couchdb.nouveau.api.IndexDefinition;
-import org.eclipse.jetty.io.RuntimeIOException;
+import org.apache.couchdb.nouveau.lucene9.Lucene9AnalyzerFactory;
+import org.apache.couchdb.nouveau.lucene9.Lucene9Index;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.misc.store.DirectIODirectory;
+import org.apache.lucene.search.SearcherFactory;
+import org.apache.lucene.search.SearcherManager;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;
+import org.checkerframework.checker.index.qual.NonNegative;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -68,55 +80,27 @@
private MetricRegistry metricRegistry;
- private ScheduledExecutorService scheduler;
+ private Scheduler scheduler;
- private Cache<String, Index> cache;
+ private SearcherFactory searcherFactory;
+
+ private AsyncLoadingCache<String, Index> cache;
private StripedLock<String> lock;
- public <R> R with(final String name, final IndexLoader loader, final IndexFunction<Index, R> indexFun)
+ public <R> R with(final String name, final IndexFunction<Index, R> indexFun)
throws IOException, InterruptedException {
while (true) {
if (!exists(name)) {
throw new WebApplicationException("Index does not exist", Status.NOT_FOUND);
}
- final Index index;
- try {
- index = cache.get(name, (n) -> {
- LOGGER.info("opening {}", n);
- final Path path = indexPath(n);
- try {
- final IndexDefinition indexDefinition = loadIndexDefinition(n);
- return loader.apply(path, indexDefinition);
- } catch (final IOException e) {
- throw new RuntimeIOException(e);
- }
- });
- } catch (final RuntimeIOException e) {
- throw (IOException) e.getCause();
- }
+ final CompletableFuture<Index> future = cache.get(name);
+ final Index index = future.join();
- if (index.tryAcquire(1, TimeUnit.SECONDS)) {
+ if (index.tryAcquire()) {
try {
- final R result = indexFun.apply(index);
- if (index.needsCommit(commitIntervalSeconds, TimeUnit.SECONDS)) {
- scheduler.execute(() -> {
- if (index.tryAcquire()) {
- try {
- LOGGER.debug("committing {}", name);
- try {
- index.commit();
- } catch (final IOException e) {
- LOGGER.warn("I/O exception while committing " + name, e);
- }
- } finally {
- index.release();
- }
- }
- });
- }
- return result;
+ return indexFun.apply(index);
} finally {
index.release();
}
@@ -193,7 +177,11 @@
}
private void deleteIndex(final String name) throws IOException {
- final Index index = cache.asMap().remove(name);
+ final CompletableFuture<Index> future = cache.asMap().remove(name);
+ if (future == null) {
+ return;
+ }
+ final Index index = future.getNow(null);
if (index != null) {
index.setDeleteOnClose(true);
close(name, index);
@@ -202,39 +190,18 @@
}
}
- @JsonProperty
- public int getMaxIndexesOpen() {
- return maxIndexesOpen;
- }
-
public void setMaxIndexesOpen(int maxIndexesOpen) {
this.maxIndexesOpen = maxIndexesOpen;
}
- public int getCommitIntervalSeconds() {
- return commitIntervalSeconds;
- }
-
public void setCommitIntervalSeconds(int commitIntervalSeconds) {
this.commitIntervalSeconds = commitIntervalSeconds;
}
- public int getIdleSeconds() {
- return idleSeconds;
- }
-
public void setIdleSeconds(int idleSeconds) {
this.idleSeconds = idleSeconds;
}
- public void setScheduler(ScheduledExecutorService scheduler) {
- this.scheduler = scheduler;
- }
-
- public Path getRootDir() {
- return rootDir;
- }
-
public void setRootDir(Path rootDir) {
this.rootDir = rootDir;
}
@@ -247,16 +214,26 @@
this.metricRegistry = metricRegistry;
}
+ public void setScheduler(final Scheduler scheduler) {
+ this.scheduler = scheduler;
+ }
+
+ public void setSearcherFactory(final SearcherFactory searcherFactory) {
+ this.searcherFactory = searcherFactory;
+ }
+
@Override
public void start() throws IOException {
cache = Caffeine.newBuilder()
.recordStats(() -> new MetricsStatsCounter(metricRegistry, name(IndexManager.class, "cache")))
.initialCapacity(maxIndexesOpen)
- .maximumSize(maxIndexesOpen)
+ .maximumWeight(maxIndexesOpen)
+ .weigher(new IndexWeigher())
.expireAfterAccess(Duration.ofSeconds(idleSeconds))
- .scheduler(Scheduler.systemScheduler())
+ .refreshAfterWrite(Duration.ofSeconds(commitIntervalSeconds))
+ .scheduler(scheduler)
.evictionListener(new IndexEvictionListener())
- .build();
+ .buildAsync(new AsyncIndexLoader());
lock = new StripedLock<String>(100);
}
@@ -307,12 +284,91 @@
}
}
+ private class IndexWeigher implements Weigher<String, Index> {
+
+ @Override
+ public @NonNegative int weigh(String key, Index value) {
+ // Pin active indexes
+ return value.isActive() ? 0 : 1;
+ }
+ }
+
+ private class AsyncIndexLoader implements AsyncCacheLoader<String, Index> {
+
+ @Override
+ public CompletableFuture<? extends Index> asyncLoad(String name, Executor executor) throws Exception {
+ final CompletableFuture<Index> future = new CompletableFuture<Index>();
+
+ executor.execute(() -> {
+ LOGGER.info("opening {}", name);
+ final Path path = indexPath(name);
+ Index result;
+ try {
+ final IndexDefinition indexDefinition = loadIndexDefinition(name);
+ final Analyzer analyzer = Lucene9AnalyzerFactory.fromDefinition(indexDefinition);
+ final Directory dir = new DirectIODirectory(FSDirectory.open(path.resolve("9")));
+ final IndexWriterConfig config = new IndexWriterConfig(analyzer);
+ config.setUseCompoundFile(false);
+ final IndexWriter writer = new IndexWriter(dir, config);
+ final long updateSeq = getSeq(writer, "update_seq");
+ final long purgeSeq = getSeq(writer, "purge_seq");
+ final SearcherManager searcherManager = new SearcherManager(writer, searcherFactory);
+ result = new Lucene9Index(analyzer, writer, updateSeq, purgeSeq, searcherManager);
+ future.complete(result);
+ } catch (IOException e) {
+ future.completeExceptionally(e);
+ }
+ });
+
+ return future;
+ }
+
+ @Override
+ public CompletableFuture<? extends Index> asyncReload(String name, Index index, Executor executor)
+ throws Exception {
+ executor.execute(() -> {
+ if (index.tryAcquire()) {
+ try {
+ if (index.commit()) {
+ LOGGER.info("committed {}", name);
+ }
+ } catch (final IOException e) {
+ LOGGER.warn("I/O exception while committing " + name, e);
+ } finally {
+ index.release();
+ }
+ }
+ });
+ return CompletableFuture.completedFuture(index);
+ }
+
+ private long getSeq(final IndexWriter writer, final String key) throws IOException {
+ final Iterable<Map.Entry<String, String>> commitData = writer.getLiveCommitData();
+ if (commitData == null) {
+ return 0L;
+ }
+ for (Map.Entry<String, String> entry : commitData) {
+ if (entry.getKey().equals(key)) {
+ return Long.parseLong(entry.getValue());
+ }
+ }
+ return 0L;
+ }
+ }
+
+ private void close(final String name, final CompletableFuture<Index> future) throws IOException {
+ final Index index = future.getNow(null);
+ if (index != null) {
+ close(name, index);
+ }
+ }
+
private void close(final String name, final Index index) throws IOException {
IOUtils.runAll(
() -> {
if (index.tryAcquire()) {
try {
- if (!index.isDeleteOnClose() && index.commit()) {
+ if (index.commit()) {
LOGGER.debug("committed {} before close", name);
}
} finally {
diff --git a/nouveau/src/main/java/org/apache/couchdb/nouveau/resources/IndexResource.java b/nouveau/src/main/java/org/apache/couchdb/nouveau/resources/IndexResource.java
index 9c7a100..a6ca2c4 100644
--- a/nouveau/src/main/java/org/apache/couchdb/nouveau/resources/IndexResource.java
+++ b/nouveau/src/main/java/org/apache/couchdb/nouveau/resources/IndexResource.java
@@ -29,7 +29,6 @@
import jakarta.ws.rs.core.MediaType;
import java.io.IOException;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
import org.apache.couchdb.nouveau.api.DocumentDeleteRequest;
import org.apache.couchdb.nouveau.api.DocumentUpdateRequest;
@@ -38,18 +37,7 @@
import org.apache.couchdb.nouveau.api.IndexInfoRequest;
import org.apache.couchdb.nouveau.api.SearchRequest;
import org.apache.couchdb.nouveau.api.SearchResults;
-import org.apache.couchdb.nouveau.core.IndexLoader;
import org.apache.couchdb.nouveau.core.IndexManager;
-import org.apache.couchdb.nouveau.lucene9.Lucene9AnalyzerFactory;
-import org.apache.couchdb.nouveau.lucene9.Lucene9Index;
-import org.apache.lucene.analysis.Analyzer;
-import org.apache.lucene.index.IndexWriter;
-import org.apache.lucene.index.IndexWriterConfig;
-import org.apache.lucene.misc.store.DirectIODirectory;
-import org.apache.lucene.search.SearcherFactory;
-import org.apache.lucene.search.SearcherManager;
-import org.apache.lucene.store.Directory;
-import org.apache.lucene.store.FSDirectory;
@Path("/index/{name}")
@Metered
@@ -60,11 +48,9 @@
public final class IndexResource {
private final IndexManager indexManager;
- private final SearcherFactory searcherFactory;
- public IndexResource(final IndexManager indexManager, final SearcherFactory searcherFactory) {
+ public IndexResource(final IndexManager indexManager) {
this.indexManager = Objects.requireNonNull(indexManager);
- this.searcherFactory = Objects.requireNonNull(searcherFactory);
}
@PUT
@@ -80,7 +66,7 @@
@PathParam("docId") String docId,
@NotNull @Valid DocumentDeleteRequest request)
throws Exception {
- indexManager.with(name, indexLoader(), (index) -> {
+ indexManager.with(name, (index) -> {
index.delete(docId, request);
return null;
});
@@ -93,7 +79,7 @@
@GET
public IndexInfo getIndexInfo(@PathParam("name") String name) throws Exception {
- return indexManager.with(name, indexLoader(), (index) -> {
+ return indexManager.with(name, (index) -> {
return index.info();
});
}
@@ -101,7 +87,7 @@
@POST
public void setIndexInfo(@PathParam("name") String name, @NotNull @Valid IndexInfoRequest request)
throws Exception {
- indexManager.with(name, indexLoader(), (index) -> {
+ indexManager.with(name, (index) -> {
if (request.getMatchUpdateSeq().isPresent()
&& request.getUpdateSeq().isPresent()) {
index.setUpdateSeq(
@@ -121,7 +107,7 @@
@Path("/search")
public SearchResults searchIndex(@PathParam("name") String name, @NotNull @Valid SearchRequest request)
throws Exception {
- return indexManager.with(name, indexLoader(), (index) -> {
+ return indexManager.with(name, (index) -> {
return index.search(request);
});
}
@@ -133,36 +119,9 @@
@PathParam("docId") String docId,
@NotNull @Valid DocumentUpdateRequest request)
throws Exception {
- indexManager.with(name, indexLoader(), (index) -> {
+ indexManager.with(name, (index) -> {
index.update(docId, request);
return null;
});
}
-
- private IndexLoader indexLoader() {
- return (path, indexDefinition) -> {
- final Analyzer analyzer = Lucene9AnalyzerFactory.fromDefinition(indexDefinition);
- final Directory dir = new DirectIODirectory(FSDirectory.open(path.resolve("9")));
- final IndexWriterConfig config = new IndexWriterConfig(analyzer);
- config.setUseCompoundFile(false);
- final IndexWriter writer = new IndexWriter(dir, config);
- final long updateSeq = getSeq(writer, "update_seq");
- final long purgeSeq = getSeq(writer, "purge_seq");
- final SearcherManager searcherManager = new SearcherManager(writer, searcherFactory);
- return new Lucene9Index(analyzer, writer, updateSeq, purgeSeq, searcherManager);
- };
- }
-
- private static long getSeq(final IndexWriter writer, final String key) throws IOException {
- final Iterable<Map.Entry<String, String>> commitData = writer.getLiveCommitData();
- if (commitData == null) {
- return 0L;
- }
- for (Map.Entry<String, String> entry : commitData) {
- if (entry.getKey().equals(key)) {
- return Long.parseLong(entry.getValue());
- }
- }
- return 0L;
- }
}
diff --git a/nouveau/src/test/java/org/apache/couchdb/nouveau/health/IndexHealthCheckTest.java b/nouveau/src/test/java/org/apache/couchdb/nouveau/health/IndexHealthCheckTest.java
index c71c281..7ee3223 100644
--- a/nouveau/src/test/java/org/apache/couchdb/nouveau/health/IndexHealthCheckTest.java
+++ b/nouveau/src/test/java/org/apache/couchdb/nouveau/health/IndexHealthCheckTest.java
@@ -17,8 +17,8 @@
import com.codahale.metrics.MetricRegistry;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.benmanes.caffeine.cache.Scheduler;
import java.nio.file.Path;
-import java.util.concurrent.Executors;
import org.apache.couchdb.nouveau.core.IndexManager;
import org.apache.couchdb.nouveau.resources.IndexResource;
import org.apache.lucene.search.SearcherFactory;
@@ -29,19 +29,20 @@
@Test
public void testIndexHealthCheck(@TempDir final Path tempDir) throws Exception {
- var scheduler = Executors.newSingleThreadScheduledExecutor();
var manager = new IndexManager();
+ manager.setCommitIntervalSeconds(1);
manager.setObjectMapper(new ObjectMapper());
manager.setMetricRegistry(new MetricRegistry());
manager.setRootDir(tempDir);
- manager.setScheduler(scheduler);
+ manager.setScheduler(Scheduler.systemScheduler());
+ manager.setSearcherFactory(new SearcherFactory());
manager.start();
+
try {
- var resource = new IndexResource(manager, new SearcherFactory());
+ var resource = new IndexResource(manager);
var check = new IndexHealthCheck(resource);
assertTrue(check.check().isHealthy());
} finally {
- scheduler.shutdown();
manager.stop();
}
}
diff --git a/nouveau/src/test/java/org/apache/couchdb/nouveau/lucene9/Lucene9IndexTest.java b/nouveau/src/test/java/org/apache/couchdb/nouveau/lucene9/Lucene9IndexTest.java
index eaaad17..ece5fb3 100644
--- a/nouveau/src/test/java/org/apache/couchdb/nouveau/lucene9/Lucene9IndexTest.java
+++ b/nouveau/src/test/java/org/apache/couchdb/nouveau/lucene9/Lucene9IndexTest.java
@@ -33,7 +33,6 @@
import org.apache.couchdb.nouveau.api.SearchResults;
import org.apache.couchdb.nouveau.api.StringField;
import org.apache.couchdb.nouveau.core.Index;
-import org.apache.couchdb.nouveau.core.IndexLoader;
import org.apache.couchdb.nouveau.core.UpdatesOutOfOrderException;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.IndexWriter;
@@ -50,12 +49,17 @@
protected final Index setup(final Path path) throws IOException {
final IndexDefinition indexDefinition = new IndexDefinition();
indexDefinition.setDefaultAnalyzer("standard");
- final Index index = indexLoader().apply(path, indexDefinition);
- index.setDeleteOnClose(true);
- return index;
+ final Analyzer analyzer = Lucene9AnalyzerFactory.fromDefinition(indexDefinition);
+ final Directory dir = new DirectIODirectory(FSDirectory.open(path));
+ final IndexWriterConfig config = new IndexWriterConfig(analyzer);
+ config.setUseCompoundFile(false);
+ final IndexWriter writer = new IndexWriter(dir, config);
+ final SearcherManager searcherManager = new SearcherManager(writer, null);
+ return new Lucene9Index(analyzer, writer, 0L, 0L, searcherManager);
}
protected final void cleanup(final Index index) throws IOException {
+ index.setDeleteOnClose(true);
index.close();
}
@@ -236,16 +240,4 @@
cleanup(index);
}
}
-
- protected IndexLoader indexLoader() {
- return (path, indexDefinition) -> {
- final Analyzer analyzer = Lucene9AnalyzerFactory.fromDefinition(indexDefinition);
- final Directory dir = new DirectIODirectory(FSDirectory.open(path));
- final IndexWriterConfig config = new IndexWriterConfig(analyzer);
- config.setUseCompoundFile(false);
- final IndexWriter writer = new IndexWriter(dir, config);
- final SearcherManager searcherManager = new SearcherManager(writer, null);
- return new Lucene9Index(analyzer, writer, 0L, 0L, searcherManager);
- };
- }
}