mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-12-03 12:03:51 +08:00
Using IProcessEngine to schedule batched indexing; Modifying
IIndexingTaskExecutor to handle index deletiong in order to prevent concurrency issues. --HG-- branch : indexing
This commit is contained in:
@@ -34,7 +34,7 @@ namespace Orchard.Tests.Modules.Indexing {
|
|||||||
private IIndexProvider _provider;
|
private IIndexProvider _provider;
|
||||||
private IAppDataFolder _appDataFolder;
|
private IAppDataFolder _appDataFolder;
|
||||||
private ShellSettings _shellSettings;
|
private ShellSettings _shellSettings;
|
||||||
private IIndexNotifierHandler _indexNotifier;
|
private IIndexingTaskExecutor _indexTaskExecutor;
|
||||||
private IContentManager _contentManager;
|
private IContentManager _contentManager;
|
||||||
private Mock<IContentDefinitionManager> _contentDefinitionManager;
|
private Mock<IContentDefinitionManager> _contentDefinitionManager;
|
||||||
private StubLogger _logger;
|
private StubLogger _logger;
|
||||||
@@ -43,7 +43,6 @@ namespace Orchard.Tests.Modules.Indexing {
|
|||||||
private const string IndexName = "Search";
|
private const string IndexName = "Search";
|
||||||
private readonly string _basePath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
private readonly string _basePath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||||
|
|
||||||
|
|
||||||
[TestFixtureTearDown]
|
[TestFixtureTearDown]
|
||||||
public void Clean() {
|
public void Clean() {
|
||||||
if (Directory.Exists(_basePath)) {
|
if (Directory.Exists(_basePath)) {
|
||||||
@@ -61,7 +60,7 @@ namespace Orchard.Tests.Modules.Indexing {
|
|||||||
|
|
||||||
builder.RegisterType<LuceneIndexProvider>().As<IIndexProvider>();
|
builder.RegisterType<LuceneIndexProvider>().As<IIndexProvider>();
|
||||||
builder.RegisterInstance(_appDataFolder).As<IAppDataFolder>();
|
builder.RegisterInstance(_appDataFolder).As<IAppDataFolder>();
|
||||||
builder.RegisterType<IndexingTaskExecutor>().As<IIndexNotifierHandler>();
|
builder.RegisterType<IndexingTaskExecutor>().As<IIndexingTaskExecutor>();
|
||||||
builder.RegisterType<DefaultIndexManager>().As<IIndexManager>();
|
builder.RegisterType<DefaultIndexManager>().As<IIndexManager>();
|
||||||
builder.RegisterType<IndexingTaskManager>().As<IIndexingTaskManager>();
|
builder.RegisterType<IndexingTaskManager>().As<IIndexingTaskManager>();
|
||||||
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
|
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
|
||||||
@@ -105,9 +104,9 @@ namespace Orchard.Tests.Modules.Indexing {
|
|||||||
base.Init();
|
base.Init();
|
||||||
_lockFileManager = _container.Resolve<ILockFileManager>();
|
_lockFileManager = _container.Resolve<ILockFileManager>();
|
||||||
_provider = _container.Resolve<IIndexProvider>();
|
_provider = _container.Resolve<IIndexProvider>();
|
||||||
_indexNotifier = _container.Resolve<IIndexNotifierHandler>();
|
_indexTaskExecutor = _container.Resolve<IIndexingTaskExecutor>();
|
||||||
_contentManager = _container.Resolve<IContentManager>();
|
_contentManager = _container.Resolve<IContentManager>();
|
||||||
((IndexingTaskExecutor)_indexNotifier).Logger = _logger = new StubLogger();
|
((IndexingTaskExecutor)_indexTaskExecutor).Logger = _logger = new StubLogger();
|
||||||
|
|
||||||
var thingType = new ContentTypeDefinitionBuilder()
|
var thingType = new ContentTypeDefinitionBuilder()
|
||||||
.Named(ThingDriver.ContentTypeName)
|
.Named(ThingDriver.ContentTypeName)
|
||||||
@@ -121,7 +120,7 @@ namespace Orchard.Tests.Modules.Indexing {
|
|||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void IndexShouldBeEmptyWhenThereIsNoContent() {
|
public void IndexShouldBeEmptyWhenThereIsNoContent() {
|
||||||
_indexNotifier.UpdateIndex(IndexName);
|
while(_indexTaskExecutor.UpdateIndexBatch(IndexName)) {}
|
||||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(0));
|
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +136,7 @@ namespace Orchard.Tests.Modules.Indexing {
|
|||||||
|
|
||||||
_contentManager.Create("alpha");
|
_contentManager.Create("alpha");
|
||||||
|
|
||||||
_indexNotifier.UpdateIndex(IndexName);
|
while (_indexTaskExecutor.UpdateIndexBatch(IndexName)) {}
|
||||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(0));
|
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +153,7 @@ namespace Orchard.Tests.Modules.Indexing {
|
|||||||
|
|
||||||
_contentManager.Create("alpha");
|
_contentManager.Create("alpha");
|
||||||
|
|
||||||
_indexNotifier.UpdateIndex(IndexName);
|
while (_indexTaskExecutor.UpdateIndexBatch(IndexName)) {}
|
||||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(0));
|
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,22 +162,22 @@ namespace Orchard.Tests.Modules.Indexing {
|
|||||||
var content = _contentManager.Create<Thing>(ThingDriver.ContentTypeName);
|
var content = _contentManager.Create<Thing>(ThingDriver.ContentTypeName);
|
||||||
content.Text = "Lorem ipsum";
|
content.Text = "Lorem ipsum";
|
||||||
|
|
||||||
_indexNotifier.UpdateIndex(IndexName);
|
while (_indexTaskExecutor.UpdateIndexBatch(IndexName)) {}
|
||||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ShouldUpdateTheIndexWhenContentIsPublished() {
|
public void ShouldUpdateTheIndexWhenContentIsPublished() {
|
||||||
_contentManager.Create<Thing>(ThingDriver.ContentTypeName).Text = "Lorem ipsum";
|
_contentManager.Create<Thing>(ThingDriver.ContentTypeName).Text = "Lorem ipsum";
|
||||||
_indexNotifier.UpdateIndex(IndexName);
|
while (_indexTaskExecutor.UpdateIndexBatch(IndexName)) {}
|
||||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
||||||
|
|
||||||
// there should be nothing done
|
// there should be nothing done
|
||||||
_indexNotifier.UpdateIndex(IndexName);
|
while (_indexTaskExecutor.UpdateIndexBatch(IndexName)) {}
|
||||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
||||||
|
|
||||||
_contentManager.Create<Thing>(ThingDriver.ContentTypeName).Text = "Lorem ipsum";
|
_contentManager.Create<Thing>(ThingDriver.ContentTypeName).Text = "Lorem ipsum";
|
||||||
_indexNotifier.UpdateIndex(IndexName);
|
while (_indexTaskExecutor.UpdateIndexBatch(IndexName)) {}
|
||||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(2));
|
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,13 +186,13 @@ namespace Orchard.Tests.Modules.Indexing {
|
|||||||
ILockFile lockFile = null;
|
ILockFile lockFile = null;
|
||||||
_lockFileManager.TryAcquireLock("Sites/My Site/Search.settings.xml.lock", ref lockFile);
|
_lockFileManager.TryAcquireLock("Sites/My Site/Search.settings.xml.lock", ref lockFile);
|
||||||
using (lockFile) {
|
using (lockFile) {
|
||||||
_indexNotifier.UpdateIndex(IndexName);
|
while (_indexTaskExecutor.UpdateIndexBatch(IndexName)) {}
|
||||||
Assert.That(_logger.LogEntries.Count, Is.EqualTo(1));
|
Assert.That(_logger.LogEntries.Count, Is.EqualTo(1));
|
||||||
Assert.That(_logger.LogEntries, Has.Some.Matches<LogEntry>(entry => entry.LogFormat == "Index was requested but is already running"));
|
Assert.That(_logger.LogEntries, Has.Some.Matches<LogEntry>(entry => entry.LogFormat == "Index was requested but is already running"));
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogEntries.Clear();
|
_logger.LogEntries.Clear();
|
||||||
_indexNotifier.UpdateIndex(IndexName);
|
while (_indexTaskExecutor.UpdateIndexBatch(IndexName)) {}
|
||||||
Assert.That(_logger.LogEntries, Has.None.Matches<LogEntry>(entry => entry.LogFormat == "Index was requested but is already running"));
|
Assert.That(_logger.LogEntries, Has.None.Matches<LogEntry>(entry => entry.LogFormat == "Index was requested but is already running"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,18 +200,18 @@ namespace Orchard.Tests.Modules.Indexing {
|
|||||||
public void ShouldUpdateTheIndexWhenContentIsUnPublished() {
|
public void ShouldUpdateTheIndexWhenContentIsUnPublished() {
|
||||||
_contentManager.Create<Thing>(ThingDriver.ContentTypeName).Text = "Lorem ipsum";
|
_contentManager.Create<Thing>(ThingDriver.ContentTypeName).Text = "Lorem ipsum";
|
||||||
|
|
||||||
_indexNotifier.UpdateIndex(IndexName);
|
while (_indexTaskExecutor.UpdateIndexBatch(IndexName)) {}
|
||||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
||||||
|
|
||||||
var content = _contentManager.Create<Thing>(ThingDriver.ContentTypeName);
|
var content = _contentManager.Create<Thing>(ThingDriver.ContentTypeName);
|
||||||
content.Text = "Lorem ipsum";
|
content.Text = "Lorem ipsum";
|
||||||
|
|
||||||
_indexNotifier.UpdateIndex(IndexName);
|
while (_indexTaskExecutor.UpdateIndexBatch(IndexName)) {}
|
||||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(2));
|
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(2));
|
||||||
|
|
||||||
_contentManager.Unpublish(content.ContentItem);
|
_contentManager.Unpublish(content.ContentItem);
|
||||||
|
|
||||||
_indexNotifier.UpdateIndex(IndexName);
|
while (_indexTaskExecutor.UpdateIndexBatch(IndexName)) {}
|
||||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +222,7 @@ namespace Orchard.Tests.Modules.Indexing {
|
|||||||
var content = _contentManager.Create<Thing>(ThingDriver.ContentTypeName);
|
var content = _contentManager.Create<Thing>(ThingDriver.ContentTypeName);
|
||||||
content.Text = "Lorem ipsum " + i;
|
content.Text = "Lorem ipsum " + i;
|
||||||
}
|
}
|
||||||
_indexNotifier.UpdateIndex(IndexName);
|
while (_indexTaskExecutor.UpdateIndexBatch(IndexName)) {}
|
||||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(999));
|
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(999));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ namespace Orchard.Indexing.Commands {
|
|||||||
[CommandHelp("index rebuild \r\n\t" + "Rebuilds the search index")]
|
[CommandHelp("index rebuild \r\n\t" + "Rebuilds the search index")]
|
||||||
public string Rebuild() {
|
public string Rebuild() {
|
||||||
_indexingService.RebuildIndex(SearchIndexName);
|
_indexingService.RebuildIndex(SearchIndexName);
|
||||||
_indexingService.UpdateIndex(SearchIndexName);
|
|
||||||
|
|
||||||
return T("Index is now being rebuilt...").Text;
|
return T("Index is now being rebuilt...").Text;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ namespace Orchard.Indexing.Controllers {
|
|||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
_indexingService.RebuildIndex(DefaultIndexName);
|
_indexingService.RebuildIndex(DefaultIndexName);
|
||||||
_indexingService.UpdateIndex(DefaultIndexName);
|
|
||||||
|
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace Orchard.Indexing.Models
|
|||||||
Mode = (IndexingMode) Enum.Parse(typeof (IndexingMode), doc.Descendants(TagMode).First().Value),
|
Mode = (IndexingMode) Enum.Parse(typeof (IndexingMode), doc.Descendants(TagMode).First().Value),
|
||||||
LastIndexedId = Int32.Parse(doc.Descendants(TagLastIndexedId).First().Value),
|
LastIndexedId = Int32.Parse(doc.Descendants(TagLastIndexedId).First().Value),
|
||||||
LastContentId = Int32.Parse(doc.Descendants(TagLastContentId).First().Value),
|
LastContentId = Int32.Parse(doc.Descendants(TagLastContentId).First().Value),
|
||||||
LastIndexedUtc = DateTime.Parse(doc.Descendants(TagLastIndexedUtc).First().Value)
|
LastIndexedUtc = DateTime.Parse(doc.Descendants(TagLastIndexedUtc).First().Value).ToUniversalTime()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
@@ -44,7 +44,7 @@ namespace Orchard.Indexing.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() {
|
public string ToXml() {
|
||||||
return new XDocument(
|
return new XDocument(
|
||||||
new XElement(TagSettings,
|
new XElement(TagSettings,
|
||||||
new XElement(TagMode, Mode),
|
new XElement(TagMode, Mode),
|
||||||
|
|||||||
@@ -60,6 +60,9 @@
|
|||||||
<Compile Include="Models\IndexSettings.cs">
|
<Compile Include="Models\IndexSettings.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Services\UpdateIndexScheduler.cs" />
|
||||||
|
<Compile Include="Services\IIndexingTaskExecutor.cs" />
|
||||||
|
<Compile Include="Services\IUpdateIndexScheduler.cs" />
|
||||||
<Compile Include="Services\IIndexStatisticsProvider.cs" />
|
<Compile Include="Services\IIndexStatisticsProvider.cs" />
|
||||||
<Compile Include="Services\IndexServiceNotificationProvider.cs" />
|
<Compile Include="Services\IndexServiceNotificationProvider.cs" />
|
||||||
<Compile Include="Services\IndexingBackgroundTask.cs" />
|
<Compile Include="Services\IndexingBackgroundTask.cs" />
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Orchard.Indexing.Services {
|
||||||
|
public interface IIndexingTaskExecutor : IDependency {
|
||||||
|
bool DeleteIndex(string indexName);
|
||||||
|
bool UpdateIndexBatch(string indexName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
namespace Orchard.Indexing.Services {
|
||||||
|
public interface IUpdateIndexScheduler : IDependency {
|
||||||
|
void Schedule(string indexName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.UI.Notify;
|
using Orchard.UI.Notify;
|
||||||
|
|
||||||
@@ -9,38 +8,41 @@ namespace Orchard.Indexing.Services
|
|||||||
private readonly IIndexManager _indexManager;
|
private readonly IIndexManager _indexManager;
|
||||||
private readonly IEnumerable<IIndexNotifierHandler> _indexNotifierHandlers;
|
private readonly IEnumerable<IIndexNotifierHandler> _indexNotifierHandlers;
|
||||||
private readonly IIndexStatisticsProvider _indexStatisticsProvider;
|
private readonly IIndexStatisticsProvider _indexStatisticsProvider;
|
||||||
|
private readonly IIndexingTaskExecutor _indexingTaskExecutor;
|
||||||
|
|
||||||
public IndexingService(
|
public IndexingService(
|
||||||
IOrchardServices services,
|
IOrchardServices services,
|
||||||
IIndexManager indexManager,
|
IIndexManager indexManager,
|
||||||
IEnumerable<IIndexNotifierHandler> indexNotifierHandlers,
|
IEnumerable<IIndexNotifierHandler> indexNotifierHandlers,
|
||||||
IIndexStatisticsProvider indexStatisticsProvider) {
|
IIndexStatisticsProvider indexStatisticsProvider,
|
||||||
|
IIndexingTaskExecutor indexingTaskExecutor) {
|
||||||
Services = services;
|
Services = services;
|
||||||
_indexManager = indexManager;
|
_indexManager = indexManager;
|
||||||
_indexNotifierHandlers = indexNotifierHandlers;
|
_indexNotifierHandlers = indexNotifierHandlers;
|
||||||
_indexStatisticsProvider = indexStatisticsProvider;
|
_indexStatisticsProvider = indexStatisticsProvider;
|
||||||
|
_indexingTaskExecutor = indexingTaskExecutor;
|
||||||
T = NullLocalizer.Instance;
|
T = NullLocalizer.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IOrchardServices Services { get; set; }
|
public IOrchardServices Services { get; set; }
|
||||||
public Localizer T { get; set; }
|
public Localizer T { get; set; }
|
||||||
|
|
||||||
void IIndexingService.RebuildIndex(string indexName) {
|
public void RebuildIndex(string indexName) {
|
||||||
if (!_indexManager.HasIndexProvider()) {
|
if (!_indexManager.HasIndexProvider()) {
|
||||||
Services.Notifier.Warning(T("There is no search index to rebuild."));
|
Services.Notifier.Warning(T("There is no search index to rebuild."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var searchProvider = _indexManager.GetSearchIndexProvider();
|
if(_indexingTaskExecutor.DeleteIndex(indexName)) {
|
||||||
if (searchProvider.Exists(indexName))
|
Services.Notifier.Information(T("The index {0} has been rebuilt.", indexName));
|
||||||
searchProvider.DeleteIndex(indexName);
|
UpdateIndex(indexName);
|
||||||
|
}
|
||||||
searchProvider.CreateIndex(indexName); // or just reset the updated date and let the background process recreate the index
|
else {
|
||||||
|
Services.Notifier.Warning(T("The index {0} could no ben rebuilt. It might already be in use, please try again later.", indexName));
|
||||||
Services.Notifier.Information(T("The index {0} has been rebuilt.", indexName));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IIndexingService.UpdateIndex(string indexName) {
|
public void UpdateIndex(string indexName) {
|
||||||
|
|
||||||
foreach(var handler in _indexNotifierHandlers) {
|
foreach(var handler in _indexNotifierHandlers) {
|
||||||
handler.UpdateIndex(indexName);
|
handler.UpdateIndex(indexName);
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ namespace Orchard.Indexing.Services {
|
|||||||
/// and singleton locks would not be shared accross those two.
|
/// and singleton locks would not be shared accross those two.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public class IndexingTaskExecutor : IIndexNotifierHandler, IIndexStatisticsProvider {
|
public class IndexingTaskExecutor : IIndexingTaskExecutor, IIndexStatisticsProvider
|
||||||
|
{
|
||||||
private readonly IRepository<IndexingTaskRecord> _taskRepository;
|
private readonly IRepository<IndexingTaskRecord> _taskRepository;
|
||||||
private readonly IRepository<ContentItemVersionRecord> _contentRepository;
|
private readonly IRepository<ContentItemVersionRecord> _contentRepository;
|
||||||
private IIndexProvider _indexProvider;
|
private IIndexProvider _indexProvider;
|
||||||
@@ -32,7 +33,7 @@ namespace Orchard.Indexing.Services {
|
|||||||
private readonly ShellSettings _shellSettings;
|
private readonly ShellSettings _shellSettings;
|
||||||
private readonly ILockFileManager _lockFileManager;
|
private readonly ILockFileManager _lockFileManager;
|
||||||
private readonly IClock _clock;
|
private readonly IClock _clock;
|
||||||
private const int ContentItemsPerLoop = 100;
|
private const int ContentItemsPerLoop = 50;
|
||||||
private IndexingStatus _indexingStatus = IndexingStatus.Idle;
|
private IndexingStatus _indexingStatus = IndexingStatus.Idle;
|
||||||
|
|
||||||
public IndexingTaskExecutor(
|
public IndexingTaskExecutor(
|
||||||
@@ -57,9 +58,31 @@ namespace Orchard.Indexing.Services {
|
|||||||
|
|
||||||
public ILogger Logger { get; set; }
|
public ILogger Logger { get; set; }
|
||||||
|
|
||||||
public void UpdateIndex(string indexName) {
|
public bool DeleteIndex(string indexName) {
|
||||||
// What to do here to run next batch in a separate transaction
|
ILockFile lockFile = null;
|
||||||
while (UpdateIndexBatch(indexName)) {}
|
var settingsFilename = GetSettingsFileName(indexName);
|
||||||
|
var lockFilename = settingsFilename + ".lock";
|
||||||
|
|
||||||
|
// acquire a lock file on the index
|
||||||
|
if (!_lockFileManager.TryAcquireLock(lockFilename, ref lockFile)) {
|
||||||
|
Logger.Information("Could not delete the index. Already in use.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (lockFile) {
|
||||||
|
if (!_indexManager.HasIndexProvider()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var searchProvider = _indexManager.GetSearchIndexProvider();
|
||||||
|
if (searchProvider.Exists(indexName)) {
|
||||||
|
searchProvider.DeleteIndex(indexName);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteSettings(indexName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool UpdateIndexBatch(string indexName) {
|
public bool UpdateIndexBatch(string indexName) {
|
||||||
@@ -83,10 +106,8 @@ namespace Orchard.Indexing.Services {
|
|||||||
|
|
||||||
_indexProvider = _indexManager.GetSearchIndexProvider();
|
_indexProvider = _indexManager.GetSearchIndexProvider();
|
||||||
|
|
||||||
// should the index be rebuilt
|
if (indexSettings.Mode == IndexingMode.Rebuild && indexSettings.LastContentId == 0) {
|
||||||
if (!_indexProvider.Exists(indexName)) {
|
|
||||||
_indexProvider.CreateIndex(indexName);
|
_indexProvider.CreateIndex(indexName);
|
||||||
indexSettings = new IndexSettings();
|
|
||||||
|
|
||||||
// mark the last available task at the moment the process is started.
|
// mark the last available task at the moment the process is started.
|
||||||
// once the Rebuild is done, Update will start at this point of the table
|
// once the Rebuild is done, Update will start at this point of the table
|
||||||
@@ -120,7 +141,7 @@ namespace Orchard.Indexing.Services {
|
|||||||
// load all content items
|
// load all content items
|
||||||
var contentItems = _contentRepository
|
var contentItems = _contentRepository
|
||||||
.Fetch(
|
.Fetch(
|
||||||
versionRecord => versionRecord.Published && versionRecord.ContentItemRecord.Id > indexSettings.LastContentId,
|
versionRecord => versionRecord.Published && versionRecord.Id > indexSettings.LastContentId,
|
||||||
order => order.Asc(versionRecord => versionRecord.Id))
|
order => order.Asc(versionRecord => versionRecord.Id))
|
||||||
.Take(ContentItemsPerLoop)
|
.Take(ContentItemsPerLoop)
|
||||||
.Select(versionRecord => _contentManager.Get(versionRecord.ContentItemRecord.Id, VersionOptions.VersionRecord(versionRecord.Id)))
|
.Select(versionRecord => _contentManager.Get(versionRecord.ContentItemRecord.Id, VersionOptions.VersionRecord(versionRecord.Id)))
|
||||||
@@ -182,7 +203,7 @@ namespace Orchard.Indexing.Services {
|
|||||||
|
|
||||||
// save current state of the index
|
// save current state of the index
|
||||||
indexSettings.LastIndexedUtc = _clock.UtcNow;
|
indexSettings.LastIndexedUtc = _clock.UtcNow;
|
||||||
_appDataFolder.CreateFile(settingsFilename, indexSettings.ToString());
|
_appDataFolder.CreateFile(settingsFilename, indexSettings.ToXml());
|
||||||
|
|
||||||
if (deleteFromIndex.Count == 0 && addToIndex.Count == 0) {
|
if (deleteFromIndex.Count == 0 && addToIndex.Count == 0) {
|
||||||
// nothing more to do
|
// nothing more to do
|
||||||
@@ -218,10 +239,12 @@ namespace Orchard.Indexing.Services {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads the settings file or create a new default one if it doesn't exist
|
/// Loads the settings file or create a new default one if it doesn't exist
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IndexSettings LoadSettings(string indexName) {
|
public IndexSettings LoadSettings(string indexName)
|
||||||
|
{
|
||||||
var indexSettings = new IndexSettings();
|
var indexSettings = new IndexSettings();
|
||||||
var settingsFilename = GetSettingsFileName(indexName);
|
var settingsFilename = GetSettingsFileName(indexName);
|
||||||
if (_appDataFolder.FileExists(settingsFilename)) {
|
if (_appDataFolder.FileExists(settingsFilename))
|
||||||
|
{
|
||||||
var content = _appDataFolder.ReadFile(settingsFilename);
|
var content = _appDataFolder.ReadFile(settingsFilename);
|
||||||
indexSettings = IndexSettings.Parse(content);
|
indexSettings = IndexSettings.Parse(content);
|
||||||
}
|
}
|
||||||
@@ -229,6 +252,16 @@ namespace Orchard.Indexing.Services {
|
|||||||
return indexSettings;
|
return indexSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes the settings file
|
||||||
|
/// </summary>
|
||||||
|
public void DeleteSettings(string indexName) {
|
||||||
|
var settingsFilename = GetSettingsFileName(indexName);
|
||||||
|
if (_appDataFolder.FileExists(settingsFilename)) {
|
||||||
|
_appDataFolder.DeleteFile(settingsFilename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a IDocumentIndex instance for a specific content item id. If the content
|
/// Creates a IDocumentIndex instance for a specific content item id. If the content
|
||||||
/// item is no more published, it returns null.
|
/// item is no more published, it returns null.
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Orchard.Environment.Configuration;
|
||||||
|
using Orchard.Environment.Descriptor;
|
||||||
|
using Orchard.Environment.State;
|
||||||
|
|
||||||
|
namespace Orchard.Indexing.Services {
|
||||||
|
public class UpdateIndexScheduler : IUpdateIndexScheduler, IIndexNotifierHandler {
|
||||||
|
private readonly IProcessingEngine _processingEngine;
|
||||||
|
private readonly ShellSettings _shellSettings;
|
||||||
|
private readonly IShellDescriptorManager _shellDescriptorManager;
|
||||||
|
private readonly Lazy<IIndexingTaskExecutor> _indexingTaskExecutor;
|
||||||
|
|
||||||
|
public UpdateIndexScheduler(
|
||||||
|
IProcessingEngine processingEngine,
|
||||||
|
ShellSettings shellSettings,
|
||||||
|
IShellDescriptorManager shellDescriptorManager,
|
||||||
|
Lazy<IIndexingTaskExecutor> indexingTaskExecutor
|
||||||
|
) {
|
||||||
|
_processingEngine = processingEngine;
|
||||||
|
_shellSettings = shellSettings;
|
||||||
|
_shellDescriptorManager = shellDescriptorManager;
|
||||||
|
_indexingTaskExecutor = indexingTaskExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Schedule(string indexName) {
|
||||||
|
var shellDescriptor = _shellDescriptorManager.GetShellDescriptor();
|
||||||
|
_processingEngine.AddTask(
|
||||||
|
_shellSettings,
|
||||||
|
shellDescriptor,
|
||||||
|
"IIndexNotifierHandler.UpdateIndex",
|
||||||
|
new Dictionary<string, object> { { "indexName", indexName } }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateIndex(string indexName) {
|
||||||
|
if(_indexingTaskExecutor.Value.UpdateIndexBatch(indexName)) {
|
||||||
|
Schedule(indexName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user