Replication
Replication copies a Lucene index from a source directory to a destination directory. The typical use is keeping a fast local index in sync with an index held in slower or shared storage, so that searching is served from local disk while writes go to the durable copy.
Replication is provided by ExamineReplicator, which wraps the Lucene.NET Replicator library.
Note: the destination directory must not have any active writers open to it.
Requirements
The source index must be configured with an IndexDeletionPolicy that retains commit points, otherwise there is nothing for the replicator to publish. A SnapshotDeletionPolicy is the usual choice.
services.AddExamineLuceneIndex("MyIndex", options =>
{
options.IndexDeletionPolicy = new SnapshotDeletionPolicy(
new KeepOnlyLastCommitDeletionPolicy());
});
Replicating an index
using var replicator = new ExamineReplicator(
replicatorLogger,
clientLogger,
sourceIndex, // LuceneIndex
sourceDirectory, // Lucene.Net.Store.Directory
destinationDirectory, // Lucene.Net.Store.Directory
destinationTaxonomyDirectory, // Lucene.Net.Store.Directory, or null
new DirectoryInfo(tempStoragePath));
// Sync once, on demand
replicator.ReplicateIndex();
ReplicateIndex() performs a single synchronization. It throws an InvalidOperationException if the destination directory - or the destination taxonomy directory, when taxonomy replication is enabled - is locked.
Taxonomy replication
When the source index uses the taxonomy sidecar index, the taxonomy index must be replicated alongside the main index or facet queries against the destination will not resolve correctly.
Pass a destinationTaxonomyDirectory to enable this. Pass null when the source index is not using a taxonomy index.
Scheduled replication
StartIndexReplicationOnSchedule(int milliseconds) subscribes to the source index's IndexCommitted event and publishes a new revision on every commit, with the destination polling on the given interval.
// Check for new revisions every 5 seconds
replicator.StartIndexReplicationOnSchedule(5000);
Monitoring replication health
Scheduled replication tolerates transient failures - a destination briefly locked by another process, for example - by retrying on the next commit. A persistent failure is a different matter: retrying forever would hide the problem while the destination index silently falls further behind.
ExamineReplicator therefore counts consecutive publish failures and stops replicating once the limit is reached:
ConsecutiveReplicationFailures- how many times in a row publishing a revision has failed. Reset to zero on a successful publish, and when scheduled replication is restarted.MaxConsecutiveReplicationFailures- the tolerated number of consecutive failures. Defaults to5. A value of0or less means replication is never stopped automatically.IsReplicationHealthy-falseonce that limit has been hit and replication has been stopped.
When the limit is reached, the replicator unsubscribes from IndexCommitted and stops its background update thread. A Critical log entry is written, and the destination index is no longer updated until replication is restarted by calling StartIndexReplicationOnSchedule again.
IsReplicationHealthy is intended to be surfaced through whatever health checking you already have, so that a stalled replica is visible rather than silent.
if (!replicator.IsReplicationHealthy)
{
// Replication has stopped after
// replicator.MaxConsecutiveReplicationFailures consecutive failures.
// Investigate, then restart:
replicator.StartIndexReplicationOnSchedule(5000);
}
Synced directory factory
For the common case of syncing between a main storage location and a local one, SyncedFileSystemDirectoryFactory wires this up for you - it maintains a local index directory that is kept in sync with a main directory, without you having to manage an ExamineReplicator directly.
services.AddExamineLuceneIndex<LuceneIndex, SyncedFileSystemDirectoryFactory>("MyIndex");