-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
285 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 0 additions & 7 deletions
7
...ce/Maintenance/DeleteElasticsearchIndices/DeleteElasticsearchIndicesMaintenanceOptions.cs
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
...ntenance/Maintenance/DeleteElasticsearchIndices/ElasticsearchIndicesMaintenanceOptions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Lombiq.Hosting.Tenants.Maintenance.Maintenance.DeleteElasticsearchIndices; | ||
|
||
public class ElasticsearchIndicesMaintenanceOptions | ||
{ | ||
public bool DeleteMaintenanceIsEnabled { get; set; } | ||
public bool RebuildMaintenanceIsEnabled { get; set; } | ||
public bool BeforeSetupMiddlewareIsEnabled { get; set; } | ||
} |
50 changes: 50 additions & 0 deletions
50
.../Maintenance/DeleteElasticsearchIndices/RebuildElasticsearchIndicesMaintenanceProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using Lombiq.Hosting.Tenants.Maintenance.Extensions; | ||
using Lombiq.Hosting.Tenants.Maintenance.Models; | ||
using Lombiq.Hosting.Tenants.Maintenance.Services; | ||
using Microsoft.Extensions.Options; | ||
using OrchardCore.Search.Elasticsearch.Core.Services; | ||
using System.Threading.Tasks; | ||
|
||
namespace Lombiq.Hosting.Tenants.Maintenance.Maintenance.DeleteElasticsearchIndices; | ||
|
||
public class RebuildElasticsearchIndicesMaintenanceProvider : MaintenanceProviderBase | ||
{ | ||
private readonly IOptions<ElasticsearchIndicesMaintenanceOptions> _options; | ||
private readonly ElasticIndexingService _elasticIndexingService; | ||
private readonly ElasticIndexSettingsService _elasticIndexSettingsService; | ||
|
||
public RebuildElasticsearchIndicesMaintenanceProvider( | ||
IOptions<ElasticsearchIndicesMaintenanceOptions> options, | ||
ElasticIndexingService elasticIndexingService, | ||
ElasticIndexSettingsService elasticIndexSettingsService) | ||
{ | ||
_options = options; | ||
_elasticIndexingService = elasticIndexingService; | ||
_elasticIndexSettingsService = elasticIndexSettingsService; | ||
} | ||
|
||
public override Task<bool> ShouldExecuteAsync(MaintenanceTaskExecutionContext context) => | ||
Task.FromResult( | ||
_options.Value.RebuildMaintenanceIsEnabled && | ||
!context.WasLatestExecutionSuccessful()); | ||
|
||
public override async Task ExecuteAsync(MaintenanceTaskExecutionContext context) | ||
{ | ||
var settings = await _elasticIndexSettingsService.GetSettingsAsync(); | ||
foreach (var setting in settings) | ||
{ | ||
await _elasticIndexingService.RebuildIndexAsync(setting); | ||
|
||
if (setting.QueryAnalyzerName != setting.AnalyzerName) | ||
{ | ||
// Query Analyzer may be different until the index in rebuilt. | ||
// Since the index is rebuilt, lets make sure we query using the same analyzer. | ||
setting.QueryAnalyzerName = setting.AnalyzerName; | ||
|
||
await _elasticIndexSettingsService.UpdateIndexAsync(setting); | ||
} | ||
|
||
await _elasticIndexingService.ProcessContentItemsAsync(setting.IndexName); | ||
} | ||
} | ||
} |
132 changes: 124 additions & 8 deletions
132
Lombiq.Hosting.Tenants.Maintenance/Maintenance/DeleteElasticsearchIndices/Startup.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,162 @@ | ||
using Elasticsearch.Net; | ||
using Lombiq.HelpfulLibraries.OrchardCore.Mvc; | ||
using Lombiq.Hosting.Tenants.Maintenance.Constants; | ||
using Lombiq.Hosting.Tenants.Maintenance.Services; | ||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.AspNetCore.Routing; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Options; | ||
using Nest; | ||
using OrchardCore.Environment.Shell; | ||
using OrchardCore.Environment.Shell.Configuration; | ||
using OrchardCore.Modules; | ||
using OrchardCore.Search.Elasticsearch.Core.Models; | ||
using OrchardCore.Search.Elasticsearch.Core.Services; | ||
using System; | ||
using System.Linq; | ||
|
||
namespace Lombiq.Hosting.Tenants.Maintenance.Maintenance.DeleteElasticsearchIndices; | ||
|
||
[Feature(FeatureNames.DeleteElasticsearchIndices)] | ||
public class Startup : StartupBase | ||
[Feature(FeatureNames.DeleteOrRebuildElasticsearchIndices)] | ||
public class DeleteElasticsearchIndicesStartup : StartupBase | ||
{ | ||
private readonly IShellConfiguration _shellConfiguration; | ||
|
||
public override int Order => int.MaxValue; | ||
|
||
public DeleteElasticsearchIndicesStartup(IShellConfiguration shellConfiguration) => _shellConfiguration = shellConfiguration; | ||
|
||
public override void ConfigureServices(IServiceCollection services) | ||
{ | ||
services.BindAndConfigureSection<ElasticsearchIndicesMaintenanceOptions>( | ||
_shellConfiguration, | ||
"Lombiq_Hosting_Tenants_Maintenance:ElasticsearchIndicesOptions"); | ||
|
||
services.AddScoped<IMaintenanceProvider, DeleteElasticsearchIndicesMaintenanceProvider>(); | ||
services.AddScoped<IMaintenanceProvider, RebuildElasticsearchIndicesMaintenanceProvider>(); | ||
} | ||
} | ||
|
||
[Feature(FeatureNames.DeleteElasticsearchIndicesBeforeSetup)] | ||
public class DeleteElasticsearchIndicesBeforeSetupStartup : StartupBase | ||
{ | ||
private readonly IShellConfiguration _shellConfiguration; | ||
private readonly ShellSettings _shellSettings; | ||
|
||
public Startup(IShellConfiguration shellConfiguration, ShellSettings shellSettings) | ||
public override int Order => int.MaxValue; | ||
|
||
public DeleteElasticsearchIndicesBeforeSetupStartup(IShellConfiguration shellConfiguration, ShellSettings shellSettings) | ||
{ | ||
_shellConfiguration = shellConfiguration; | ||
_shellSettings = shellSettings; | ||
} | ||
|
||
public override void ConfigureServices(IServiceCollection services) | ||
{ | ||
services.BindAndConfigureSection<DeleteElasticsearchIndicesMaintenanceOptions>( | ||
services.BindAndConfigureSection<ElasticsearchIndicesMaintenanceOptions>( | ||
_shellConfiguration, | ||
"Lombiq_Hosting_Tenants_Maintenance:DeleteElasticsearchIndices"); | ||
"Lombiq_Hosting_Tenants_Maintenance:ElasticsearchIndicesOptions"); | ||
|
||
services.AddScoped<IMaintenanceProvider, DeleteElasticsearchIndicesMaintenanceProvider>(); | ||
// After the setup, the Elasticsearch module can be loaded the regular way. | ||
if (!_shellSettings.IsUninitialized()) return; | ||
|
||
// This is necessary because the Elasticsearch module can't be enabled the regular way if this module is added | ||
// as a setup feature, otherwise you get a ContentsAdminList shape missing exception on the admin dashboard. For | ||
// more info see: | ||
var configuration = _shellConfiguration.GetSection("OrchardCore_Elasticsearch"); | ||
var elasticConfiguration = configuration.Get<ElasticConnectionOptions>(); | ||
services.Configure<ElasticConnectionOptions>(o => o.ConfigurationExists = true); | ||
// Otherwise the ElasticClient won't work. Copied all this from the OC Elasticsearch module. | ||
#pragma warning disable CA2000 // Call System. IDisposable. Dispose on object created by | ||
// 'GetConnectionSettings(elasticConfiguration)' before all references to it are out of scope | ||
var settings = GetConnectionSettings(elasticConfiguration); | ||
#pragma warning restore CA2000 | ||
services.AddSingleton<IElasticClient>(new ElasticClient(settings)); | ||
services.AddSingleton<ElasticIndexManager>(); | ||
} | ||
|
||
public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) | ||
{ | ||
if (!_shellSettings.IsUninitialized()) return; | ||
|
||
var options = serviceProvider.GetRequiredService<IOptions<DeleteElasticsearchIndicesMaintenanceOptions>>().Value; | ||
if (options.MiddlewareIsEnabled) | ||
var options = serviceProvider.GetRequiredService<IOptions<ElasticsearchIndicesMaintenanceOptions>>().Value; | ||
if (options.BeforeSetupMiddlewareIsEnabled) | ||
{ | ||
app.UseMiddleware<DeleteElasticsearchIndicesMiddleware>(); | ||
} | ||
} | ||
|
||
private static ConnectionSettings GetConnectionSettings(ElasticConnectionOptions elasticConfiguration) | ||
{ | ||
// This is a copy of the OC Elasticsearch module's OrchardCore.Search.Elasticsearch.Startup.GetConnectionSettings method. | ||
#pragma warning disable CA2000 // Call System. IDisposable. Dispose on object created by | ||
// 'GetConnectionPool(elasticConfiguration)' before all references to it are out of scope | ||
var pool = GetConnectionPool(elasticConfiguration); | ||
#pragma warning restore CA2000 | ||
|
||
var settings = new ConnectionSettings(pool); | ||
|
||
if (elasticConfiguration.ConnectionType != "CloudConnectionPool" && | ||
!string.IsNullOrWhiteSpace(elasticConfiguration.Username) && | ||
!string.IsNullOrWhiteSpace(elasticConfiguration.Password)) | ||
{ | ||
settings.BasicAuthentication(elasticConfiguration.Username, elasticConfiguration.Password); | ||
} | ||
|
||
if (!string.IsNullOrWhiteSpace(elasticConfiguration.CertificateFingerprint)) | ||
{ | ||
settings.CertificateFingerprint(elasticConfiguration.CertificateFingerprint); | ||
} | ||
|
||
if (elasticConfiguration.EnableApiVersioningHeader) | ||
{ | ||
settings.EnableApiVersioningHeader(); | ||
} | ||
|
||
return settings; | ||
} | ||
|
||
private static IConnectionPool GetConnectionPool(ElasticConnectionOptions elasticConfiguration) | ||
{ | ||
var uris = elasticConfiguration.Ports.Select(port => new Uri($"{elasticConfiguration.Url}:{port.ToTechnicalString()}")).Distinct(); | ||
IConnectionPool pool = null; | ||
switch (elasticConfiguration.ConnectionType) | ||
{ | ||
case "SingleNodeConnectionPool": | ||
pool = new SingleNodeConnectionPool(uris.First()); | ||
break; | ||
|
||
case "CloudConnectionPool": | ||
if (!string.IsNullOrWhiteSpace(elasticConfiguration.Username) && | ||
!string.IsNullOrWhiteSpace(elasticConfiguration.Password) && | ||
!string.IsNullOrWhiteSpace(elasticConfiguration.CloudId)) | ||
{ | ||
using var credentials = new BasicAuthenticationCredentials( | ||
elasticConfiguration.Username, | ||
elasticConfiguration.Password); | ||
pool = new CloudConnectionPool(elasticConfiguration.CloudId, credentials); | ||
} | ||
|
||
break; | ||
|
||
case "StaticConnectionPool": | ||
pool = new StaticConnectionPool(uris); | ||
break; | ||
|
||
case "SniffingConnectionPool": | ||
pool = new SniffingConnectionPool(uris); | ||
break; | ||
|
||
case "StickyConnectionPool": | ||
pool = new StickyConnectionPool(uris); | ||
break; | ||
|
||
default: | ||
pool = new SingleNodeConnectionPool(uris.First()); | ||
break; | ||
} | ||
|
||
return pool; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.