1
This commit is contained in:
parent
d40e83ba9c
commit
87f096e0e6
@ -42,5 +42,11 @@
|
||||
"UserName": "dev",
|
||||
"Password": "itd!@#123"
|
||||
}
|
||||
},
|
||||
"ElasticSearch": {
|
||||
"NodeUrls": [ "http://elasticsearch-dev.default.svc.cluster.local:9200" ],
|
||||
"LoginName": "elastic",
|
||||
"Password": "afyTgmVb8jq6",
|
||||
"Base64PassPassword": "Basic ZWxhc3RpYzphZnlUZ21WYjhqcTY="
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
using Fake.Modularity;
|
||||
using System.Configuration;
|
||||
using Fake.Modularity;
|
||||
using Fake.SqlSugarCore;
|
||||
using Fake.UnitOfWork;
|
||||
using InterfaceForward.Repositories.Log.ES;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
@ -20,5 +22,13 @@ public class InterfaceForwardRepositoriesModule : FakeModule
|
||||
});
|
||||
|
||||
context.Services.AddScoped(typeof(IBasicRepository<>), typeof(BasicRepository<>));
|
||||
|
||||
context.Services.Configure<ElasticSearchOptions>(options =>
|
||||
{
|
||||
configuration.GetSection("ElasticSearch").Bind(options);
|
||||
#if !DEBUG
|
||||
options.ShowLogInfo = false;
|
||||
#endif
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,29 +1,25 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
using Elasticsearch.Net;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Nest;
|
||||
|
||||
namespace InterfaceForward.Repositories.Log.ES;
|
||||
|
||||
public class ConnectionFactory
|
||||
public class ConnectionFactory : ISingletonDependency
|
||||
{
|
||||
internal static ElasticSearchOptions _options;
|
||||
internal static ConnectionSettings _connectionSettings;
|
||||
private static ConcurrentDictionary<Type, IElasticClient> _clientDic = new();
|
||||
private readonly ILogger<ConnectionFactory> _logger;
|
||||
private readonly ElasticSearchOptions _options;
|
||||
private readonly ConnectionSettings _connectionSettings;
|
||||
private readonly ConcurrentDictionary<Type, IElasticClient> _clientDic = new();
|
||||
|
||||
#region 构造函数
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
public ConnectionFactory(IOptions<ElasticSearchOptions> options)
|
||||
|
||||
public ConnectionFactory(IOptions<ElasticSearchOptions> options, ILogger<ConnectionFactory> logger)
|
||||
{
|
||||
if (_options == null)
|
||||
_logger = logger;
|
||||
_options = options.Value;
|
||||
|
||||
if (_connectionSettings == null)
|
||||
{
|
||||
var uris = new List<Uri>();
|
||||
foreach (var item in _options.NodeUrls)
|
||||
{
|
||||
@ -33,35 +29,29 @@ public class ConnectionFactory
|
||||
//using var connectionPool = new SniffingConnectionPool(uris);//集群连接池,支持嗅探,ping
|
||||
|
||||
using var connectionPool = new SingleNodeConnectionPool(uris[0]); //单点连接池
|
||||
_connectionSettings = new ConnectionSettings(connectionPool).BasicAuthentication(_options.LoginName, _options.Password);
|
||||
_connectionSettings =
|
||||
new ConnectionSettings(connectionPool).BasicAuthentication(_options.LoginName, _options.Password);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 上下文
|
||||
|
||||
public IElasticClient GetContext(Type type)
|
||||
{
|
||||
IElasticClient client = null;
|
||||
|
||||
//如果有缓存,直接从缓存返回
|
||||
if (_clientDic.ContainsKey(type))
|
||||
if (_clientDic.TryGetValue(type, out var value))
|
||||
{
|
||||
client = _clientDic[type];
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
IElasticClient client;
|
||||
var defaultIndex = "";
|
||||
|
||||
var attr = type.GetCustomAttribute<ElasticsearchTypeAttribute>(false);
|
||||
if (attr == null)
|
||||
throw new Exception("未找到指定对象的index名称");
|
||||
|
||||
//如果启用了index前缀
|
||||
var useIndexNamePrefix = type.GetCustomAttributes(typeof(UseIndexPrefixAttribute), true).Any();
|
||||
if (useIndexNamePrefix && string.IsNullOrEmpty(_options.IndexPrefix))
|
||||
throw new Exception($"{type}启用了index前缀,却没在配置文件中找到相关配置,请检查配置项[ElasticSearch:IndexPrefix]是否指定!");
|
||||
|
||||
defaultIndex = useIndexNamePrefix ? $"{_options.IndexPrefix}{attr.RelationName}" : attr.RelationName;
|
||||
defaultIndex = !_options.IndexPrefix.IsNullOrWhiteSpace()
|
||||
? $"{_options.IndexPrefix}{attr.RelationName}"
|
||||
: attr.RelationName;
|
||||
_connectionSettings.DefaultIndex(defaultIndex);
|
||||
|
||||
//是否输出日志
|
||||
@ -85,13 +75,10 @@ public class ConnectionFactory
|
||||
|
||||
_clientDic.TryAdd(type, client);
|
||||
|
||||
}
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
#region 输出执行结果
|
||||
/// <summary>
|
||||
/// 输出执行结果
|
||||
/// </summary>
|
||||
@ -100,11 +87,8 @@ public class ConnectionFactory
|
||||
private string GetInfosFromApiCallDetails(IApiCallDetails details)
|
||||
{
|
||||
var infos = $@"
|
||||
|-执行时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")}
|
||||
|-执行时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss ffff}
|
||||
|-请求响应:{details.DebugInformation} ";
|
||||
return infos;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -4,35 +4,15 @@ namespace InterfaceForward.Repositories.Log.ES;
|
||||
|
||||
public abstract class ElasticSearchContextAbstract<T> : IElasticsearchClientService<T> where T : IdBaseIndex, new()
|
||||
{
|
||||
private readonly string _indexName;
|
||||
protected IElasticClient Context { get; }
|
||||
|
||||
#region 构造函数
|
||||
private readonly IElasticClient _client;
|
||||
private string _indexName;
|
||||
public ElasticSearchContextAbstract(ConnectionFactory connectionFactory)
|
||||
protected ElasticSearchContextAbstract(ConnectionFactory connectionFactory)
|
||||
{
|
||||
_client = connectionFactory.GetContext(typeof(T));
|
||||
_indexName = _client.ConnectionSettings.DefaultIndex;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 上下文
|
||||
public IElasticClient Context
|
||||
{
|
||||
get
|
||||
{
|
||||
return _client;
|
||||
}
|
||||
Context = connectionFactory.GetContext(typeof(T));
|
||||
_indexName = Context.ConnectionSettings.DefaultIndex;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 新增文档
|
||||
/// <summary>
|
||||
/// 新增文档
|
||||
/// </summary>
|
||||
/// <param name="data">索引数据</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public virtual async Task<string> IndexDocumentAsync(T data)
|
||||
{
|
||||
var response = await Context.IndexAsync(data, request => request.Index(_indexName));
|
||||
@ -42,13 +22,6 @@ public abstract class ElasticSearchContextAbstract<T> : IElasticsearchClientServ
|
||||
return response.Id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量新增文档
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="list"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public virtual async Task<BulkResponse> IndexManyDocumentAsync(List<T> list, bool refresh = false)
|
||||
{
|
||||
var response = await Context.IndexManyAsync<T>(list, _indexName);
|
||||
@ -60,47 +33,22 @@ public abstract class ElasticSearchContextAbstract<T> : IElasticsearchClientServ
|
||||
|
||||
return response;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 根据Id删除文档
|
||||
/// <summary>
|
||||
/// 根据Id删除文档
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public virtual async Task DeleteByIdAsync(string id)
|
||||
{
|
||||
var response = await Context.DeleteAsync<T>(id, i => i.Index(_indexName));
|
||||
if (!response.IsValid)
|
||||
throw new Exception($"数据删除失败,原因:{response.DebugInformation}");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 修改指定的文档
|
||||
/// <summary>
|
||||
/// 修改指定的文档
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public virtual async Task UpdateAsync(string id, T data)
|
||||
{
|
||||
var response = await Context.UpdateAsync<T>(id, u => u.Doc(data).Index(_indexName));
|
||||
if (!response.IsValid)
|
||||
throw new Exception($"数据修改失败,原因:{response.DebugInformation}");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 根据ID获取单条
|
||||
/// <summary>
|
||||
/// 根据ID获取单条文档
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public virtual async Task<T> GetByIdAsync(string id)
|
||||
public virtual async Task<T?> GetByIdAsync(string id)
|
||||
{
|
||||
var response = await Context.GetAsync<T>(id, i => i.Index(_indexName));
|
||||
if (response.Source != null)
|
||||
@ -108,11 +56,10 @@ public abstract class ElasticSearchContextAbstract<T> : IElasticsearchClientServ
|
||||
|
||||
switch (response.ApiCall.HttpStatusCode)
|
||||
{
|
||||
case 200: return response?.Source;
|
||||
case 200: return response.Source;
|
||||
case 404: return null;
|
||||
default: throw new Exception($"数据查询失败,原因:{response.DebugInformation}");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
@ -5,31 +5,25 @@ public class ElasticSearchOptions
|
||||
/// <summary>
|
||||
/// 是否显示日志
|
||||
/// </summary>
|
||||
public bool ShowLogInfo { get; set; } = false;
|
||||
public bool ShowLogInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 服务节点
|
||||
/// </summary>
|
||||
public List<string> NodeUrls { get; set; }
|
||||
public List<string> NodeUrls { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 索引前缀
|
||||
/// </summary>
|
||||
public string IndexPrefix { get; set; }
|
||||
public string? IndexPrefix { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 登录账号
|
||||
/// </summary>
|
||||
public string LoginName { get; set; }
|
||||
public string LoginName { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 登录密码(明文)
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 登录密码(加密)
|
||||
/// </summary>
|
||||
public string Base64PassPassword { get; set; }
|
||||
|
||||
public string Password { get; set; } = null!;
|
||||
}
|
||||
@ -4,10 +4,47 @@ namespace InterfaceForward.Repositories.Log.ES;
|
||||
|
||||
public interface IElasticsearchClientService<T> where T : class
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 新增文档
|
||||
/// </summary>
|
||||
/// <param name="data">索引数据</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
Task<string> IndexDocumentAsync(T data);
|
||||
Task<T> GetByIdAsync(string Id);
|
||||
Task UpdateAsync(string id, T input);
|
||||
Task DeleteByIdAsync(string id);
|
||||
|
||||
/// <summary>
|
||||
/// 批量新增文档
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="refresh"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
Task<BulkResponse> IndexManyDocumentAsync(List<T> list, bool refresh);
|
||||
|
||||
/// <summary>
|
||||
/// 根据ID获取单条文档
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
Task<T?> GetByIdAsync(string id);
|
||||
|
||||
/// <summary>
|
||||
/// 修改指定的文档
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
Task UpdateAsync(string id, T data);
|
||||
|
||||
/// <summary>
|
||||
/// 根据Id删除文档
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
Task DeleteByIdAsync(string id);
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
namespace InterfaceForward.Repositories.Log.ES;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class UseIndexPrefixAttribute : Attribute
|
||||
{
|
||||
public UseIndexPrefixAttribute()
|
||||
{
|
||||
|
||||
}
|
||||
public UseIndexPrefixAttribute(string indexPrefix)
|
||||
{
|
||||
IndexPrefix = indexPrefix;
|
||||
}
|
||||
|
||||
public string IndexPrefix { get; }
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
using InterfaceForward.Domain.Shared.Dtos;
|
||||
using InterfaceForward.Repositories.Log.Entitys;
|
||||
using InterfaceForward.Repositories.Log.ES;
|
||||
using InterfaceForward.Repositories.Log.ValueObjects;
|
||||
using Nest;
|
||||
|
||||
@ -8,7 +9,7 @@ namespace InterfaceForward.Repositories.Log.Services
|
||||
/// <summary>
|
||||
/// 日志仓储
|
||||
/// </summary>
|
||||
public interface ILogRepository
|
||||
public interface ILogRepository : IElasticsearchClientService<LogIndex>
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用id
|
||||
|
||||
Loading…
Reference in New Issue
Block a user