From 0b8260f3fa800dcbd2d6238f88301fbadf8a8c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Ros?= Date: Mon, 20 Apr 2015 21:11:09 -0700 Subject: [PATCH 1/7] Create README.md --- README.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..aca411162 --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +# Orchard +Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform. + +## About The Orchard Project + +#### Please visit our website at http://orchardproject.net for the most current information about this project. + +Orchard is a free, open source, community-focused project aimed at delivering applications and reusable components +on the ASP.NET platform. It will create shared components for building ASP.NET applications and extensions, and +specific applications that leverage these components to meet the needs of end-users, scripters, and developers. +Additionally, we seek to create partnerships with existing application authors to help them achieve their goals. +Orchard is delivered under the [.NET Foundation](http://www.dotnetfoundation.org/). It is licensed under a +[New BSD license](http://www.opensource.org/licenses/bsd-license.php), which is approved by the OSI. The intended +output of the Orchard project is three-fold: + +* Individual .NET-based applications that appeal to end-users, scripters, and developers +* A set of re-usable components that makes it easy to build such applications +* A vibrant community to help define these applications and extensions +In the near term, the Orchard project is focused on delivering a .NET-based CMS application that will allow users +to rapidly create content-driven Websites, and an extensibility framework that will allow developers and customizers to provide additional functionality through modules and themes. You can learn more about the project on the [url:Orchard Project Website|http://www.orchardproject.net]. + +## Project Status +Orchard is currently in version 1.8.1. We invite participation by the developer community in shaping the project’s direction, so that we can publicly validate our designs and development approach. +Our 1.8.1 release is available from our Downloads page, and is easy to [url: Install Orchard using the Web Platform Installer | http://www.orchardproject.net/docs/Installing-Orchard.ashx]. We encourage interested developers to check out the source code on the Orchard Github site and get involved with the project. + +* [Download the latest release](https://github.com/OrchardCMS/Orchard/releases) +* [Feature roadmap](http://www.orchardproject.net/docs/feature-roadmap.ashx) +* [Docs and designs/specs](http://www.orchardproject.net/docs) +* [About us](http://www.orchardproject.net/about) +* [Contact us](mailto:ofeedbk@microsoft.com) + +## How To Get Involved +We hope that by engaging with the community in the very early stages of the project that we will be able to shape Orchard into a valuable set of tools and applications for the community. The Orchard team is committed to open community participation and accepts code contributions today. We encourage community participation at all levels from general project feedback to bug fixes and patches. + +* [Check out the code](https://github.com/OrchardCMS/Orchard) +* [Check out the docs](http://orchardproject.net/docs) +* [Find and file a bug](https://github.com/OrchardCMS/Orchard/issues) +* [Propose a feature idea](http://orchard.uservoice.com) +* [Ask and answer questions](http://www.orchardproject.net/discussions) +* [Participate in forum discussions](http://orchard.codeplex.com/discussions) +* [Submit a patch](http://www.orchardproject.net/docs/Contributing-patches.ashx) +* [Send us feedback](mailto:ofeedbk@microsoft.com) From 1c1ba30a8ca78250654f1d17cdaa18778be76b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Ros?= Date: Wed, 22 Apr 2015 15:44:07 -0700 Subject: [PATCH 2/7] Fixing links in README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index aca411162..7d255e283 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,11 @@ output of the Orchard project is three-fold: * A set of re-usable components that makes it easy to build such applications * A vibrant community to help define these applications and extensions In the near term, the Orchard project is focused on delivering a .NET-based CMS application that will allow users -to rapidly create content-driven Websites, and an extensibility framework that will allow developers and customizers to provide additional functionality through modules and themes. You can learn more about the project on the [url:Orchard Project Website|http://www.orchardproject.net]. +to rapidly create content-driven Websites, and an extensibility framework that will allow developers and customizers to provide additional functionality through modules and themes. You can learn more about the project on the [Orchard Project Website](http://www.orchardproject.net). ## Project Status Orchard is currently in version 1.8.1. We invite participation by the developer community in shaping the project’s direction, so that we can publicly validate our designs and development approach. -Our 1.8.1 release is available from our Downloads page, and is easy to [url: Install Orchard using the Web Platform Installer | http://www.orchardproject.net/docs/Installing-Orchard.ashx]. We encourage interested developers to check out the source code on the Orchard Github site and get involved with the project. +Our 1.8.1 release is available from our Downloads page, and is easy to [Install Orchard using the Web Platform Installer](http://www.orchardproject.net/docs/Installing-Orchard.ashx). We encourage interested developers to check out the source code on the Orchard Github site and get involved with the project. * [Download the latest release](https://github.com/OrchardCMS/Orchard/releases) * [Feature roadmap](http://www.orchardproject.net/docs/feature-roadmap.ashx) From 61b8f82fd7f4f1b7ac948d3557e02b10d07731d7 Mon Sep 17 00:00:00 2001 From: jtkech Date: Thu, 7 May 2015 21:24:08 +0200 Subject: [PATCH 3/7] #5234 Duplicate lines in WorkflowManager --- .../Modules/Orchard.Workflows/Services/WorkflowManager.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Workflows/Services/WorkflowManager.cs b/src/Orchard.Web/Modules/Orchard.Workflows/Services/WorkflowManager.cs index eea418460..8795555f6 100644 --- a/src/Orchard.Web/Modules/Orchard.Workflows/Services/WorkflowManager.cs +++ b/src/Orchard.Web/Modules/Orchard.Workflows/Services/WorkflowManager.cs @@ -73,11 +73,6 @@ namespace Orchard.Workflows.Services { return; } - // if no activity record is matching the event, do nothing - if (!startedWorkflows.Any() && !awaitingActivities.Any()) { - return; - } - // resume halted workflows foreach (var awaitingActivityRecord in awaitingActivities) { var workflowContext = new WorkflowContext { @@ -292,4 +287,4 @@ namespace Orchard.Workflows.Services { return FormParametersHelper.FromJsonString("{}"); } } -} \ No newline at end of file +} From 91e040e684a874bd410a2259f45070b0b7f55945 Mon Sep 17 00:00:00 2001 From: Lombiq Date: Mon, 11 May 2015 16:52:54 +0200 Subject: [PATCH 4/7] Fixing that the technical names of widgets couldn't contain hyphens, see #4981 --- .../Drivers/WidgetPartDriver.cs | 2 +- .../Utility/Extensions/StringExtensions.cs | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs index 9a3fba25c..4016c9f17 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs @@ -53,7 +53,7 @@ namespace Orchard.Widgets.Drivers { // if there is a name, ensure it's unique if(!string.IsNullOrWhiteSpace(widgetPart.Name)) { - widgetPart.Name = widgetPart.Name.ToSafeName(); + widgetPart.Name = widgetPart.Name.ToHtmlName(); var widgets = _contentManager.Query().Where(x => x.Name == widgetPart.Name && x.Id != widgetPart.Id).Count(); if(widgets > 0) { diff --git a/src/Orchard/Utility/Extensions/StringExtensions.cs b/src/Orchard/Utility/Extensions/StringExtensions.cs index 65a6c73e9..d1290b794 100644 --- a/src/Orchard/Utility/Extensions/StringExtensions.cs +++ b/src/Orchard/Utility/Extensions/StringExtensions.cs @@ -191,6 +191,34 @@ namespace Orchard.Utility.Extensions { return name; } + /// + /// Generates a valid Html name. + /// + /// + /// Uses a white list set of chars. + /// + public static string ToHtmlName(this string name) { + if (String.IsNullOrWhiteSpace(name)) + return String.Empty; + + name = RemoveDiacritics(name); + name = name.Strip(c => + c != '-' + && c != '_' + && !c.IsLetter() + && !Char.IsDigit(c) + ); + + name = name.Trim(); + + // don't allow non A-Z chars as first letter, as they are not allowed in prefixes + while (name.Length > 0 && !IsLetter(name[0])) { + name = name.Substring(1); + } + + return name; + } + /// /// Whether the char is a letter between A and Z or not /// From 40243f2224452033a4826d22f56fd31da2368c66 Mon Sep 17 00:00:00 2001 From: Lombiq Date: Mon, 11 May 2015 23:17:58 +0200 Subject: [PATCH 5/7] Indexing task creation now happens gradually in a background task, preventing timeout/out of memory when editing a content type with many items. Fixes #4729. --- .../Modules/Orchard.Indexing/Migrations.cs | 29 +++++++++- .../Models/IndexTaskBatchRecord.cs | 7 +++ .../Orchard.Indexing/Orchard.Indexing.csproj | 4 ++ .../CreateUpdateIndexTaskBackgroundTask.cs | 25 +++++++++ .../IIndexTaskBatchManagementService.cs | 21 ++++++++ .../IndexTaskBatchManagementService.cs | 53 +++++++++++++++++++ .../Orchard.Indexing/Settings/EditorEvents.cs | 48 +++++------------ 7 files changed, 150 insertions(+), 37 deletions(-) create mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Models/IndexTaskBatchRecord.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Services/CreateUpdateIndexTaskBackgroundTask.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Services/IIndexTaskBatchManagementService.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexTaskBatchManagementService.cs diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Migrations.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Migrations.cs index 5905ff0d2..1d57200ba 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Migrations.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Migrations.cs @@ -20,7 +20,18 @@ namespace Orchard.Indexing { .Column("ContentItemRecord_id") ); - return 2; + SchemaBuilder.CreateTable("IndexTaskBatchRecord", + table => table + .Column("Id", column => column.PrimaryKey().Identity()) + .Column("BatchStartIndex") + .Column("ContentType") + ) + .AlterTable("IndexTaskBatchRecord", + table => + table.CreateIndex("IDX_ContentType", "ContentType") + ); + + return 3; } public int UpdateFrom1() { @@ -35,5 +46,21 @@ namespace Orchard.Indexing { return 2; } + + public int UpdateFrom2() { + + SchemaBuilder.CreateTable("IndexTaskBatchRecord", + table => table + .Column("Id", column => column.PrimaryKey().Identity()) + .Column("BatchStartIndex") + .Column("ContentType") + ) + .AlterTable("IndexTaskBatchRecord", + table => + table.CreateIndex("IDX_ContentType", "ContentType") + ); + + return 3; + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Models/IndexTaskBatchRecord.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Models/IndexTaskBatchRecord.cs new file mode 100644 index 000000000..2ba820b46 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Models/IndexTaskBatchRecord.cs @@ -0,0 +1,7 @@ +namespace Orchard.Indexing.Models { + public class IndexTaskBatchRecord { + public virtual int Id { get; set; } + public virtual int BatchStartIndex { get; set; } + public virtual string ContentType { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj b/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj index eae542b6a..c783ef9c5 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj @@ -78,6 +78,9 @@ Code + + + @@ -91,6 +94,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Services/CreateUpdateIndexTaskBackgroundTask.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Services/CreateUpdateIndexTaskBackgroundTask.cs new file mode 100644 index 000000000..1418ad37f --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Services/CreateUpdateIndexTaskBackgroundTask.cs @@ -0,0 +1,25 @@ +using System.Linq; +using Orchard.Tasks; +using Orchard.Tasks.Indexing; + +namespace Orchard.Indexing.Services { + public class CreateUpdateIndexTaskBackgroundTask : IBackgroundTask { + private readonly IIndexTaskBatchManagementService _indexTaskBatchManagementService; + private readonly IIndexingTaskManager _indexingTaskManager; + + public CreateUpdateIndexTaskBackgroundTask(IIndexTaskBatchManagementService indexTaskBatchManagementService, IIndexingTaskManager indexingTaskManager) { + _indexTaskBatchManagementService = indexTaskBatchManagementService; + _indexingTaskManager = indexingTaskManager; + } + + public void Sweep() { + var contentItemsLists = _indexTaskBatchManagementService.GetNextBatchOfContentItemsToIndex(); + + foreach (var contentItemsList in contentItemsLists) { + foreach (var contentItem in contentItemsList) { + _indexingTaskManager.CreateUpdateIndexTask(contentItem); + } + } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Services/IIndexTaskBatchManagementService.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Services/IIndexTaskBatchManagementService.cs new file mode 100644 index 000000000..233b52262 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Services/IIndexTaskBatchManagementService.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using Orchard.ContentManagement; + +namespace Orchard.Indexing.Services { + /// + /// Manages the batches for indexing tasks. + /// + public interface IIndexTaskBatchManagementService : IDependency { + + /// + /// Registers a content type for the . + /// + /// The content type. + void RegisterContentType(string contentType); + + /// + /// Returns a list of a list of the registered content items. + /// + IEnumerable> GetNextBatchOfContentItemsToIndex(); + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexTaskBatchManagementService.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexTaskBatchManagementService.cs new file mode 100644 index 000000000..963499012 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexTaskBatchManagementService.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; +using System.Linq; +using Orchard.ContentManagement; +using Orchard.Data; +using Orchard.Indexing.Models; + +namespace Orchard.Indexing.Services { + public class IndexTaskBatchManagementService : IIndexTaskBatchManagementService { + private readonly IRepository _indexTaskBatchRecordRepository; + private readonly IContentManager _contentManager; + + private const int BatchSize = 50; + + public IndexTaskBatchManagementService(IRepository indexTaskBatchRecordRepository, IContentManager contentManager) { + _indexTaskBatchRecordRepository = indexTaskBatchRecordRepository; + _contentManager = contentManager; + } + + public void RegisterContentType(string contentType) { + var registeredContentType = _indexTaskBatchRecordRepository.Table.Where(i => i.ContentType == contentType).FirstOrDefault(); + + if (registeredContentType == null) { + _indexTaskBatchRecordRepository.Create(new IndexTaskBatchRecord { ContentType = contentType, BatchStartIndex = 0 }); + } + else { + registeredContentType.BatchStartIndex = 0; + } + + } + + public IEnumerable> GetNextBatchOfContentItemsToIndex() { + var indexTaskBatchRecords = _indexTaskBatchRecordRepository.Table; + if (indexTaskBatchRecords == null) return null; + + var contentItemsList = new List>(); + + foreach (var indexTaskBatchRecord in indexTaskBatchRecords) { + var contentItems = _contentManager.Query(indexTaskBatchRecord.ContentType).Slice(indexTaskBatchRecord.BatchStartIndex, BatchSize).ToList(); + + if (contentItems.Any()) contentItemsList.Add(contentItems); + + if (contentItems.Count == 0 || contentItems.Count < BatchSize) { + _indexTaskBatchRecordRepository.Delete(_indexTaskBatchRecordRepository.Table.FirstOrDefault(i => i.ContentType == indexTaskBatchRecord.ContentType)); + } + else { + indexTaskBatchRecord.BatchStartIndex += BatchSize; + } + } + + return contentItemsList; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs index d4de846b8..37a6d3426 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs @@ -1,27 +1,23 @@ -using System.Collections.Generic; -using System.Linq; +using System; +using System.Collections.Generic; using Orchard.ContentManagement; using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData.Builders; using Orchard.ContentManagement.MetaData.Models; using Orchard.ContentManagement.ViewModels; -using Orchard.Tasks.Indexing; +using Orchard.Indexing.Services; namespace Orchard.Indexing.Settings { public class EditorEvents : ContentDefinitionEditorEventsBase { - private readonly IIndexingTaskManager _indexingTaskManager; - private readonly IContentManager _contentManager; - - private const int PageSize = 50; - - public EditorEvents(IIndexingTaskManager indexingTaskManager, IContentManager contentManager){ - _indexingTaskManager = indexingTaskManager; - _contentManager = contentManager; - } + private readonly IIndexTaskBatchManagementService _indexTaskBatchManagementService; private string _contentTypeName; private bool _tasksCreated; + public EditorEvents(IIndexTaskBatchManagementService indexTaskBatchManagementService) { + _indexTaskBatchManagementService = indexTaskBatchManagementService; + } + public override IEnumerable TypeEditor(ContentTypeDefinition definition) { var model = definition.Settings.GetModel(); _contentTypeName = definition.Name; @@ -41,12 +37,12 @@ namespace Orchard.Indexing.Settings { // if a an index is added, all existing content items need to be re-indexed CreateIndexingTasks(); } - + yield return DefinitionTemplate(model); } private string Clean(string value) { - if (string.IsNullOrEmpty(value)) + if (String.IsNullOrEmpty(value)) return value; return value.Trim(',', ' '); @@ -57,7 +53,8 @@ namespace Orchard.Indexing.Settings { /// private void CreateIndexingTasks() { if (!_tasksCreated) { - CreateTasksForType(_contentTypeName); + // Creating tasks in batches is needed because editing content type settings for a type with many items causes OutOfMemoryException, see issue: https://github.com/OrchardCMS/Orchard/issues/4729 + _indexTaskBatchManagementService.RegisterContentType(_contentTypeName); _tasksCreated = true; } } @@ -83,26 +80,5 @@ namespace Orchard.Indexing.Settings { yield return DefinitionTemplate(model); } - - private void CreateTasksForType(string type) { - var index = 0; - bool contentItemProcessed; - - // todo: load ids only, or create a queued job - // we create a task even for draft items, and the executor will filter based on the settings - - do { - contentItemProcessed = false; - var contentItemsToIndex = _contentManager.Query(VersionOptions.Latest, new [] { type }).Slice(index, PageSize); - - foreach (var contentItem in contentItemsToIndex) { - contentItemProcessed = true; - _indexingTaskManager.CreateUpdateIndexTask(contentItem); - } - - index += PageSize; - - } while (contentItemProcessed); - } } } \ No newline at end of file From b98d35305a21c690847c369580ff8cc1a55fd286 Mon Sep 17 00:00:00 2001 From: Lombiq Date: Thu, 14 May 2015 12:54:02 +0200 Subject: [PATCH 6/7] Revert "Indexing task creation now happens gradually in a background task, preventing timeout/out of memory when editing a content type with many items. Fixes #4729." Commit moved to dev branch as it's not a completely safe change. This reverts commit 40243f2224452033a4826d22f56fd31da2368c66. --- .../Modules/Orchard.Indexing/Migrations.cs | 29 +--------- .../Models/IndexTaskBatchRecord.cs | 7 --- .../Orchard.Indexing/Orchard.Indexing.csproj | 4 -- .../CreateUpdateIndexTaskBackgroundTask.cs | 25 --------- .../IIndexTaskBatchManagementService.cs | 21 -------- .../IndexTaskBatchManagementService.cs | 53 ------------------- .../Orchard.Indexing/Settings/EditorEvents.cs | 48 ++++++++++++----- 7 files changed, 37 insertions(+), 150 deletions(-) delete mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Models/IndexTaskBatchRecord.cs delete mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Services/CreateUpdateIndexTaskBackgroundTask.cs delete mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Services/IIndexTaskBatchManagementService.cs delete mode 100644 src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexTaskBatchManagementService.cs diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Migrations.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Migrations.cs index 1d57200ba..5905ff0d2 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Migrations.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Migrations.cs @@ -20,18 +20,7 @@ namespace Orchard.Indexing { .Column("ContentItemRecord_id") ); - SchemaBuilder.CreateTable("IndexTaskBatchRecord", - table => table - .Column("Id", column => column.PrimaryKey().Identity()) - .Column("BatchStartIndex") - .Column("ContentType") - ) - .AlterTable("IndexTaskBatchRecord", - table => - table.CreateIndex("IDX_ContentType", "ContentType") - ); - - return 3; + return 2; } public int UpdateFrom1() { @@ -46,21 +35,5 @@ namespace Orchard.Indexing { return 2; } - - public int UpdateFrom2() { - - SchemaBuilder.CreateTable("IndexTaskBatchRecord", - table => table - .Column("Id", column => column.PrimaryKey().Identity()) - .Column("BatchStartIndex") - .Column("ContentType") - ) - .AlterTable("IndexTaskBatchRecord", - table => - table.CreateIndex("IDX_ContentType", "ContentType") - ); - - return 3; - } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Models/IndexTaskBatchRecord.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Models/IndexTaskBatchRecord.cs deleted file mode 100644 index 2ba820b46..000000000 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Models/IndexTaskBatchRecord.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Orchard.Indexing.Models { - public class IndexTaskBatchRecord { - public virtual int Id { get; set; } - public virtual int BatchStartIndex { get; set; } - public virtual string ContentType { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj b/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj index c783ef9c5..eae542b6a 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Orchard.Indexing.csproj @@ -78,9 +78,6 @@ Code - - - @@ -94,7 +91,6 @@ - diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Services/CreateUpdateIndexTaskBackgroundTask.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Services/CreateUpdateIndexTaskBackgroundTask.cs deleted file mode 100644 index 1418ad37f..000000000 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Services/CreateUpdateIndexTaskBackgroundTask.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Linq; -using Orchard.Tasks; -using Orchard.Tasks.Indexing; - -namespace Orchard.Indexing.Services { - public class CreateUpdateIndexTaskBackgroundTask : IBackgroundTask { - private readonly IIndexTaskBatchManagementService _indexTaskBatchManagementService; - private readonly IIndexingTaskManager _indexingTaskManager; - - public CreateUpdateIndexTaskBackgroundTask(IIndexTaskBatchManagementService indexTaskBatchManagementService, IIndexingTaskManager indexingTaskManager) { - _indexTaskBatchManagementService = indexTaskBatchManagementService; - _indexingTaskManager = indexingTaskManager; - } - - public void Sweep() { - var contentItemsLists = _indexTaskBatchManagementService.GetNextBatchOfContentItemsToIndex(); - - foreach (var contentItemsList in contentItemsLists) { - foreach (var contentItem in contentItemsList) { - _indexingTaskManager.CreateUpdateIndexTask(contentItem); - } - } - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Services/IIndexTaskBatchManagementService.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Services/IIndexTaskBatchManagementService.cs deleted file mode 100644 index 233b52262..000000000 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Services/IIndexTaskBatchManagementService.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Collections.Generic; -using Orchard.ContentManagement; - -namespace Orchard.Indexing.Services { - /// - /// Manages the batches for indexing tasks. - /// - public interface IIndexTaskBatchManagementService : IDependency { - - /// - /// Registers a content type for the . - /// - /// The content type. - void RegisterContentType(string contentType); - - /// - /// Returns a list of a list of the registered content items. - /// - IEnumerable> GetNextBatchOfContentItemsToIndex(); - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexTaskBatchManagementService.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexTaskBatchManagementService.cs deleted file mode 100644 index 963499012..000000000 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Services/IndexTaskBatchManagementService.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Orchard.ContentManagement; -using Orchard.Data; -using Orchard.Indexing.Models; - -namespace Orchard.Indexing.Services { - public class IndexTaskBatchManagementService : IIndexTaskBatchManagementService { - private readonly IRepository _indexTaskBatchRecordRepository; - private readonly IContentManager _contentManager; - - private const int BatchSize = 50; - - public IndexTaskBatchManagementService(IRepository indexTaskBatchRecordRepository, IContentManager contentManager) { - _indexTaskBatchRecordRepository = indexTaskBatchRecordRepository; - _contentManager = contentManager; - } - - public void RegisterContentType(string contentType) { - var registeredContentType = _indexTaskBatchRecordRepository.Table.Where(i => i.ContentType == contentType).FirstOrDefault(); - - if (registeredContentType == null) { - _indexTaskBatchRecordRepository.Create(new IndexTaskBatchRecord { ContentType = contentType, BatchStartIndex = 0 }); - } - else { - registeredContentType.BatchStartIndex = 0; - } - - } - - public IEnumerable> GetNextBatchOfContentItemsToIndex() { - var indexTaskBatchRecords = _indexTaskBatchRecordRepository.Table; - if (indexTaskBatchRecords == null) return null; - - var contentItemsList = new List>(); - - foreach (var indexTaskBatchRecord in indexTaskBatchRecords) { - var contentItems = _contentManager.Query(indexTaskBatchRecord.ContentType).Slice(indexTaskBatchRecord.BatchStartIndex, BatchSize).ToList(); - - if (contentItems.Any()) contentItemsList.Add(contentItems); - - if (contentItems.Count == 0 || contentItems.Count < BatchSize) { - _indexTaskBatchRecordRepository.Delete(_indexTaskBatchRecordRepository.Table.FirstOrDefault(i => i.ContentType == indexTaskBatchRecord.ContentType)); - } - else { - indexTaskBatchRecord.BatchStartIndex += BatchSize; - } - } - - return contentItemsList; - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs b/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs index 37a6d3426..d4de846b8 100644 --- a/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs +++ b/src/Orchard.Web/Modules/Orchard.Indexing/Settings/EditorEvents.cs @@ -1,23 +1,27 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; +using System.Linq; using Orchard.ContentManagement; using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData.Builders; using Orchard.ContentManagement.MetaData.Models; using Orchard.ContentManagement.ViewModels; -using Orchard.Indexing.Services; +using Orchard.Tasks.Indexing; namespace Orchard.Indexing.Settings { public class EditorEvents : ContentDefinitionEditorEventsBase { - private readonly IIndexTaskBatchManagementService _indexTaskBatchManagementService; + private readonly IIndexingTaskManager _indexingTaskManager; + private readonly IContentManager _contentManager; + + private const int PageSize = 50; + + public EditorEvents(IIndexingTaskManager indexingTaskManager, IContentManager contentManager){ + _indexingTaskManager = indexingTaskManager; + _contentManager = contentManager; + } private string _contentTypeName; private bool _tasksCreated; - public EditorEvents(IIndexTaskBatchManagementService indexTaskBatchManagementService) { - _indexTaskBatchManagementService = indexTaskBatchManagementService; - } - public override IEnumerable TypeEditor(ContentTypeDefinition definition) { var model = definition.Settings.GetModel(); _contentTypeName = definition.Name; @@ -37,12 +41,12 @@ namespace Orchard.Indexing.Settings { // if a an index is added, all existing content items need to be re-indexed CreateIndexingTasks(); } - + yield return DefinitionTemplate(model); } private string Clean(string value) { - if (String.IsNullOrEmpty(value)) + if (string.IsNullOrEmpty(value)) return value; return value.Trim(',', ' '); @@ -53,8 +57,7 @@ namespace Orchard.Indexing.Settings { /// private void CreateIndexingTasks() { if (!_tasksCreated) { - // Creating tasks in batches is needed because editing content type settings for a type with many items causes OutOfMemoryException, see issue: https://github.com/OrchardCMS/Orchard/issues/4729 - _indexTaskBatchManagementService.RegisterContentType(_contentTypeName); + CreateTasksForType(_contentTypeName); _tasksCreated = true; } } @@ -80,5 +83,26 @@ namespace Orchard.Indexing.Settings { yield return DefinitionTemplate(model); } + + private void CreateTasksForType(string type) { + var index = 0; + bool contentItemProcessed; + + // todo: load ids only, or create a queued job + // we create a task even for draft items, and the executor will filter based on the settings + + do { + contentItemProcessed = false; + var contentItemsToIndex = _contentManager.Query(VersionOptions.Latest, new [] { type }).Slice(index, PageSize); + + foreach (var contentItem in contentItemsToIndex) { + contentItemProcessed = true; + _indexingTaskManager.CreateUpdateIndexTask(contentItem); + } + + index += PageSize; + + } while (contentItemProcessed); + } } } \ No newline at end of file From f8c6feea8690ccce7766521d8fd7ed3ba40fefc7 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 29 Apr 2015 20:30:08 +0200 Subject: [PATCH 7/7] #5216: Added call to *InitHelpers*. This will cause various helpers to be initialized, such as the *Html* property. --- .../Orchard.Templates/Services/Razor/RazorTemplateBase.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Services/Razor/RazorTemplateBase.cs b/src/Orchard.Web/Modules/Orchard.Templates/Services/Razor/RazorTemplateBase.cs index 5e07235d4..e118a945b 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Services/Razor/RazorTemplateBase.cs +++ b/src/Orchard.Web/Modules/Orchard.Templates/Services/Razor/RazorTemplateBase.cs @@ -23,6 +23,7 @@ namespace Orchard.Templates.Compilation.Razor { public abstract class RazorTemplateBase : Mvc.ViewEngines.Razor.WebViewPage, IRazorTemplateBase { public WebPageContext WebPageContext { get; set; } public virtual void Render(TextWriter writer) { + InitHelpers(); PushContext(WebPageContext, writer); OutputStack.Push(writer); Execute();