Browse Source

调整

td_orm
H Vs 1 year ago
parent
commit
8b20f0877e
11 changed files with 135 additions and 306 deletions
  1. +1
    -1
      HealthMonitor.Core/Aop/QueryCacheInterceptorAttribute.cs
  2. +0
    -7
      HealthMonitor.Core/Class1.cs
  3. +4
    -1
      HealthMonitor.Core/Operator/IHealthMonitorOperatorManager.cs
  4. +0
    -30
      HealthMonitor.Core/Pipeline/Aop/Delete/AssertValidDeleteHisValue.cs
  5. +0
    -46
      HealthMonitor.Core/Pipeline/Aop/Delete/DeleteEntityCacheHisValue.cs
  6. +0
    -54
      HealthMonitor.Core/Pipeline/Aop/Query/AssertValidQueryHisValue.cs
  7. +0
    -77
      HealthMonitor.Core/Pipeline/Aop/Query/GetOrInsertEntityCacheHisValue.cs
  8. +100
    -0
      HealthMonitor.Core/Pipeline/Aop/Query/TryGetRefManagerValue.cs
  9. +0
    -30
      HealthMonitor.Core/Pipeline/Aop/Update/AssertValidUpdateHisValue.cs
  10. +6
    -6
      HealthMonitor.WebApi/Controllers/Base/GpsCardControllerBase.cs
  11. +24
    -54
      HealthMonitor.WebApi/Controllers/Base/HealthMonitorControllerBase.cs

+ 1
- 1
HealthMonitor.Core/Aop/QueryCacheInterceptorAttribute.cs View File

@@ -23,7 +23,7 @@ namespace HealthMonitor.Core.Aop

var pipeline = new AopCachePipeline();
pipeline.AddValue(new AssertValidQueryValue());
//pipeline.AddValue(new TryGetRefManagerValue());
pipeline.AddValue(new TryGetRefManagerValue());
pipeline.AddValue(new GetOrInsertEntityCacheValue());
pipeline.AddValue(new AopEndPipeValue());
await pipeline.Start(pipeContext);


+ 0
- 7
HealthMonitor.Core/Class1.cs View File

@@ -1,7 +0,0 @@
namespace HealthMonitor.Core
{
public class Class1
{

}
}

+ 4
- 1
HealthMonitor.Core/Operator/IHealthMonitorOperatorManager.cs View File

@@ -1,4 +1,7 @@
namespace HealthMonitor.Core.Operator
using HealthMonitor.Core.Common;
using HealthMonitor.Util.Common.Operator;

