mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +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.ContentManagement.MetaData;
|
||||||
using Orchard.Core.Title.Models;
|
using Orchard.Core.Title.Models;
|
||||||
using Orchard.Data;
|
using Orchard.Data;
|
||||||
|
using Orchard.Environment.State;
|
||||||
|
using Orchard.Environment.Configuration;
|
||||||
|
using Orchard.Environment.Descriptor;
|
||||||
|
|
||||||
namespace Orchard.Taxonomies.Handlers {
|
namespace Orchard.Taxonomies.Handlers {
|
||||||
public class TermsPartHandler : ContentHandler {
|
public class TermsPartHandler : ContentHandler {
|
||||||
@@ -19,14 +22,17 @@ namespace Orchard.Taxonomies.Handlers {
|
|||||||
IContentDefinitionManager contentDefinitionManager,
|
IContentDefinitionManager contentDefinitionManager,
|
||||||
IRepository<TermsPartRecord> repository,
|
IRepository<TermsPartRecord> repository,
|
||||||
ITaxonomyService taxonomyService,
|
ITaxonomyService taxonomyService,
|
||||||
IContentManager contentManager) {
|
IContentManager contentManager,
|
||||||
|
IProcessingEngine processingEngine,
|
||||||
|
ShellSettings shellSettings,
|
||||||
|
IShellDescriptorManager shellDescriptorManager) {
|
||||||
_contentDefinitionManager = contentDefinitionManager;
|
_contentDefinitionManager = contentDefinitionManager;
|
||||||
_contentManager = contentManager;
|
_contentManager = contentManager;
|
||||||
|
|
||||||
Filters.Add(StorageFilter.For(repository));
|
Filters.Add(StorageFilter.For(repository));
|
||||||
OnPublished<TermsPart>((context, part) => RecalculateCount(taxonomyService, part));
|
OnPublished<TermsPart>((context, part) => RecalculateCount(processingEngine, shellSettings, shellDescriptorManager, part));
|
||||||
OnUnpublished<TermsPart>((context, part) => RecalculateCount(taxonomyService, part));
|
OnUnpublished<TermsPart>((context, part) => RecalculateCount(processingEngine, shellSettings, shellDescriptorManager, part));
|
||||||
OnRemoved<TermsPart>((context, part) => RecalculateCount(taxonomyService, 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
|
// 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));
|
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) {
|
// Fires off a processing engine task to run the count processing after the request so it's non-blocking.
|
||||||
foreach (var term in part.Terms) {
|
private void RecalculateCount(IProcessingEngine processingEngine, ShellSettings shellSettings, IShellDescriptorManager shellDescriptorManager, TermsPart part) {
|
||||||
var termPart = taxonomyService.GetTerm(term.TermRecord.Id);
|
processingEngine.AddTask(shellSettings, shellDescriptorManager.GetShellDescriptor(), "ITermCountProcessor.Process", new Dictionary<string, object> { { "termsPartId", part.ContentItem.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Activating(ActivatingContentContext context) {
|
protected override void Activating(ActivatingContentContext context) {
|
||||||
|
|||||||
@@ -99,7 +99,9 @@
|
|||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Fields\TaxonomyField.cs" />
|
<Compile Include="Fields\TaxonomyField.cs" />
|
||||||
<Compile Include="Services\ITaxonomyService.cs" />
|
<Compile Include="Services\ITaxonomyService.cs" />
|
||||||
|
<Compile Include="Services\ITermCountProcessor.cs" />
|
||||||
<Compile Include="Services\TaxonomyService.cs" />
|
<Compile Include="Services\TaxonomyService.cs" />
|
||||||
|
<Compile Include="Services\TermCountProcessor.cs" />
|
||||||
<Compile Include="Settings\TermPartEditorEvents.cs" />
|
<Compile Include="Settings\TermPartEditorEvents.cs" />
|
||||||
<Compile Include="Settings\TaxonomyFieldEditorEvents.cs" />
|
<Compile Include="Settings\TaxonomyFieldEditorEvents.cs" />
|
||||||
<Compile Include="Settings\TermPartSettings.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