diff --git a/src/Contrib/SearchEngine/AutoComplete/Masa.Contrib.SearchEngine.AutoComplete.ElasticSearch/ServiceCollectionExtensions.cs b/src/Contrib/SearchEngine/AutoComplete/Masa.Contrib.SearchEngine.AutoComplete.ElasticSearch/ServiceCollectionExtensions.cs index 00050f86d..3bad660e6 100644 --- a/src/Contrib/SearchEngine/AutoComplete/Masa.Contrib.SearchEngine.AutoComplete.ElasticSearch/ServiceCollectionExtensions.cs +++ b/src/Contrib/SearchEngine/AutoComplete/Masa.Contrib.SearchEngine.AutoComplete.ElasticSearch/ServiceCollectionExtensions.cs @@ -117,7 +117,7 @@ private static void TryAddAutoCompleteRelation(this IServiceCollection services, throw new ArgumentException($"indexName or alias exists"); if (relation.IsDefault && relationsOptions.Relations.Any(r => r.IsDefault)) - throw new ArgumentException("ElasticClient can only have one default", nameof(ElasticsearchRelations.IsDefault)); + throw new ArgumentException("ElasticClient can only have one default", nameof(ElasticsearchOptions.IsDefault)); relationsOptions.AddRelation(relation); } diff --git a/src/Contrib/StackSdks/Masa.Contrib.StackSdks.Tsc.Elasticsearch/Extenistions/ServiceExtenistion.cs b/src/Contrib/StackSdks/Masa.Contrib.StackSdks.Tsc.Elasticsearch/Extenistions/ServiceExtenistion.cs index 668cce268..1a20d3d9a 100644 --- a/src/Contrib/StackSdks/Masa.Contrib.StackSdks.Tsc.Elasticsearch/Extenistions/ServiceExtenistion.cs +++ b/src/Contrib/StackSdks/Masa.Contrib.StackSdks.Tsc.Elasticsearch/Extenistions/ServiceExtenistion.cs @@ -90,12 +90,12 @@ private static IServiceCollection AddElasticsearch(IServiceCollection services, }); } - internal static IElasticClient CreateElasticClient(this IElasticsearchFactory elasticsearchFactory, bool isLog) + internal static IElasticClient CreateElasticClient(this IElasticClientFactory elasticsearchFactory, bool isLog) { if (isLog) - return elasticsearchFactory.CreateElasticClient(ElasticConstant.Log.IsIndependent ? ElasticConstant.LOG_CALLER_CLIENT_NAME : ElasticConstant.DEFAULT_CALLER_CLIENT_NAME); + return elasticsearchFactory.Create(ElasticConstant.Log.IsIndependent ? ElasticConstant.LOG_CALLER_CLIENT_NAME : ElasticConstant.DEFAULT_CALLER_CLIENT_NAME); else - return elasticsearchFactory.CreateElasticClient(ElasticConstant.Trace.IsIndependent ? ElasticConstant.TRACE_CALLER_CLIENT_NAME : ElasticConstant.DEFAULT_CALLER_CLIENT_NAME); + return elasticsearchFactory.Create(ElasticConstant.Trace.IsIndependent ? ElasticConstant.TRACE_CALLER_CLIENT_NAME : ElasticConstant.DEFAULT_CALLER_CLIENT_NAME); } internal static ICaller Create(this ICallerFactory callerFactory, bool isLog) diff --git a/src/Contrib/StackSdks/Masa.Contrib.StackSdks.Tsc.Elasticsearch/LogService.cs b/src/Contrib/StackSdks/Masa.Contrib.StackSdks.Tsc.Elasticsearch/LogService.cs index ea9e1ff2d..5aa921376 100644 --- a/src/Contrib/StackSdks/Masa.Contrib.StackSdks.Tsc.Elasticsearch/LogService.cs +++ b/src/Contrib/StackSdks/Masa.Contrib.StackSdks.Tsc.Elasticsearch/LogService.cs @@ -8,9 +8,9 @@ internal class LogService : ILogService private readonly IElasticClient _client; private readonly ICallerFactory _callerFactory; - public LogService(IElasticsearchFactory elasticsearchFactory, ICallerFactory callerFactory) + public LogService(IElasticClientFactory elasticClientFactory, ICallerFactory callerFactory) { - _client = elasticsearchFactory.CreateElasticClient(true); + _client = elasticClientFactory.CreateElasticClient(true); _callerFactory = callerFactory; } diff --git a/src/Contrib/StackSdks/Masa.Contrib.StackSdks.Tsc.Elasticsearch/TraceService.cs b/src/Contrib/StackSdks/Masa.Contrib.StackSdks.Tsc.Elasticsearch/TraceService.cs index 4149fbbb7..fc8ec63fe 100644 --- a/src/Contrib/StackSdks/Masa.Contrib.StackSdks.Tsc.Elasticsearch/TraceService.cs +++ b/src/Contrib/StackSdks/Masa.Contrib.StackSdks.Tsc.Elasticsearch/TraceService.cs @@ -7,9 +7,9 @@ internal class TraceService : ITraceService { private readonly IElasticClient _client; - public TraceService(IElasticsearchFactory elasticsearchFactory) + public TraceService(IElasticClientFactory elasticClientFactory) { - _client = elasticsearchFactory.CreateElasticClient(false); + _client = elasticClientFactory.CreateElasticClient(false); } public async Task AggregateAsync(SimpleAggregateRequestDto query) diff --git a/src/Contrib/StackSdks/Tests/Masa.Contrib.StackSdks.Tsc.Elasticsearch.Tests/Extensions/ServiceExtenistionTests.cs b/src/Contrib/StackSdks/Tests/Masa.Contrib.StackSdks.Tsc.Elasticsearch.Tests/Extensions/ServiceExtenistionTests.cs index 2da7b4ee6..6edfe78f8 100644 --- a/src/Contrib/StackSdks/Tests/Masa.Contrib.StackSdks.Tsc.Elasticsearch.Tests/Extensions/ServiceExtenistionTests.cs +++ b/src/Contrib/StackSdks/Tests/Masa.Contrib.StackSdks.Tsc.Elasticsearch.Tests/Extensions/ServiceExtenistionTests.cs @@ -3,6 +3,7 @@ namespace Masa.Contrib.StackSdks.Tsc.Elasticsearch.Tests.Extensions; +#pragma warning disable CS0618 [TestClass] public class ServiceExtenistionTests { @@ -16,6 +17,7 @@ public void AddLogNodesTest() var factory = services.BuildServiceProvider().GetRequiredService(); Assert.IsNotNull(factory); + Assert.IsNotNull(factory.CreateElasticClient(ElasticConstant.LOG_CALLER_CLIENT_NAME)); Assert.ThrowsException(() => factory.CreateElasticClient(ElasticConstant.TRACE_CALLER_CLIENT_NAME)); Assert.ThrowsException(() => factory.CreateElasticClient(ElasticConstant.DEFAULT_CALLER_CLIENT_NAME)); @@ -132,3 +134,4 @@ public void AddLogTraceOptionsTest() services.Clear(); } } +#pragma warning restore CS0618 diff --git a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/DefaultElasticClientFactory.cs b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/DefaultElasticClientFactory.cs new file mode 100644 index 000000000..bb85617dc --- /dev/null +++ b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/DefaultElasticClientFactory.cs @@ -0,0 +1,71 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.Utils.Data.Elasticsearch; + +public class DefaultElasticClientFactory : IElasticClientFactory +{ + private readonly List _names; + private readonly IOptionsMonitor _elasticsearchOptions; + + public DefaultElasticClientFactory(IOptionsMonitor elasticsearchOptions, + IEnumerable> options) + { + _elasticsearchOptions = elasticsearchOptions; + _names = options.Select(opt => ((ConfigureNamedOptions)opt).Name).ToList(); + } + + public IElasticClient Create() + { + var elasticsearchOptions = _elasticsearchOptions.Get(Microsoft.Extensions.Options.Options.DefaultName); + + if (elasticsearchOptions.Nodes is null) elasticsearchOptions = _elasticsearchOptions.Get(_names.FirstOrDefault()); + + if (elasticsearchOptions.Nodes is null) throw new ArgumentException("The default ElasticClient is not found, please check if Elasticsearch is added"); + + return Create(elasticsearchOptions); + } + + public IElasticClient Create(string name) + { + var elasticsearchOptions = _elasticsearchOptions.Get(name); + if (elasticsearchOptions.Nodes is null) throw new NotSupportedException($"The ElasticClient whose name is {name} is not found"); + + return Create(elasticsearchOptions); + } + + private static IElasticClient Create(ElasticsearchOptions elasticsearchOptions) + { + var settings = elasticsearchOptions.UseConnectionPool + ? GetConnectionSettingsConnectionPool(elasticsearchOptions) + : GetConnectionSettingsBySingleNode(elasticsearchOptions); + + return new ElasticClient(settings); + } + + private static ConnectionSettings GetConnectionSettingsBySingleNode(ElasticsearchOptions relation) + { + var connectionSetting = new ConnectionSettings(new Uri(relation.Nodes[0])) + .EnableApiVersioningHeader(); + relation.Action?.Invoke(connectionSetting); + return connectionSetting; + } + + private static ConnectionSettings GetConnectionSettingsConnectionPool(ElasticsearchOptions relation) + { + var pool = new StaticConnectionPool( + relation.Nodes.Select(node => new Uri(node)), + relation.StaticConnectionPoolOptions?.Randomize ?? true, + relation.StaticConnectionPoolOptions?.DateTimeProvider); + + var settings = new ConnectionSettings( + pool, + relation.ConnectionSettingsOptions?.Connection, + relation.ConnectionSettingsOptions?.SourceSerializerFactory, + relation.ConnectionSettingsOptions?.PropertyMappingProvider) + .EnableApiVersioningHeader(); + + relation.Action?.Invoke(settings); + return settings; + } +} diff --git a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/DefaultElasticsearchFactory.cs b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/DefaultElasticsearchFactory.cs index 2423a175c..5c533ddbc 100644 --- a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/DefaultElasticsearchFactory.cs +++ b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/DefaultElasticsearchFactory.cs @@ -5,80 +5,16 @@ namespace Masa.Utils.Data.Elasticsearch; public class DefaultElasticsearchFactory : IElasticsearchFactory { - private readonly Dictionary _relations; - private readonly ConcurrentDictionary _elasticClients; + private readonly IElasticClientFactory _factory; - public DefaultElasticsearchFactory(ElasticsearchRelationsOptions options) - { - _relations = options.Relations; - _elasticClients = new(); - } + public DefaultElasticsearchFactory(IElasticClientFactory factory) + => _factory = factory; - public IMasaElasticClient CreateClient() - { - return new DefaultMasaElasticClient(CreateElasticClient()); - } + public IMasaElasticClient CreateClient() => new DefaultMasaElasticClient(CreateElasticClient()); - public IMasaElasticClient CreateClient(string name) - { - return new DefaultMasaElasticClient(CreateElasticClient(name)); - } + public IMasaElasticClient CreateClient(string name) => new DefaultMasaElasticClient(CreateElasticClient(name)); - public IElasticClient CreateElasticClient() - { - var elasticsearchRelation = _relations.Values.SingleOrDefault(r => r.IsDefault) ?? _relations.Values.FirstOrDefault(); + public IElasticClient CreateElasticClient() => _factory.Create(); - if (elasticsearchRelation == null) - throw new Exception("The default ElasticClient is not found, please check if Elasticsearch is added"); - - return GetOrAddElasticClient(elasticsearchRelation.Name); - } - - public IElasticClient CreateElasticClient(string name) - { - if (!_relations.ContainsKey(name)) - throw new NotSupportedException($"The ElasticClient whose name is {name} is not found"); - - return GetOrAddElasticClient(name); - } - - private IElasticClient GetOrAddElasticClient(string name) - => _elasticClients.GetOrAdd(name, name => Create(name)); - - private IElasticClient Create(string name) - { - var relation = _relations[name]; - - var settings = relation.UseConnectionPool - ? GetConnectionSettingsConnectionPool(relation) - : GetConnectionSettingsBySingleNode(relation); - - return new ElasticClient(settings); - } - - private ConnectionSettings GetConnectionSettingsBySingleNode(ElasticsearchRelations relation) - { - var connectionSetting = new ConnectionSettings(relation.Nodes[0]) - .EnableApiVersioningHeader(); - relation.Action?.Invoke(connectionSetting); - return connectionSetting; - } - - private ConnectionSettings GetConnectionSettingsConnectionPool(ElasticsearchRelations relation) - { - var pool = new StaticConnectionPool( - relation.Nodes, - relation.StaticConnectionPoolOptions?.Randomize ?? true, - relation.StaticConnectionPoolOptions?.DateTimeProvider); - - var settings = new ConnectionSettings( - pool, - relation.ConnectionSettingsOptions?.Connection, - relation.ConnectionSettingsOptions?.SourceSerializerFactory, - relation.ConnectionSettingsOptions?.PropertyMappingProvider) - .EnableApiVersioningHeader(); - - relation.Action?.Invoke(settings); - return settings; - } + public IElasticClient CreateElasticClient(string name) => _factory.Create(name); } diff --git a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/DefaultMasaElasticClientFactory.cs b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/DefaultMasaElasticClientFactory.cs new file mode 100644 index 000000000..00cd23efa --- /dev/null +++ b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/DefaultMasaElasticClientFactory.cs @@ -0,0 +1,26 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.Utils.Data.Elasticsearch; + +public class DefaultMasaElasticClientFactory : IMasaElasticClientFactory +{ + private readonly IElasticClientFactory _clientFactory; + + public DefaultMasaElasticClientFactory(IElasticClientFactory clientFactory) + { + _clientFactory = clientFactory; + } + + public IMasaElasticClient Create() + { + var elasticClient = _clientFactory.Create(); + return new DefaultMasaElasticClient(elasticClient); + } + + public IMasaElasticClient Create(string name) + { + var elasticClient = _clientFactory.Create(name); + return new DefaultMasaElasticClient(elasticClient); + } +} diff --git a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/ElasticsearchRelations.cs b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/ElasticsearchRelations.cs deleted file mode 100644 index 8927fa4a1..000000000 --- a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/ElasticsearchRelations.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) MASA Stack All rights reserved. -// Licensed under the MIT License. See LICENSE.txt in the project root for license information. - -namespace Masa.Utils.Data.Elasticsearch; - -public class ElasticsearchRelations -{ - public bool IsDefault { get; private set; } - - public string Name { get; } - - public Uri[] Nodes { get; } - - public bool UseConnectionPool { get; } - - internal StaticConnectionPoolOptions? StaticConnectionPoolOptions { get; private set; } - - internal ConnectionSettingsOptions? ConnectionSettingsOptions { get; private set; } - - internal Action? Action { get; private set; } - - public ElasticsearchRelations(string name, bool useConnectionPool, Uri[] nodes) - { - Name = name; - IsDefault = false; - UseConnectionPool = useConnectionPool; - Nodes = nodes; - Action = null; - StaticConnectionPoolOptions = null; - ConnectionSettingsOptions = null; - } - - public ElasticsearchRelations UseDefault() - { - IsDefault = true; - return this; - } - - public ElasticsearchRelations UseStaticConnectionPoolOptions(StaticConnectionPoolOptions staticConnectionPoolOptions) - { - StaticConnectionPoolOptions = staticConnectionPoolOptions; - return this; - } - - public ElasticsearchRelations UseConnectionSettingsOptions(ConnectionSettingsOptions connectionSettingsOptions) - { - ConnectionSettingsOptions = connectionSettingsOptions; - return this; - } - - public ElasticsearchRelations UseConnectionSettings(Action? action) - { - Action = action; - return this; - } -} diff --git a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/ServiceCollectionExtensions.Extensions.cs b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/Extensions/ServiceCollectionExtensions.Extensions.cs similarity index 80% rename from src/Utils/Data/Masa.Utils.Data.Elasticsearch/ServiceCollectionExtensions.Extensions.cs rename to src/Utils/Data/Masa.Utils.Data.Elasticsearch/Extensions/ServiceCollectionExtensions.Extensions.cs index 0a3912065..047e6fe5a 100644 --- a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/ServiceCollectionExtensions.Extensions.cs +++ b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/Extensions/ServiceCollectionExtensions.Extensions.cs @@ -1,13 +1,15 @@ // Copyright (c) MASA Stack All rights reserved. // Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ReSharper disable once CheckNamespace + namespace Microsoft.Extensions.DependencyInjection; public static partial class ServiceCollectionExtensions { private static MasaElasticsearchBuilder CreateElasticsearchClient(this IServiceCollection services, string name) { - var elasticClient = services.BuildServiceProvider().GetRequiredService().CreateElasticClient(name); + var elasticClient = services.BuildServiceProvider().GetRequiredService().Create(name); return new MasaElasticsearchBuilder(services, elasticClient); } @@ -16,15 +18,17 @@ public static MasaElasticsearchBuilder AddElasticsearchClient(this IServiceColle public static MasaElasticsearchBuilder AddElasticsearchClient(this IServiceCollection services, string[]? nodes) => services - .AddElasticsearch(Const.DEFAULT_CLIENT_NAME, nodes == null || nodes.Length == 0 ? new[] {"http://localhost:9200"} : nodes) + .AddElasticsearch(Const.DEFAULT_CLIENT_NAME, nodes == null || nodes.Length == 0 ? new[] { "http://localhost:9200" } : nodes) .CreateElasticsearchClient(Const.DEFAULT_CLIENT_NAME); public static MasaElasticsearchBuilder AddElasticsearchClient(this IServiceCollection services, string name, params string[] nodes) => services.AddElasticsearch(name, nodes).CreateElasticsearchClient(name); - public static MasaElasticsearchBuilder AddElasticsearchClient(this IServiceCollection services, string name, Action action) + public static MasaElasticsearchBuilder AddElasticsearchClient(this IServiceCollection services, string name, + Action action) => services.AddElasticsearch(name, action).CreateElasticsearchClient(name); - public static MasaElasticsearchBuilder AddElasticsearchClient(this IServiceCollection services, string name, Func func) + public static MasaElasticsearchBuilder AddElasticsearchClient(this IServiceCollection services, string name, + Func func) => services.AddElasticsearch(name, func).CreateElasticsearchClient(name); } diff --git a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/Extensions/ServiceCollectionExtensions.cs b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 000000000..829df7a8d --- /dev/null +++ b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,82 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +// ReSharper disable once CheckNamespace + +namespace Microsoft.Extensions.DependencyInjection; + +public static partial class ServiceCollectionExtensions +{ + public static IServiceCollection AddElasticsearch(this IServiceCollection services, string[]? nodes = null) + { + if (nodes == null || nodes.Length == 0) + { + nodes = new[] { "http://localhost:9200" }; + } + + return services.AddElasticsearch(Const.DEFAULT_CLIENT_NAME, nodes); + } + + public static IServiceCollection AddElasticsearch(this IServiceCollection services, string name, params string[] nodes) + => services.AddElasticsearch(name, options => options.UseNodes(nodes)); + + public static IServiceCollection AddElasticsearch(this IServiceCollection services, string name, Action action) + { + return services.AddElasticsearch(name, () => + { + ElasticsearchOptions options = new("http://localhost:9200"); + action.Invoke(options); + return options; + }); + } + + public static IServiceCollection AddElasticsearch(this IServiceCollection services, string name, Func func) + { + ArgumentNullException.ThrowIfNull(name); + + services + .AddElasticsearchCore() + .AddElasticsearchOptions(name, func.Invoke()); + + return services; + } + + private static IServiceCollection AddElasticsearchCore(this IServiceCollection services) + { + ArgumentNullException.ThrowIfNull(services); + + services.TryAddSingleton(); + + services.TryAddSingleton(serviceProvider => + serviceProvider.GetRequiredService().Create()); + + services.TryAddSingleton(serviceProvider + => serviceProvider.GetRequiredService().Create()); + + services.TryAddSingleton(); + services.TryAddSingleton(); + + return services; + } + + private static void AddElasticsearchOptions( + this IServiceCollection services, + string name, + ElasticsearchOptions elasticsearchOptions) + { + services.Configure(name, options => + { + if (elasticsearchOptions.IsDefault) options.UseDefault(); + + options.UseNodes(elasticsearchOptions.Nodes); + options.UseRandomize(elasticsearchOptions.StaticConnectionPoolOptions.Randomize); + options.UseDateTimeProvider(elasticsearchOptions.StaticConnectionPoolOptions.DateTimeProvider); + options.ConnectionSettingsOptions.UseConnection(elasticsearchOptions.ConnectionSettingsOptions.Connection); + options.ConnectionSettingsOptions.UseSourceSerializerFactory(elasticsearchOptions.ConnectionSettingsOptions + .SourceSerializerFactory); + options.ConnectionSettingsOptions.UsePropertyMappingProvider(elasticsearchOptions.ConnectionSettingsOptions + .PropertyMappingProvider); + options.UseConnectionSettings(elasticsearchOptions.Action); + }); + } +} diff --git a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/IElasticClientFactory.cs b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/IElasticClientFactory.cs new file mode 100644 index 000000000..cf83c4ca6 --- /dev/null +++ b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/IElasticClientFactory.cs @@ -0,0 +1,11 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.Utils.Data.Elasticsearch; + +public interface IElasticClientFactory +{ + IElasticClient Create(); + + IElasticClient Create(string name); +} diff --git a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/IElasticsearchFactory.cs b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/IElasticsearchFactory.cs index 0ad3b3cdb..3d85e81d2 100644 --- a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/IElasticsearchFactory.cs +++ b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/IElasticsearchFactory.cs @@ -5,11 +5,15 @@ namespace Masa.Utils.Data.Elasticsearch; public interface IElasticsearchFactory { + [Obsolete("Please use IMasaElasticClientFactory.Create() instead")] IMasaElasticClient CreateClient(); + [Obsolete("Please use IMasaElasticClientFactory.Create(name) instead")] IMasaElasticClient CreateClient(string name); + [Obsolete("Please use IElasticClientFactory.Create() instead")] IElasticClient CreateElasticClient(); + [Obsolete("Please use IElasticClientFactory.Create(name) instead")] IElasticClient CreateElasticClient(string name); } diff --git a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/IMasaElasticClientFactory.cs b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/IMasaElasticClientFactory.cs new file mode 100644 index 000000000..84c653292 --- /dev/null +++ b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/IMasaElasticClientFactory.cs @@ -0,0 +1,11 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.Utils.Data.Elasticsearch; + +public interface IMasaElasticClientFactory +{ + IMasaElasticClient Create(); + + IMasaElasticClient Create(string name); +} diff --git a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/ElasticsearchOptions.cs b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/Options/ElasticsearchOptions.cs similarity index 89% rename from src/Utils/Data/Masa.Utils.Data.Elasticsearch/ElasticsearchOptions.cs rename to src/Utils/Data/Masa.Utils.Data.Elasticsearch/Options/ElasticsearchOptions.cs index b51e57a0a..97c7294fe 100644 --- a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/ElasticsearchOptions.cs +++ b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/Options/ElasticsearchOptions.cs @@ -1,6 +1,8 @@ // Copyright (c) MASA Stack All rights reserved. // Licensed under the MIT License. See LICENSE.txt in the project root for license information. +// ReSharper disable once CheckNamespace + namespace Masa.Utils.Data.Elasticsearch; public class ElasticsearchOptions @@ -17,17 +19,21 @@ public class ElasticsearchOptions internal Action? Action { get; private set; } - public ElasticsearchOptions(params string[] nodes) + public ElasticsearchOptions() + { + IsDefault = false; + ConnectionSettingsOptions = new(); + StaticConnectionPoolOptions = new(); + Action = null; + } + + public ElasticsearchOptions(params string[] nodes) : this() { if (nodes.Length == 0) throw new ArgumentException("Please specify the Elasticsearch node address"); - IsDefault = false; Nodes = nodes; UseConnectionPool = nodes.Length > 1; - ConnectionSettingsOptions = new(); - StaticConnectionPoolOptions = new(); - Action = null; } public ElasticsearchOptions UseDefault() @@ -52,13 +58,13 @@ public ElasticsearchOptions UseRandomize(bool randomize) return this; } - public ElasticsearchOptions UseDateTimeProvider(IDateTimeProvider dateTimeProvider) + public ElasticsearchOptions UseDateTimeProvider(IDateTimeProvider? dateTimeProvider) { StaticConnectionPoolOptions.UseDateTimeProvider(dateTimeProvider); return this; } - public ElasticsearchOptions UseConnectionSettings(Action action) + public ElasticsearchOptions UseConnectionSettings(Action? action) { Action = action; return this; diff --git a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/Options/ElasticsearchRelationsOptions.cs b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/Options/ElasticsearchRelationsOptions.cs deleted file mode 100644 index 6697a7975..000000000 --- a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/Options/ElasticsearchRelationsOptions.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) MASA Stack All rights reserved. -// Licensed under the MIT License. See LICENSE.txt in the project root for license information. - -namespace Masa.Utils.Data.Elasticsearch.Options; - -public class ElasticsearchRelationsOptions -{ - internal readonly Dictionary Relations = new(); - - public ElasticsearchRelationsOptions AddRelation(string name, ElasticsearchOptions options) - { - Uri[] nodes = options.Nodes.Select(uriString => new Uri(uriString)).ToArray(); - ElasticsearchRelations relation = new ElasticsearchRelations(name, options.UseConnectionPool, nodes) - .UseStaticConnectionPoolOptions(options.StaticConnectionPoolOptions) - .UseConnectionSettingsOptions(options.ConnectionSettingsOptions) - .UseConnectionSettings(options.Action); - Relations.Add(name, relation); - return this; - } -} diff --git a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/Options/StaticConnectionPoolOptions.cs b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/Options/StaticConnectionPoolOptions.cs index f11083ec7..4beb58ff7 100644 --- a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/Options/StaticConnectionPoolOptions.cs +++ b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/Options/StaticConnectionPoolOptions.cs @@ -21,7 +21,7 @@ internal StaticConnectionPoolOptions UseRandomize(bool randomize) return this; } - internal StaticConnectionPoolOptions UseDateTimeProvider(IDateTimeProvider dateTimeProvider) + internal StaticConnectionPoolOptions UseDateTimeProvider(IDateTimeProvider? dateTimeProvider) { DateTimeProvider = dateTimeProvider; return this; diff --git a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/ServiceCollectionExtensions.cs b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/ServiceCollectionExtensions.cs deleted file mode 100644 index feba8bd2c..000000000 --- a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) MASA Stack All rights reserved. -// Licensed under the MIT License. See LICENSE.txt in the project root for license information. - -namespace Microsoft.Extensions.DependencyInjection; - -public static partial class ServiceCollectionExtensions -{ - public static IServiceCollection AddElasticsearch(this IServiceCollection services, string[]? nodes = null) - { - if (nodes == null || nodes.Length == 0) - { - nodes = new[] {"http://localhost:9200"}; - } - - return services.AddElasticsearch(Const.DEFAULT_CLIENT_NAME, nodes); - } - - public static IServiceCollection AddElasticsearch(this IServiceCollection services, string name, params string[] nodes) - => services.AddElasticsearch(name, options => options.UseNodes(nodes)); - - public static IServiceCollection AddElasticsearch(this IServiceCollection services, string name, Action action) - { - return services.AddElasticsearch(name, () => - { - ElasticsearchOptions options = new("http://localhost:9200"); - action.Invoke(options); - return options; - }); - } - - public static IServiceCollection AddElasticsearch(this IServiceCollection services, string name, Func func) - { - if (string.IsNullOrEmpty(name)) - { - throw new ArgumentNullException(nameof(name)); - } - - AddElasticsearchCore(services); - - services.TryAddOrUpdateElasticsearchRelation(name, func.Invoke()); - - return services; - } - - private static IServiceCollection AddElasticsearchCore(this IServiceCollection services) - { - ArgumentNullException.ThrowIfNull(services); - - services.TryAddSingleton(); - - services.TryAddSingleton(serviceProvider => - serviceProvider.GetRequiredService().CreateElasticClient()); - - services.TryAddSingleton(serviceProvider => - new DefaultMasaElasticClient(serviceProvider.GetRequiredService())); - - services.TryAddSingleton(new ElasticsearchRelationsOptions()); - - return services; - } - - private static void TryAddOrUpdateElasticsearchRelation(this IServiceCollection services, string name, ElasticsearchOptions options) - { - var serviceProvider = services.BuildServiceProvider(); - var relationsOptions = serviceProvider.GetRequiredService(); - - if (relationsOptions.Relations.ContainsKey(name)) - throw new ArgumentException($"The ElasticClient whose name is {name} is exist"); - - if (options.IsDefault && relationsOptions.Relations.Values.Any(r => r.IsDefault)) - throw new ArgumentNullException(nameof(ElasticsearchRelations.IsDefault), "ElasticClient can only have one default"); - - relationsOptions.AddRelation(name, options); - } -} diff --git a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/_Imports.cs b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/_Imports.cs index 7a55080cd..a82351aa9 100644 --- a/src/Utils/Data/Masa.Utils.Data.Elasticsearch/_Imports.cs +++ b/src/Utils/Data/Masa.Utils.Data.Elasticsearch/_Imports.cs @@ -19,6 +19,7 @@ global using Masa.Utils.Data.Elasticsearch.Response.Document; global using Microsoft.Extensions.DependencyInjection; global using Microsoft.Extensions.DependencyInjection.Extensions; +global using Microsoft.Extensions.Options; global using Nest; global using System.Collections.Concurrent; global using System.Runtime.Serialization; diff --git a/src/Utils/Data/Tests/Masa.Utils.Data.Elasticsearch.Tests/DefaultMasaElasticClientTest.cs b/src/Utils/Data/Tests/Masa.Utils.Data.Elasticsearch.Tests/DefaultMasaElasticClientTest.cs index e752b7e0f..0df14fcfb 100644 --- a/src/Utils/Data/Tests/Masa.Utils.Data.Elasticsearch.Tests/DefaultMasaElasticClientTest.cs +++ b/src/Utils/Data/Tests/Masa.Utils.Data.Elasticsearch.Tests/DefaultMasaElasticClientTest.cs @@ -550,7 +550,16 @@ public async Task TestAsync() var builder = service.AddElasticsearchClient("es", "http://localhost:9200"); await builder.Client.DeleteIndexAsync(userIndexName); var serviceProvider = builder.Services.BuildServiceProvider(); - var client = serviceProvider.GetRequiredService(); + var clientFactory = serviceProvider.GetService(); + Assert.IsNotNull(clientFactory); + var client = clientFactory.Create(); + Assert.IsNotNull(client); + + var masaElasticClientFactory = serviceProvider.GetService(); + Assert.IsNotNull(masaElasticClientFactory); + + client = masaElasticClientFactory.Create("es"); + Assert.IsNotNull(client); var list = new AutoCompleteDocument[] {