namespace HealthMonitor.Core.Operator
{
/// <summary>
/// HealthMonitor数据库的批量操作缓存管理器


+ 0
- 30
HealthMonitor.Core/Pipeline/Aop/Delete/AssertValidDeleteHisValue.cs View File

@@ -1,30 +0,0 @@
using AspectCore.DynamicProxy;
using HealthMonitor.Core.Common;

namespace HealthMonitor.Core.Pipeline.Aop.Delete
{
public class AssertValidDeleteHisValue : AopValueBase
{
public override async Task Invoke(CacheInterceptorContext context)
{
//方法需要存在参数用于生成缓存键和获取实体类型
if (context.AopContext.Parameters.Length < 2 || context.AopContext.Parameters[0] == null)
{
throw new AssertValidException();
}

var param = context.AopContext.Parameters[0];
var entityType = param.GetType();

context.IsAsyncMethod = context.AopContext.IsAsync();
context.EntityType = entityType;
context.RequestId = context.AopContext.Parameters.Length > 2 ? context.AopContext.Parameters[2] + "" : "";

using (var scope = context.Logger.BeginScope(new Dictionary<string, object> { ["RequestId"] = context.RequestId }))
using (new CustomizeStopWatch($"删除历史aop[{entityType.Name}]", context.Logger))
{
await InvokeNextAsync(context);
}
}
}
}

+ 0
- 46
HealthMonitor.Core/Pipeline/Aop/Delete/DeleteEntityCacheHisValue.cs View File

@@ -1,46 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using HealthMonitor.Core.Cache;
using HealthMonitor.Util.Common;
using HealthMonitor.Util.Entities.Interfaces;

namespace HealthMonitor.Core.Pipeline.Aop.Delete
{
public class DeleteEntityCacheHisValue : AopValueBase
{
public override async Task Invoke(CacheInterceptorContext context)
{
var entityType = context.EntityType;
var param = context.AopContext.Parameters[0];
var paramImei = context.AopContext.Parameters[1] as string;
var paramDate = (context.AopContext.Parameters.Length > 2 ? context.AopContext.Parameters[2] : null) as DateTime?;

//自增型主键无法预测其键值,所以不做缓存
if (EntityUtils.HasAutoGenerateKey(entityType))
{
await InvokeNextAsync(context);
return;
}

var durableManager = context.AopContext.ServiceProvider.GetService<IDurableEntityManager>();
var cacheHandler = durableManager?.GetCacheHandler(entityType);
//若实体类型不支持缓存,则退出
if (cacheHandler == null || cacheHandler.DurableSecond <= 0)
{
await InvokeNextAsync(context);
return;
}

string id = entityType!.GetMethod(nameof(IEntity.GetPrimaryKey))?.Invoke(param, null) + "";
if (!string.IsNullOrEmpty(id))
{
string key = durableManager!.CalcHistoryCacheKey(entityType, id, paramImei!, paramDate);
if (!string.IsNullOrEmpty(key))
{
cacheHandler.DeleteEntityCache(key);
}
}

await InvokeNextAsync(context);
}
}
}

+ 0
- 54
HealthMonitor.Core/Pipeline/Aop/Query/AssertValidQueryHisValue.cs View File

@@ -1,54 +0,0 @@
using AspectCore.DynamicProxy;
using AspectCore.DynamicProxy.Parameters;
using System.Collections;
using HealthMonitor.Core.Common;

namespace HealthMonitor.Core.Pipeline.Aop.Query
{
public class AssertValidQueryHisValue : AopValueBase
{
public override async Task Invoke(CacheInterceptorContext context)
{
var methodReturnType = context.AopContext.GetReturnParameter().Type;
//先判断方法是否有返回值,无就不进行缓存判断
if (methodReturnType == typeof(void) || methodReturnType == typeof(Task))
{
throw new AssertValidException();
}
//方法需要存在参数用于生成缓存键
if (context.AopContext.Parameters.Length < 3)
{
throw new AssertValidException();
}

var returnType = methodReturnType;
//判断是否是异步方法
bool isAsync = context.AopContext.IsAsync();
if (isAsync)
{
//取得异步返回的类型
returnType = methodReturnType.GenericTypeArguments.FirstOrDefault();
}

var entityType = returnType;
bool isEnumerable = false;
if (returnType?.GetInterface(typeof(IEnumerable).Name) != null)
{
entityType = returnType.GenericTypeArguments.FirstOrDefault();
isEnumerable = true;
}

context.EntityType = entityType!;
context.ReturnType = returnType!;
context.IsAsyncMethod = isAsync;
context.IsReturnEnumerable = isEnumerable;
context.RequestId = context.AopContext.Parameters.Length > 3 ? context.AopContext.Parameters[3] + "" : "";

using (var scope = context.Logger.BeginScope(new Dictionary<string, object> { ["RequestId"] = context.RequestId }))
using (new CustomizeStopWatch($"查询历史aop[{entityType?.Name}]", context.Logger))
{
await InvokeNextAsync(context);
}
}
}
}

+ 0
- 77
HealthMonitor.Core/Pipeline/Aop/Query/GetOrInsertEntityCacheHisValue.cs View File

@@ -1,77 +0,0 @@
using AspectCore.DynamicProxy;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Reflection;
using HealthMonitor.Core.Cache;
using HealthMonitor.Util.Models;

namespace HealthMonitor.Core.Pipeline.Aop.Query
{
public class GetOrInsertEntityCacheHisValue : AopValueBase
{
private static MethodInfo M_TaskFromResult = typeof(Task).GetMethod(nameof(Task.FromResult))!;

public override async Task Invoke(CacheInterceptorContext context)
{
var entityType = context.EntityType;
var returnType = context.ReturnType;
var isAsync = context.IsAsyncMethod;
var isEnumerable = context.IsReturnEnumerable;
var param = context.AopContext.Parameters[0];
var paramImei = context.AopContext.Parameters[1] as string;
var paramDate = context.AopContext.Parameters[2] as DateTime?;
string? key = null;

//读取缓存
var durableManager = context.AopContext.ServiceProvider.GetService<IDurableEntityManager>();
var cacheHandler = durableManager?.GetCacheHandler(entityType);
//若实体类型不支持缓存,则退出
if (cacheHandler == null || cacheHandler.DurableSecond <= 0)
{
await InvokeNextAsync(context);
return;
}

if (param is string) key = durableManager?.CalcHistoryCacheKey(entityType, param.ToString()!, paramImei!, paramDate);
else if (param is GeneralParam) key = durableManager?.CalcHistoryCacheKey(entityType, (param as GeneralParam)!, paramImei!, paramDate);

if (string.IsNullOrEmpty(key))
{
await InvokeNextAsync(context);
return;
}

var cache = cacheHandler.GetEntitiesCache(key);
object? returnValue;
if (cache != null)
{
context.Logger.LogInformation($"击中实体缓存{key}");

returnValue = isEnumerable ? cache : cache.FirstOrDefault();
if (isAsync) //&& methodReturnType == typeof(Task<>).MakeGenericType(returnType))
{
//反射获取Task<>类型的返回值,相当于Task.FromResult(value);
context.AopContext.ReturnValue = M_TaskFromResult.MakeGenericMethod(returnType).Invoke(null, new[] { returnValue });
return;
}

context.AopContext.ReturnValue = returnValue;
return;
}

await InvokeNextAsync(context);

if (isAsync)
{
returnValue = await context.AopContext.UnwrapAsyncReturnValue();
//反射获取异步结果的值,相当于(context.ReturnValue as Task<>).Result
//returnValue = typeof(Task<>).MakeGenericType(returnType).GetProperty(nameof(Task<object>.Result)).GetValue(context.ReturnValue);
}
else
{
returnValue = context.AopContext.ReturnValue;
}
cacheHandler.SetEntityCache(key, returnValue, isEnumerable);
}
}
}

+ 100
- 0
HealthMonitor.Core/Pipeline/Aop/Query/TryGetRefManagerValue.cs View File

@@ -0,0 +1,100 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Reflection;
using System.Threading.Tasks;
using HealthMonitor.Core.Operator;
using HealthMonitor.Util.Common.Operator;
using HealthMonitor.Util.Entities.Base;
using HealthMonitor.Util.Entities.Interfaces;

namespace HealthMonitor.Core.Pipeline.Aop.Query
{
public class TryGetRefManagerValue:AopValueBase
{
private readonly static MethodInfo M_TaskFromResult = typeof(Task).GetMethod(nameof(Task.FromResult))!;

public override async Task Invoke(CacheInterceptorContext context)
{
var entityType = context.EntityType;
var returnType = context.ReturnType;
var isAsync = context.IsAsyncMethod;
var isEnumerable = context.IsReturnEnumerable;
var param = context.AopContext.Parameters[0];

if (entityType == null || returnType == null
|| isEnumerable //从待插入队列中读取实体,不支持读取多个实体(列表)
|| !(param is string))
{
await InvokeNextAsync(context);
return;
}

//计算key值
var entity = Activator.CreateInstance(entityType);
var method = entityType.GetMethod(nameof(IEntity.GetUniqueKey));
var key = method?.Invoke(entity, new[] { param }) + "";

if (string.IsNullOrEmpty(key))
{
await InvokeNextAsync(context);
return;
}

OperateCacheItem cacheItem = null!;
bool isDeleted = false;
/*
* 注意这里是有并发的可能性(负责增删改的后台线程会执行2个步骤:a、从待插入列表中获取并删除实体数据,b、获取到的实体数据入库,当查询发生在a与b之间就会出现该并发情况)
* 因为该并发情况发生几率很低,而且更重要的一点是查询的性能要求比较高尽量不能加互斥锁,所以该并发允许存在,不作修改
*/
IOperatorManager operatorManager = null!;
//if (entityType.IsSubclassOf(typeof(GpsCardEntityBase))) operatorManager = context.AopContext.ServiceProvider.GetService<IGpsCardOperatorManager>();
//else if (entityType.IsSubclassOf(typeof(TelpoCommonEntityBase))) operatorManager = context.AopContext.ServiceProvider.GetService<ITelpoCommonOperatorManager>();

if (operatorManager != null)
{
cacheItem = operatorManager.GetDelayOperator(DelayOperateTypeEnum.Insert, key)!;
if (cacheItem == null) cacheItem = operatorManager.GetDelayOperator(DelayOperateTypeEnum.Update, key)!;
if (cacheItem == null && operatorManager.GetDelayOperator(DelayOperateTypeEnum.Delete, key) != null) isDeleted = true;
//从pending状态的数据中检索
if (cacheItem == null && operatorManager.PendingInsertOperators != null) operatorManager.PendingInsertOperators.TryGetValue(key, out cacheItem!);
if (cacheItem == null && operatorManager.PendingUpdateOperators != null) operatorManager.PendingUpdateOperators.TryGetValue(key, out cacheItem!);

if (cacheItem != null)
{
context.Logger.LogInformation($"击中操作缓存{key}");

entity = JsonConvert.DeserializeObject(cacheItem.JsonData!, entityType) as IEntity; //强制转换as将导致返回null或者IEntity实例,然后赋值给object类型
if (entity != null)
{
if (isAsync) //&& methodReturnType == typeof(Task<>).MakeGenericType(returnType))
{
//反射获取Task<>类型的返回值,相当于Task.FromResult(value);
context.AopContext.ReturnValue = M_TaskFromResult.MakeGenericMethod(returnType).Invoke(null, new[] { entity });
return;
}

context.AopContext.ReturnValue = entity;
return;
}
}
}

if (isDeleted)
{
if (isAsync)
{
//反射获取Task<>类型的返回值,相当于Task.FromResult(value);
context.AopContext.ReturnValue = M_TaskFromResult.MakeGenericMethod(returnType).Invoke(null, new object[] { null! });
return;
}

context.AopContext.ReturnValue = null;
return;
}

await InvokeNextAsync(context);
}
}
}

+ 0
- 30
HealthMonitor.Core/Pipeline/Aop/Update/AssertValidUpdateHisValue.cs View File

@@ -1,30 +0,0 @@
using AspectCore.DynamicProxy;
using HealthMonitor.Core.Common;

namespace HealthMonitor.Core.Pipeline.Aop.Update
{
public class AssertValidUpdateHisValue : AopValueBase
{
public override async Task Invoke(CacheInterceptorContext context)
{
//方法需要存在参数用于生成缓存键和获取实体类型
if (context.AopContext.Parameters.Length < 2 || context.AopContext.Parameters[0] == null)
{
throw new AssertValidException();
}

var param = context.AopContext.Parameters[0];
var entityType = param.GetType();

context.IsAsyncMethod = context.AopContext.IsAsync();
context.EntityType = entityType;
context.RequestId = context.AopContext.Parameters.Length > 2 ? context.AopContext.Parameters[2] + "" : "";

using (var scope = context.Logger.BeginScope(new Dictionary<string, object> { ["RequestId"] = context.RequestId }))
using (new CustomizeStopWatch($"更新历史aop[{entityType.Name}]", context.Logger))
{
await InvokeNextAsync(context);
}
}
}
}

+ 6
- 6
HealthMonitor.WebApi/Controllers/Base/GpsCardControllerBase.cs View File

@@ -44,7 +44,7 @@ namespace HealthMonitor.WebApi.Controllers.Base
/// <param name="requestId">关联服务标识</param>
/// <returns></returns>
[HttpGet]
[QueryCacheInterceptor]
//[QueryCacheInterceptor]
public async virtual Task<T> GetById([Required] string id, [FromHeader] string requestId)
{
AssertModelStateIsValid();
@@ -60,7 +60,7 @@ namespace HealthMonitor.WebApi.Controllers.Base
/// <param name="requestId">关联服务标识</param>
/// <returns></returns>
[HttpPost]
[QueryCacheInterceptor]
//[QueryCacheInterceptor]
public async virtual Task<T?> GetFirst([FromBody] GeneralParam conditions, [FromHeader] string requestId)
{
AssertModelStateIsValid();
@@ -79,7 +79,7 @@ namespace HealthMonitor.WebApi.Controllers.Base
/// <param name="requestId">关联服务标识</param>
/// <returns></returns>
[HttpPost]
[QueryCacheInterceptor]
//[QueryCacheInterceptor]
public async virtual Task<IEnumerable<T>> GetList([FromBody] GeneralParam conditions, [FromHeader] string requestId)
{
AssertModelStateIsValid();
@@ -96,7 +96,7 @@ namespace HealthMonitor.WebApi.Controllers.Base
/// <param name="model"></param>
/// <param name="requestId">关联服务标识</param>
[HttpPost]
[InsertCacheInterceptor]
//[InsertCacheInterceptor]
public virtual void Add([FromBody] T model, [FromHeader] string requestId)
{
AssertModelStateIsValid(model);
@@ -117,7 +117,7 @@ namespace HealthMonitor.WebApi.Controllers.Base
/// <param name="model"></param>
/// <param name="requestId">关联服务标识</param>
[HttpPut]
[UpdateCacheInterceptor]
//[UpdateCacheInterceptor]
public virtual void Update([FromBody] T model, [FromHeader] string requestId)
{
AssertModelStateIsValid(model);
@@ -138,7 +138,7 @@ namespace HealthMonitor.WebApi.Controllers.Base
/// <param name="model"></param>
/// <param name="requestId">关联服务标识</param>
[HttpDelete]
[DeleteCacheInterceptor]
// [DeleteCacheInterceptor]
public virtual void Delete([FromBody] T model, [FromHeader] string requestId)
{
//删除操作不需要验证模型的有效性


+ 24
- 54
HealthMonitor.WebApi/Controllers/Base/HealthMonitorControllerBase.cs View File

@@ -66,33 +66,33 @@ namespace HealthMonitor.WebApi.Controllers.Base
return await _dataAccessor.GetByIDAsync<T>(id);
}

/// <summary>
/// 通过查询条件,获取符合条件的第一个实体
/// </summary>
/// <param name="conditions"></param>
/// <param name="requestId">关联服务标识</param>
/// <returns></returns>
//[HttpPost]
// //[QueryCacheInterceptor]
// public async virtual Task<T?> GetFirst([FromBody] GeneralParam conditions, [FromHeader] string requestId)
//{
// AssertModelStateIsValid();
/// <summary>
/// 通过查询条件,获取符合条件的第一个实体
/// </summary>
/// <param name="conditions"></param>
/// <param name="requestId">关联服务标识</param>
/// <returns></returns>
[HttpPost]

// var parser = new QueryExpressionParser<T>();
// var expression = parser.ParserConditions(conditions.Filters!);
// var list = await _dataAccessor.GetMany(expression).OrderConditions(conditions.OrderBys!).Take(1).ToListAsync();
//[QueryCacheInterceptor]
public async virtual Task<T?> GetFirst([FromBody] GeneralParam conditions, [FromHeader] string requestId)
{
AssertModelStateIsValid();

// return list.Count > 0 ? list[0] : null;
//}
var parser = new QueryExpressionParser<T>();
var expression = parser.ParserConditions(conditions.Filters!);
var list = await _dataAccessor.GetMany(expression).OrderConditions(conditions.OrderBys!).Take(1).ToListAsync();

/// <summary>
/// 获取实体列表(只提取符合条件的前100条记录)
/// </summary>
/// <param name="conditions"></param>
/// <param name="requestId">关联服务标识</param>
/// <returns></returns>
[HttpPost]
return list.Count > 0 ? list[0] : null;
}

/// <summary>
/// 获取实体列表(只提取符合条件的前100条记录)
/// </summary>
/// <param name="conditions"></param>
/// <param name="requestId">关联服务标识</param>
/// <returns></returns>
[HttpPost]

//[QueryCacheInterceptor]
public async virtual Task<PageData<T>> GetPageList([FromBody] Paging page, [FromHeader] string requestId)
@@ -110,39 +110,9 @@ namespace HealthMonitor.WebApi.Controllers.Base

public async virtual Task<IEnumerable<T>> GetList([FromBody] GeneralParam conditions, [FromHeader] string requestId)
{
/**
* {
"filters": [
{
"key": "id",
"value": "aaa",
"valueType": 7,
"operator": 0
}
],
"orderBys": [
{
"key": "id",
"isDesc": true
}
]
}
*
*
*
*/
AssertModelStateIsValid();

var parser = new QueryExpressionParser<T>();




var expression = parser.ParserConditions(conditions.Filters!);
var aa = conditions.Filters!;
var cc = await _dataAccessor.GetMany(expression).ToListAsync();

var dd = conditions.OrderBys!;
var list = await _dataAccessor.GetMany(expression).OrderConditions(conditions.OrderBys!).Take(100).ToListAsync();
return list;



Loading…
Cancel
Save