Deferring Taxonomies term count calculation to a processing engine task, lowering the chance of DB deadlocks

This commit is contained in:
Lombiq
2015-02-20 00:27:11 +01:00
committed by Zoltán Lehóczky
parent aaf9387cc4
commit 0d52799fb0
4 changed files with 68 additions and 17 deletions

View File

@@ -9,6 +9,9 @@ using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.MetaData;
using Orchard.Core.Title.Models;
using Orchard.Data;
using Orchard.Environment.State;
using Orchard.Environment.Configuration;
using Orchard.Environment.Descriptor;
namespace Orchard.Taxonomies.Handlers {
public class TermsPartHandler : ContentHandler {
@@ -19,14 +22,17 @@ namespace Orchard.Taxonomies.Handlers {
IContentDefinitionManager contentDefinitionManager,
IRepository<TermsPartRecord> repository,
ITaxonomyService taxonomyService,
IContentManager contentManager) {
IContentManager contentManager,
IProcessingEngine processingEngine,
ShellSettings shellSettings,
IShellDescriptorManager shellDescriptorManager) {
_contentDefinitionManager = contentDefinitionManager;
_contentManager = contentManager;
Filters.Add(StorageFilter.For(repository));
OnPublished<TermsPart>((context, part) => RecalculateCount(taxonomyService, part));
OnUnpublished<TermsPart>((context, part) => RecalculateCount(taxonomyService, part));
OnRemoved<TermsPart>((context, part) => RecalculateCount(taxonomyService, part));
OnPublished<TermsPart>((context, part) => RecalculateCount(processingEngine, shellSettings, shellDescriptorManager, part));
OnUnpublished<TermsPart>((context, part) => RecalculateCount(processingEngine, shellSettings, shellDescriptorManager, part));
OnRemoved<TermsPart>((context, part) => RecalculateCount(processingEngine, shellSettings, shellDescriptorManager, part));
// Tells how to load the field terms on demand, when a content item it loaded or when it has been created
OnInitialized<TermsPart>((context, part) => InitializerTermsLoader(part));
@@ -82,20 +88,11 @@ namespace Orchard.Taxonomies.Handlers {
});
}
// Retrieve the number of associated content items, for the whole hierarchy
private static void RecalculateCount(ITaxonomyService taxonomyService, TermsPart part) {
foreach (var term in part.Terms) {
var termPart = taxonomyService.GetTerm(term.TermRecord.Id);
while (termPart != null) {
termPart.Count = (int)taxonomyService.GetContentItemsCount(termPart);
// Fires off a processing engine task to run the count processing after the request so it's non-blocking.
private void RecalculateCount(IProcessingEngine processingEngine, ShellSettings shellSettings, IShellDescriptorManager shellDescriptorManager, TermsPart part) {
processingEngine.AddTask(shellSettings, shellDescriptorManager.GetShellDescriptor(), "ITermCountProcessor.Process", new Dictionary<string, object> { { "termsPartId", part.ContentItem.Id } });
// compute count for the hierarchy too
if (termPart.Container != null) {
var parentTerm = termPart.Container.As<TermPart>();
termPart = parentTerm;
}
}
}
}
protected override void Activating(ActivatingContentContext context) {

View File

@@ -99,7 +99,9 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Fields\TaxonomyField.cs" />
<Compile Include="Services\ITaxonomyService.cs" />
<Compile Include="Services\ITermCountProcessor.cs" />
<Compile Include="Services\TaxonomyService.cs" />
<Compile Include="Services\TermCountProcessor.cs" />
<Compile Include="Settings\TermPartEditorEvents.cs" />
<Compile Include="Settings\TaxonomyFieldEditorEvents.cs" />
<Compile Include="Settings\TermPartSettings.cs" />

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Orchard.Events;
namespace Orchard.Taxonomies.Services {
public interface ITermCountProcessor : IEventHandler {
void Process(int termsPartId);
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Orchard.ContentManagement;
using Orchard.Taxonomies.Models;
namespace Orchard.Taxonomies.Services {
public class TermCountProcessor : ITermCountProcessor {
private readonly IContentManager _contentManager;
private readonly ITaxonomyService _taxonomyService;
public TermCountProcessor(IContentManager contentManager, ITaxonomyService taxonomyService) {
_contentManager = contentManager;
_taxonomyService = taxonomyService;
}
public void Process(int termsPartId) {
var termsPart = _contentManager.Get<TermsPart>(termsPartId);
if (termsPart == null) {
return;
}
// Retrieve the number of associated content items, for the whole hierarchy
foreach (var term in termsPart.Terms) {
var termPart = _taxonomyService.GetTerm(term.TermRecord.Id);
while (termPart != null) {
termPart.Count = (int)_taxonomyService.GetContentItemsCount(termPart);
// compute count for the hierarchy too
if (termPart.Container != null) {
var parentTerm = termPart.Container.As<TermPart>();
termPart = parentTerm;
}
}
}
}
}
}