Files
Orchard/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexingTaskExecutor.cs
Sebastien Ros 40769d6f2a Complete refactoring on Indexing module
Changed Parse() to use lucene syntax
Moved everything to Orchard.Indexing
New filters for search

--HG--
branch : dev
2010-06-17 16:21:29 -07:00

148 lines
5.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Orchard.ContentManagement;
using Orchard.Data;
using Orchard.Indexing.Models;
using Orchard.Logging;
using Orchard.Services;
using Orchard.Tasks.Indexing;
namespace Orchard.Indexing.Services {
/// <summary>
/// Contains the logic which is regularly executed to retrieve index information from multiple content handlers.
/// </summary>
[UsedImplicitly]
public class IndexingTaskExecutor : IIndexNotifierHandler {
private readonly IClock _clock;
private readonly IRepository<IndexingTaskRecord> _repository;
private IIndexProvider _indexProvider;
private readonly IIndexManager _indexManager;
private readonly IIndexingTaskManager _indexingTaskManager;
private readonly IContentManager _contentManager;
private readonly IIndexSynLock _indexSynLock;
private const string SearchIndexName = "Search";
public IndexingTaskExecutor(
IClock clock,
IRepository<IndexingTaskRecord> repository,
IIndexManager indexManager,
IIndexingTaskManager indexingTaskManager,
IContentManager contentManager,
IIndexSynLock indexSynLock) {
_clock = clock;
_repository = repository;
_indexManager = indexManager;
_indexingTaskManager = indexingTaskManager;
_contentManager = contentManager;
_indexSynLock = indexSynLock;
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
public void UpdateIndex(string indexName) {
var synLock = _indexSynLock.GetSynLock(SearchIndexName);
if ( !System.Threading.Monitor.TryEnter(synLock) ) {
Logger.Information("Index was requested but was already running");
return;
}
try {
if (!_indexManager.HasIndexProvider()) {
return;
}
_indexProvider = _indexManager.GetSearchIndexProvider();
var updateIndexDocuments = new List<IDocumentIndex>();
DateTime lastIndexing;
// Do we need to rebuild the full index (first time module is used, or rebuild index requested) ?
if (_indexProvider.IsEmpty(SearchIndexName)) {
Logger.Information("Rebuild index started");
// mark current last task, as we should process older ones (in case of rebuild index only)
lastIndexing = _indexingTaskManager.GetLastTaskDateTime();
// get every existing content item to index it
foreach (var contentItem in _contentManager.Query(VersionOptions.Published).List()) {
try {
var documentIndex = _indexProvider.New(contentItem.Id);
_contentManager.Index(contentItem, documentIndex);
if(documentIndex.IsDirty) {
updateIndexDocuments.Add(documentIndex);
}
}
catch (Exception ex) {
Logger.Warning(ex, "Unable to index content item #{0} during rebuild", contentItem.Id);
}
}
}
else {
// retrieve last processed index time
lastIndexing = _indexProvider.GetLastIndexUtc(SearchIndexName);
}
_indexProvider.SetLastIndexUtc(SearchIndexName, _clock.UtcNow);
// retrieve not yet processed tasks
var taskRecords = _repository.Fetch(x => x.CreatedUtc > lastIndexing)
.ToArray();
// nothing to do ?
if (taskRecords.Length + updateIndexDocuments.Count == 0)
return;
Logger.Information("Processing {0} indexing tasks", taskRecords.Length);
if (!_indexProvider.Exists(SearchIndexName)) {
_indexProvider.CreateIndex(SearchIndexName);
}
// process Delete tasks
try {
_indexProvider.Delete(SearchIndexName, taskRecords.Where(t => t.Action == IndexingTaskRecord.Delete).Select(t => t.Id));
}
catch (Exception ex) {
Logger.Warning(ex, "An error occured while removing a document from the index");
}
// process Update tasks
foreach (var taskRecord in taskRecords.Where(t => t.Action == IndexingTaskRecord.Update)) {
var task = new IndexingTask(_contentManager, taskRecord);
try {
var documentIndex = _indexProvider.New(task.ContentItem.Id);
_contentManager.Index(task.ContentItem, documentIndex);
if ( documentIndex.IsDirty ) {
updateIndexDocuments.Add(documentIndex);
}
}
catch (Exception ex) {
Logger.Warning(ex, "Unable to process indexing task #{0}", taskRecord.Id);
}
}
if (updateIndexDocuments.Count > 0) {
try {
_indexProvider.Store(SearchIndexName, updateIndexDocuments);
}
catch (Exception ex) {
Logger.Warning(ex, "An error occured while adding a document to the index");
}
}
}
finally {
System.Threading.Monitor.Exit(synLock);
}
}
}
}