Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workflow trimming (pruning) improvements #16565

Merged
merged 36 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
dacdf69
Some clean-up
Piedone Aug 14, 2024
5122df6
Renaming workflow pruning to trimming
Piedone Aug 14, 2024
2197485
Removing incorrect AddDays(1) from Workflows and Audit Trail trimming
Piedone Aug 14, 2024
203a13e
Adding configuration for the batch size
Piedone Aug 14, 2024
574449b
Docs
Piedone Aug 14, 2024
5fbc41b
Formatting
Piedone Aug 14, 2024
eebab50
Making WorkflowStatusBuilder public because it's needed for template …
Piedone Aug 14, 2024
7e0f140
It can remain sealed, though
Piedone Aug 14, 2024
ba03b9e
Explicit localizable status names
Piedone Aug 15, 2024
52ac3cc
More prune rename
Piedone Aug 15, 2024
2f02cfa
Ordering workflows to make sure the oldest are deleted first
Piedone Aug 15, 2024
e9191d8
Moving trimming service registrations to root Startup
Piedone Aug 15, 2024
a26a27c
Formatting
Piedone Aug 15, 2024
3dacf27
Renaming IWorkflowTrimmingManager to IWorkflowTrimmingService
Piedone Aug 15, 2024
746f10b
Removing unneeded <section>
Piedone Aug 15, 2024
b2fa6f0
Using Html.IdFor()s everywhere
Piedone Aug 15, 2024
1ea28fc
Formatting
Piedone Aug 15, 2024
8fa134b
Shorthand GetSection()
Piedone Aug 15, 2024
3616643
Moving LastRunUtc to its own document
Piedone Aug 15, 2024
3d28440
Moving trimming service registrations to AddTrimmingServices()
Piedone Aug 15, 2024
c4817ca
Formatting
Piedone Aug 15, 2024
aad7b0d
Refactoring
Piedone Aug 15, 2024
da58975
Some margins on the form
Piedone Aug 15, 2024
2d915ad
Formatting
Piedone Aug 15, 2024
a61cf0a
Formatting
Piedone Aug 15, 2024
4451d0a
Formatting
Piedone Aug 15, 2024
549412e
Formatting
Piedone Aug 15, 2024
445581e
Formatting
Piedone Aug 15, 2024
0bd774b
Revert "Formatting"
Piedone Aug 15, 2024
51cd4e3
Formatting
Piedone Aug 15, 2024
0b9682d
Merge remote-tracking branch 'official/main' into issue/OCORE-194
Piedone Aug 15, 2024
5482353
Formatting
Piedone Aug 15, 2024
a4d6d24
Revert
Piedone Aug 15, 2024
62026a0
Ordering by Id
Piedone Aug 15, 2024
5568774
Clarifying comment
Piedone Aug 15, 2024
f42a9c3
Grammar
Piedone Aug 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 2 additions & 16 deletions src/OrchardCore.Modules/OrchardCore.Workflows/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Fluid;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using OrchardCore.BackgroundTasks;
using OrchardCore.Data;
using OrchardCore.Data.Migration;
using OrchardCore.Deployment;
Expand All @@ -13,7 +12,6 @@
using OrchardCore.Recipes;
using OrchardCore.ResourceManagement;
using OrchardCore.Security.Permissions;
using OrchardCore.Settings;
using OrchardCore.Workflows.Activities;
using OrchardCore.Workflows.Deployment;
using OrchardCore.Workflows.Drivers;
Expand All @@ -26,9 +24,6 @@
using OrchardCore.Workflows.Models;
using OrchardCore.Workflows.Recipes;
using OrchardCore.Workflows.Services;
using OrchardCore.Workflows.Trimming;
using OrchardCore.Workflows.Trimming.Drivers;
using OrchardCore.Workflows.Trimming.Services;
using OrchardCore.Workflows.WorkflowContextProviders;

