mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Deferring Taxonomies term count calculation to a processing engine task, lowering the chance of DB deadlocks
This commit is contained in:
@@ -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) {
|
||||
|
@@ -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" />
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user