运行使用某些用户数据(域对象)更新Lucene索引的进程时,我收到以下错误。
Lucene.Net.Store.LockObtainFailedException:Lock获取超时: AzureLock@write.lock。在Lucene.Net.Store.Lock.Obtain(Int64 lockWaitTimeout)in d:\ Lucene.Net \ FullRepo \ trunk \ src \ core \ Store \ Lock.cs:第97行at Lucene.Net.Index.IndexWriter.Init(目录d,分析器a,布尔值 create,IndexDeletionPolicy deletionPolicy,Int32 maxFieldLength, IndexingChain indexingChain,IndexCommit commit)in d:\ Lucene.Net \ FullRepo \ trunk \ src \ core \ Index \ IndexWriter.cs:第1228行 在Lucene.Net.Index.IndexWriter..ctor(目录d,分析器a, MaxFieldLength mfl)in d:\ Lucene.Net \ FullRepo \ trunk \ src \ core \ Index \ IndexWriter.cs:第174行 在 MyApp.ApplicationServices.Search.Users.UsersSearchEngineService.EnsureIndexWriter() 在 MyApp.ApplicationServices.Search.Users.UsersSearchEngineService.DoWriterAction(Action`1 行动)....
我继承了以下代码,而且我对Lucene的了解不是很好,所以任何指针都会受到赞赏。
public class UsersSearchEngineService : IUsersSearchEngineService
{
private readonly Directory directory;
private readonly Analyzer analyzer;
private static IndexWriter indexWriter;
private static readonly Object WriterLock = new Object();
private bool disposed;
public UsersSearchEngineService (ILuceneDirectoryProvider directoryProvider)
{
directory = directoryProvider.GetDirectory();
analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);
}
public int UpdateIndex(IEnumerable<User> itemsToIndex)
{
var updatedCount = 0;
foreach (var itemToIndex in itemsToIndex)
{
try
{
ExecuteRemoveItem(itemToIndex.UserId);
var document = CreateIndexDocument(itemToIndex);
DoWriterAction(writer => writer.AddDocument(document));
updatedCount++;
}
catch (Exception ex)
{
EventLogProvider.Error("Error updating index for User with id:[{0}]", ex, itemToIndex.UserId);
}
}
DoWriterAction(writer =>
{
writer.Commit();
writer.Optimize();
});
return updatedCount;
}
private static Document CreateIndexDocument(User itemToIndex)
{
var document = new Document();
document.Add(new Field("id", itemToIndex.UserId.ToString(CultureInfo.InvariantCulture), Field.Store.YES, Field.Index.NOT_ANALYZED));
//...
//omitted other fields being added here
//...
return document;
}
void ExecuteRemoveItem(int entryId)
{
var searchQuery = GetIdSearchQuery(entryId);
DoWriterAction(writer => writer.DeleteDocuments(searchQuery));
}
void DoWriterAction(Action<IndexWriter> action)
{
lock (WriterLock)
{
EnsureIndexWriter();
}
action(indexWriter);
}
void EnsureIndexWriter()
{
if (indexWriter != null)
{
return;
}
indexWriter = new IndexWriter(this.directory, this.analyzer, IndexWriter.MaxFieldLength.UNLIMITED);
indexWriter.SetMergePolicy(new LogDocMergePolicy(indexWriter) { MergeFactor = 5 });
var retryStrategy = new ExponentialBackoff(5, TimeSpan.FromMilliseconds(200), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(10));
var retryPolicy = new RetryPolicy<LuceneWriterLockedErrorDetectionStrategy>(retryStrategy);
retryPolicy.Retrying += (sender, args) => EventLogProvider.Warn("Retrying lock delete Attempt: " + args.CurrentRetryCount);
if (IndexWriter.IsLocked(this.directory))
{
retryPolicy.ExecuteAction(() =>
{
EventLogProvider.Info("Something left a lock in the index folder: Attempting to it");
IndexWriter.Unlock(directory);
EventLogProvider.Info("Lock Deleted... can proceed");
});
}
}
~UsersSearchEngineService ()
{
Dispose();
}
public void Dispose()
{
lock (WriterLock)
{
if (!disposed)
{
var writer = indexWriter;
if (writer != null)
{
try
{
writer.Dispose();
}
catch (ObjectDisposedException e)
{
EventLogProvider.Error("Exception while disposing SearchEngineService", e);
}
indexWriter = null;
}
var disposeDirectory = directory;
if (disposeDirectory != null)
{
try
{
disposeDirectory.Dispose();
}
catch (ObjectDisposedException e)
{
EventLogProvider.Error("Exception while disposing SearchEngineService", e);
}
}
disposed = true;
}
}
GC.SuppressFinalize(this);
}
}
如果相关:
应用程序作为Azure Web App托管,运行2个实例
索引存储在Azure存储
EnsureIndexWriter方法看起来是否正确?如果没有,应该如何重做?