Skip to content

Commit 0f66a17

Browse files
authored
Merge pull request #146 from Geta/feature/suggestions-cleanup-job
Add suggestions cleanup job
2 parents 2860027 + 9eb600a commit 0f66a17

File tree

15 files changed

+264
-9
lines changed

15 files changed

+264
-9
lines changed

README.md

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ If you want to specify this yourself, add `IgnoredResourceExtensions` to the con
161161

162162
## Restricting access to the Admin UI
163163

164-
By default, only users of `Administrators` role can access Admin UI. But you can configure you authorization policy when registrating the NotFound handler.
164+
By default, only users of `Administrators` role can access Admin UI. But you can configure your authorization policy when registering the NotFound handler.
165165

166166
```
167167
services.AddNotFoundHandler(o => { },
@@ -171,15 +171,15 @@ By default, only users of `Administrators` role can access Admin UI. But you can
171171
});
172172
```
173173

174-
You can setup any policy rules you want.
174+
You can set up any policy rules you want.
175175

176176
## Import
177177

178178
For details see [Import redirects for 404 handler](https://getadigital.com/blog/import-redirects-for-404-handler/) article.
179179

180180
# Custom 404 Page
181181

182-
To setup 404 page, you can use any method ASP.NET Core provides.
182+
To set up 404 page, you can use any method ASP.NET Core provides.
183183

184184
One of the simplest solutions is adding a controller and a view for it that would display an error page:
185185

@@ -274,9 +274,37 @@ It will monitor primary, secondary and SEO URLs:
274274

275275
Optimizely Content Cloud supports only primary URLs and Optimizely Commerce supports all three types of URLs.
276276

277-
There are two scheduled jobs:
278-
- *[Geta NotFoundHandler] Index content URLs* - as mentioned before, this job indexes URLs of content. Usually, it is required to run this job only once. All new content is automatically indexed. But if for some reasons content publish events are not firing when creating new content (for example, during the import), then you should set this job to run frequently.
279-
- *[Geta NotFoundHandler] Register content move redirects* - this job creates redirects based on registered moved content. Normally, this job is not required at all, but there might be situations when content move is registered but redirect creation is not completed. This could happen during deployments. In this case, you can manually run this job or schedule it to run time to time to fix such issues.
277+
# Scheduled jobs
278+
279+
Scheduled job - process that runs in background
280+
- Suggestions cleanup job - shipped with the package, contains process that cleans up suggestions table.
281+
This job is configured by default to remove records older than 14 days. You can adjust the retention period or timeout as needed.
282+
```
283+
services.AddNotFoundHandler(o =>
284+
{
285+
o.SuggestionsCleanupOptions.DaysToKeep = 30;
286+
o.SuggestionsCleanupOptions.Timeout = 30 * 60;
287+
});
288+
```
289+
290+
Scheduler - mechanism that triggers scheduled jobs in a recurrent manner
291+
- InternalScheduler - default scheduler, included in the core package, a scheduler that uses [Coravel](https://docs.coravel.net/).
292+
To enable the scheduler, you need to enable UseInternalScheduler flag. Additionally, you can adjust the scheduler run interval:
293+
```
294+
services.AddNotFoundHandler(o =>
295+
{
296+
...
297+
o.UseInternalScheduler = true;
298+
o.InternalSchedulerCronInterval = "0 0 * * *" // by default it's configured to run daily at midnight
299+
});
300+
```
301+
- OptimizelyScheduler - uses Optimizely to schedule job runs.
302+
An Optimizely scheduled job was added - <code>[Geta NotFoundHandler] Suggestions cleanup job</code>.
303+
304+
Additionally, there are two optimizely scheduled jobs responsible for:
305+
- *[Geta NotFoundHandler] Index content URLs* - as mentioned before, this job indexes URLs of content. Usually, it is required to run this job only once. All new content is automatically indexed. But if for some reason content publish events are not firing when creating new content (for example, during the import), then you should set this job to run frequently.
306+
- *[Geta NotFoundHandler] Register content move redirects* - this job creates redirects based on registered moved content. Normally, this job is not required at all, but there might be situations when content move is registered but redirect creation is not completed. This could happen during deployments. In this case, you can manually run this job or schedule it to run time to time to fix such issues.
307+
280308

281309
# Troubleshooting
282310

@@ -293,7 +321,7 @@ For example, if we have a redirect: `/a` to `/b`, then:
293321
- without wildcard setting it will redirect `/a/1` to `/b/1`
294322

295323
# Sandbox App
296-
Sandbox application is testing poligon for pacakge new features and bug fixes.
324+
Sandbox application is testing polygon for package new features and bug fixes.
297325

298326
CMS username: admin@example.com
299327

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright (c) Geta Digital. All rights reserved.
2+
// Licensed under Apache-2.0. See the LICENSE file in the project root for more information
3+
4+
using EPiServer.PlugIn;
5+
using EPiServer.Scheduler;
6+
using Geta.NotFoundHandler.Core.Suggestions;
7+
8+
namespace Geta.NotFoundHandler.Optimizely.Core.Suggestions.Jobs;
9+
10+
[ScheduledPlugIn(DisplayName = "[Geta NotFoundHandler] Suggestions cleanup job",
11+
Description = "As suggestions table grow fast we should add a possibility to clean up old suggestions",
12+
GUID = "6AE19CEC-1052-4482-97DF-981076DDD6F2",
13+
SortIndex = 5555)]
14+
public class SuggestionsCleanupJob : ScheduledJobBase
15+
{
16+
private readonly ISuggestionsCleanupService _suggestionsCleanupService;
17+
18+
public SuggestionsCleanupJob(ISuggestionsCleanupService suggestionsCleanupService)
19+
{
20+
IsStoppable = true;
21+
_suggestionsCleanupService = suggestionsCleanupService;
22+
}
23+
24+
public override string Execute()
25+
{
26+
_suggestionsCleanupService.Cleanup();
27+
28+
return string.Empty;
29+
}
30+
}

src/Geta.NotFoundHandler.Optimizely/Infrastructure/Configuration/OptimizelyNotFoundHandlerOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace Geta.NotFoundHandler.Optimizely.Infrastructure.Configuration
1010
{
1111
public class OptimizelyNotFoundHandlerOptions
1212
{
13+
public const string Section = "Geta:NotFoundHandler:Optimizely";
1314
public const int CurrentDbVersion = 3;
1415

1516
public bool AutomaticRedirectsEnabled { get; set; }

src/Geta.NotFoundHandler.Optimizely/Infrastructure/Configuration/ServiceCollectionExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public static IServiceCollection AddOptimizelyNotFoundHandler(
7474
services.AddOptions<OptimizelyNotFoundHandlerOptions>().Configure<IConfiguration>((options, configuration) =>
7575
{
7676
setupAction(options);
77-
configuration.GetSection("Geta:NotFoundHandler:Optimizely").Bind(options);
77+
configuration.GetSection(OptimizelyNotFoundHandlerOptions.Section).Bind(options);
7878
});
7979

8080
return services;

src/Geta.NotFoundHandler.Optimizely/Infrastructure/Initialization/ApplicationBuilderExtensions.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// Copyright (c) Geta Digital. All rights reserved.
22
// Licensed under Apache-2.0. See the LICENSE file in the project root for more information
33

4+
using Coravel.Scheduling.Schedule;
5+
using Coravel.Scheduling.Schedule.Interfaces;
6+
using Geta.NotFoundHandler.Core.ScheduledJobs.Suggestions;
47
using Geta.NotFoundHandler.Optimizely.Core.AutomaticRedirects;
58
using Geta.NotFoundHandler.Optimizely.Core.Events;
69
using Microsoft.AspNetCore.Builder;
@@ -23,6 +26,10 @@ public static IApplicationBuilder UseOptimizelyNotFoundHandler(this IApplication
2326
var historyEvents = services.GetRequiredService<ContentUrlHistoryEvents>();
2427
historyEvents.Initialize();
2528

29+
// For optimizely we will use built-in scheduler for this job
30+
var scheduler = services.GetService<IScheduler>();
31+
(scheduler as Scheduler)?.TryUnschedule(nameof(SuggestionsCleanupJob));
32+
2633
return app;
2734
}
2835
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright (c) Geta Digital. All rights reserved.
2+
// Licensed under Apache-2.0. See the LICENSE file in the project root for more information
3+
4+
using Coravel;
5+
using Geta.NotFoundHandler.Core.ScheduledJobs.Suggestions;
6+
using Geta.NotFoundHandler.Infrastructure.Configuration;
7+
using Microsoft.AspNetCore.Builder;
8+
using Microsoft.Extensions.DependencyInjection;
9+
using Microsoft.Extensions.Logging;
10+
using Microsoft.Extensions.Options;
11+
12+
namespace Geta.NotFoundHandler.Core.ScheduledJobs;
13+
14+
public static class ApplicationBuilderExtensions
15+
{
16+
public static IApplicationBuilder UseInternalScheduler(this IApplicationBuilder app)
17+
{
18+
var services = app.ApplicationServices;
19+
20+
var options = services.GetRequiredService<IOptions<NotFoundHandlerOptions>>().Value;
21+
var logger = services.GetRequiredService<ILogger>();
22+
23+
services.UseScheduler(scheduler =>
24+
{
25+
scheduler
26+
.Schedule<SuggestionsCleanupJob>()
27+
.Cron(options.InternalSchedulerCronInterval)
28+
.PreventOverlapping(nameof(SuggestionsCleanupJob));
29+
})
30+
.OnError(x =>
31+
{
32+
logger.LogError(x, "Something went wrong, scheduled job failed with exception");
33+
});
34+
35+
return app;
36+
}
37+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) Geta Digital. All rights reserved.
2+
// Licensed under Apache-2.0. See the LICENSE file in the project root for more information
3+
4+
using Coravel;
5+
using Geta.NotFoundHandler.Core.ScheduledJobs.Suggestions;
6+
using Geta.NotFoundHandler.Infrastructure.Configuration;
7+
using Microsoft.Extensions.DependencyInjection;
8+
using Microsoft.Extensions.Options;
9+
10+
namespace Geta.NotFoundHandler.Core.ScheduledJobs;
11+
12+
public static class ServiceCollectionExtensions
13+
{
14+
public static IServiceCollection EnableScheduler(this IServiceCollection services)
15+
{
16+
using var serviceProvider = services.BuildServiceProvider();
17+
var options = serviceProvider.GetRequiredService<IOptions<NotFoundHandlerOptions>>().Value;
18+
19+
if (options.UseInternalScheduler)
20+
{
21+
services.AddScheduler();
22+
23+
services.AddTransient<SuggestionsCleanupJob>();
24+
}
25+
26+
return services;
27+
}
28+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) Geta Digital. All rights reserved.
2+
// Licensed under Apache-2.0. See the LICENSE file in the project root for more information
3+
4+
using System.Threading.Tasks;
5+
using Coravel.Invocable;
6+
using Geta.NotFoundHandler.Core.Suggestions;
7+
8+
namespace Geta.NotFoundHandler.Core.ScheduledJobs.Suggestions;
9+
10+
public class SuggestionsCleanupJob : IInvocable
11+
{
12+
private readonly ISuggestionsCleanupService _suggestionsCleanupService;
13+
14+
public SuggestionsCleanupJob(ISuggestionsCleanupService suggestionsCleanupService)
15+
{
16+
_suggestionsCleanupService = suggestionsCleanupService;
17+
}
18+
19+
public async Task Invoke()
20+
{
21+
_suggestionsCleanupService.Cleanup();
22+
}
23+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright (c) Geta Digital. All rights reserved.
2+
// Licensed under Apache-2.0. See the LICENSE file in the project root for more information
3+
4+
namespace Geta.NotFoundHandler.Core.Suggestions;
5+
6+
public interface ISuggestionsCleanupService
7+
{
8+
void Cleanup();
9+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright (c) Geta Digital. All rights reserved.
2+
// Licensed under Apache-2.0. See the LICENSE file in the project root for more information
3+
4+
namespace Geta.NotFoundHandler.Core.Suggestions;
5+
6+
public class SuggestionsCleanupOptions
7+
{
8+
public int DaysToKeep { get; set; } = 14;
9+
public int Timeout { get; set; } = 30 * 60;
10+
}

0 commit comments

Comments
 (0)