namespace OrchardCore.Workflows;
Expand All @@ -37,10 +32,7 @@ public sealed class Startup : StartupBase
{
private readonly IShellConfiguration _shellConfiguration;

public Startup(IShellConfiguration shellConfiguration)
{
_shellConfiguration = shellConfiguration;
}
public Startup(IShellConfiguration shellConfiguration) => _shellConfiguration = shellConfiguration;

public override void ConfigureServices(IServiceCollection services)
{
Expand Down Expand Up @@ -92,13 +84,7 @@ public override void ConfigureServices(IServiceCollection services)
services.AddRecipeExecutionStep<WorkflowTypeStep>();
services.AddTransient<IConfigureOptions<ResourceManagementOptions>, ResourceManagementOptionsConfiguration>();

// Trimming
services.AddScoped<IPermissionProvider, Permissions>();
services.AddScoped<IWorkflowTrimmingService, WorkflowTrimmingService>();
services.AddSingleton<IBackgroundTask, WorkflowTrimmingBackgroundTask>();
services.AddScoped<IDisplayDriver<ISite>, WorkflowTrimmingDisplayDriver>();
services.AddScoped<INavigationProvider, AdminMenu>();
services.Configure<WorkflowTrimmingOptions>(_shellConfiguration.GetSection("OrchardCore_Workflows").GetSection("Trimming"));
services.AddTrimmingServices(_shellConfiguration);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using OrchardCore.DisplayManagement.Entities;
using OrchardCore.DisplayManagement.Handlers;
using OrchardCore.DisplayManagement.Views;
using OrchardCore.Documents;
using OrchardCore.Settings;
using OrchardCore.Workflows.Trimming.Models;
using OrchardCore.Workflows.Trimming.ViewModels;
Expand All @@ -13,6 +14,7 @@ namespace OrchardCore.Workflows.Trimming.Drivers;

public sealed class WorkflowTrimmingDisplayDriver : SiteDisplayDriver<WorkflowTrimmingSettings>
{
private readonly IDocumentManager<WorkflowTrimmingState> _workflowTrimmingStateDocumentManager;
public const string GroupId = "WorkflowTrimmingSettings";

private readonly IHttpContextAccessor _httpContextAccessor;
Expand All @@ -21,24 +23,26 @@ public sealed class WorkflowTrimmingDisplayDriver : SiteDisplayDriver<WorkflowTr
public WorkflowTrimmingDisplayDriver(
IAuthorizationService authorizationService,
IHttpContextAccessor httpContextAccessor
)
,
IDocumentManager<WorkflowTrimmingState> workflowTrimmingStateDocumentManager)
{
_authorizationService = authorizationService;
_httpContextAccessor = httpContextAccessor;
_workflowTrimmingStateDocumentManager = workflowTrimmingStateDocumentManager;
}

protected override string SettingsGroupId
=> GroupId;

public override IDisplayResult Edit(ISite site, WorkflowTrimmingSettings settings, BuildEditorContext context)
{
return Initialize<WorkflowTrimmingViewModel>("WorkflowTrimming_Fields_Edit", model =>
return Initialize<WorkflowTrimmingViewModel>("WorkflowTrimming_Fields_Edit", async model =>
{
model.RetentionDays = settings.RetentionDays;
model.LastRunUtc = settings.LastRunUtc;
model.LastRunUtc = (await _workflowTrimmingStateDocumentManager.GetOrCreateImmutableAsync()).LastRunUtc;
model.Disabled = settings.Disabled;

foreach (var status in (settings.Statuses ?? []))
foreach (var status in settings.Statuses ?? [])
{
model.Statuses.Single(statusItem => statusItem.Status == status).IsSelected = true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using OrchardCore.BackgroundTasks;
using OrchardCore.DisplayManagement.Handlers;
using OrchardCore.Environment.Shell.Configuration;
using OrchardCore.Navigation;
using OrchardCore.Settings;
using OrchardCore.Workflows.Trimming;
using OrchardCore.Workflows.Trimming.Drivers;
using OrchardCore.Workflows.Trimming.Services;

namespace Microsoft.Extensions.DependencyInjection;

internal static class ServiceCollectionExtensions
{
public static IServiceCollection AddTrimmingServices(this IServiceCollection services, IShellConfiguration shellConfiguration)
{
services.AddScoped<IWorkflowTrimmingService, WorkflowTrimmingService>();
services.AddSingleton<IBackgroundTask, WorkflowTrimmingBackgroundTask>();
services.AddScoped<IDisplayDriver<ISite>, WorkflowTrimmingDisplayDriver>();
services.AddScoped<INavigationProvider, AdminMenu>();
services.Configure<WorkflowTrimmingOptions>(shellConfiguration.GetSection("OrchardCore_Workflows:Trimming"));

return services;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using OrchardCore.Entities;
using OrchardCore.Workflows.Models;

Expand All @@ -8,8 +7,6 @@ public class WorkflowTrimmingSettings : Entity
{
public int RetentionDays { get; set; } = 90;

public DateTime? LastRunUtc { get; set; }

public bool Disabled { get; set; }

public WorkflowStatus[] Statuses { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;
using OrchardCore.Data.Documents;

namespace OrchardCore.Workflows.Trimming.Models;

public class WorkflowTrimmingState : Document
{
public DateTime? LastRunUtc { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OrchardCore.BackgroundTasks;
using OrchardCore.Entities;
using OrchardCore.Documents;
using OrchardCore.Modules;
using OrchardCore.Settings;
using OrchardCore.Workflows.Trimming.Models;
Expand Down Expand Up @@ -40,19 +40,18 @@ public async Task DoWorkAsync(IServiceProvider serviceProvider, CancellationToke
var batchSize = serviceProvider.GetRequiredService<IOptions<WorkflowTrimmingOptions>>().Value.BatchSize;

logger.LogDebug("Starting trimming Workflow instances.");

var trimmedCount = await workflowTrimmingManager.TrimWorkflowInstancesAsync(
TimeSpan.FromDays(workflowTrimmingSettings.RetentionDays),
batchSize
);
logger.LogDebug("Trimmed {TrimmedCount} workflow instances.", trimmedCount);

var siteSettings = await siteService.LoadSiteSettingsAsync();
siteSettings.Alter<WorkflowTrimmingSettings>(settings =>
{
settings.LastRunUtc = clock.UtcNow;
});
logger.LogDebug("Trimmed {TrimmedCount} workflow instances.", trimmedCount);

await siteService.UpdateSiteSettingsAsync(siteSettings);
var workflowTrimmingSateDocumentManager = serviceProvider.GetRequiredService<IDocumentManager<WorkflowTrimmingState>>();
var workflowTrimmingState = await workflowTrimmingSateDocumentManager.GetOrCreateMutableAsync();
workflowTrimmingState.LastRunUtc = clock.UtcNow;
await workflowTrimmingSateDocumentManager.UpdateAsync(workflowTrimmingState);
}
catch (Exception ex) when (!ex.IsFatal())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ public class WorkflowTrimmingService : IWorkflowTrimmingService
private readonly ISession _session;
private readonly IClock _clock;

public WorkflowTrimmingService(ISiteService siteService, ISession session, IClock clock)
public WorkflowTrimmingService(
ISiteService siteService,
ISession session,
IClock clock)
{
_siteService = siteService;
_session = session;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using OrchardCore.Workflows.Models;

namespace OrchardCore.Workflows.Trimming.ViewModels;

public class WorkflowStatusItem
{
public WorkflowStatus Status { get; set; }

public bool IsSelected { get; set; }
}

Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,3 @@ public WorkflowTrimmingViewModel()
.ToArray();
}
}

public class WorkflowStatusItem
{
public WorkflowStatus Status { get; set; }

public bool IsSelected { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
@using OrchardCore.Workflows.Trimming.ViewModels
@model WorkflowTrimmingViewModel

<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="Disabled" checked="@Model.Disabled" />
<label class="form-check-label" asp-for="Disabled">@T["Disable"]</label>
<span class="hint dashed">@T["Whether the task is disabled."]</span>
<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="Disabled" checked="@Model.Disabled" />
<label class="form-check-label" asp-for="Disabled">@T["Disable"]</label>
<span class="hint dashed">@T["Whether the task is disabled."]</span>
</div>
</div>

<div class="mb-3" asp-validation-class-for="RetentionDays">
Expand All @@ -26,8 +28,8 @@
</div>

@* We use a hard-coded list of statuses here instead of iterating over the enum so the explicit T-strings make
localization easier (and so the default English displayed string can be different than the enum value's name). *@
<div class="row">
localization easier (and so the default English displayed string can be different than the enum value's name). *@
<div class="mb-3 row">
<div class="col-xs-12">
<div class="form-check">
<input type="hidden" asp-for="@Model.Statuses[0].Status" />
Expand Down Expand Up @@ -107,5 +109,4 @@
</label>
</div>
</div>

</div>
10 changes: 5 additions & 5 deletions src/docs/reference/modules/Workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,11 +443,11 @@ Old workflow instances can be automatically deleted with the Trimming feature. T
By default, the trimming background task runs once a day and removes at most 5000 workflow instances. You can change the frequency of the background task via [the `OrchardCore.BackgroundTasks` configuration](../BackgroundTasks/README.md), and the batch size via the `OrchardCore_Workflows` configuration from e.g. an `appsettings` file:

```json
"OrchardCore_Workflows": {
"Trimming": {
"BatchSize": 1000
}
}
"OrchardCore_Workflows": {
"Trimming": {
"BatchSize": 1000
}
}
```

See [Configuration](../../core/Configuration/README.md) for more information on such configuration.
Expand Down
2 changes: 1 addition & 1 deletion src/docs/releases/2.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -738,4 +738,4 @@ Many type commonly used by modules can be `sealed`, which improves runtime perfo

### Workflow Trimming

The Workflows module now has a Trimming feature to automatically clean up old workflow instances. See [the corresponding documentation](../reference/modules/Workflows/README.md#trimming) for details.
The Workflows module now has a `Trimming` feature to automatically clean up old workflow instances. See [the corresponding documentation](../reference/modules/Workflows/README.md#trimming) for details.