-
Notifications
You must be signed in to change notification settings - Fork 0
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
Asli Yigit
authored and
Asli Yigit
committed
Dec 13, 2023
1 parent
1376c71
commit 42a2693
Showing
8 changed files
with
265 additions
and
2 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Newtonsoft.Json; | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Security.Cryptography; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using NexusAop.Console.Models; | ||
|
||
namespace NexusAop.Console.Cache | ||
{ | ||
public class CacheMethodAttribute : NexusAopAttribute | ||
{ | ||
public CacheMethodAttribute( | ||
int ttlAsSecond) | ||
{ | ||
Ttl = TimeSpan.FromSeconds(ttlAsSecond); | ||
} | ||
|
||
public CacheMethodAttribute() | ||
{ | ||
Ttl = null; | ||
} | ||
|
||
public TimeSpan? Ttl { get; set; } | ||
|
||
public override async Task ExecuteAsync(NexusAopContext context) | ||
{ | ||
if (!CheckMethodCacheable(context.TargetMethod)) | ||
{ | ||
return; | ||
} | ||
var cacheKey = GetCacheKey(context.TargetMethod, context.TargetMethodsArgs); | ||
var result = GetResult(cacheKey); | ||
|
||
// read from cache | ||
if (result != null) | ||
{ | ||
context.Result= result; | ||
return; | ||
} | ||
|
||
result = await context.SetResultAsync(); | ||
await SetCacheAsync(context.TargetMethod, context.TargetMethodsArgs,result); | ||
} | ||
|
||
public void CacheResult( | ||
string key, | ||
object value, | ||
TimeSpan? ttl = null) | ||
{ | ||
DateTime? expDate = ttl.HasValue ? DateTime.Now.Add(ttl.Value) : null; | ||
CacheResultModel.Store.TryAdd(key, new Tuple<object, DateTime?>(value, expDate)); | ||
} | ||
|
||
public object GetResult( | ||
string key) | ||
{ | ||
if (!CacheResultModel.Store.ContainsKey(key)) return null; | ||
var value = CacheResultModel.Store[key]; | ||
if (!value.Item2.HasValue || value.Item2.Value >= DateTime.Now) | ||
{ | ||
return value.Item1; | ||
} | ||
|
||
CacheResultModel.Store.Remove(key, out _); | ||
return null; | ||
} | ||
|
||
|
||
protected virtual Task SetCacheAsync( | ||
MethodInfo targetMethod, | ||
object[] args, | ||
object result) | ||
{ | ||
if (result == null || !CheckMethodCacheable(targetMethod)) | ||
{ | ||
return Task.CompletedTask; | ||
} | ||
|
||
var cacheAttribute = targetMethod.GetCustomAttribute<CacheMethodAttribute>(); | ||
var key = GetCacheKey(targetMethod, args); | ||
CacheResult(key, result, cacheAttribute.Ttl); | ||
|
||
return Task.CompletedTask; | ||
} | ||
|
||
private bool CheckMethodCacheable( | ||
MethodInfo targetMethod) | ||
{ | ||
return targetMethod.ReturnType != typeof(void) | ||
&& targetMethod.ReturnType != typeof(Task) | ||
&& targetMethod.CustomAttributes.Any(x => x.AttributeType == typeof(CacheMethodAttribute)); | ||
} | ||
|
||
protected virtual string GetCacheKey( | ||
MethodInfo targetMethod, | ||
object[] args) | ||
{ | ||
var stringBuilder = new StringBuilder(targetMethod.Name); | ||
stringBuilder.AppendJoin(";", targetMethod.ReflectedType.Name); | ||
stringBuilder.AppendJoin(";", targetMethod.ReturnType.Name); | ||
|
||
if (args != null && args.Any()) | ||
{ | ||
stringBuilder.AppendJoin(";", JsonConvert.SerializeObject(args)); | ||
} | ||
|
||
var hash = SHA256.Create().ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringBuilder.ToString())); | ||
return Convert.ToBase64String(hash); | ||
} | ||
|
||
} | ||
|
||
} |
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,10 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace NexusAop.Console.Models | ||
{ | ||
public class CacheResultModel | ||
{ | ||
public static Dictionary<string, Tuple<object, DateTime?>> Store { get; set; } = new Dictionary<string, Tuple<object, DateTime?>>(); | ||
} | ||
} |
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,21 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Text.Json; | ||
using System.Threading.Tasks; | ||
|
||
namespace NexusAop.Console.Models | ||
{ | ||
public class FooEntity | ||
{ | ||
public int Id { get; set; } | ||
public string Text { get; set; } | ||
|
||
public override string ToString() | ||
{ | ||
return JsonSerializer.Serialize(this); | ||
} | ||
|
||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using NexusAop.Console.Models; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using static NexusAop.Console.Repository.FooRepository; | ||
|
||
namespace NexusAop.Console.Repository | ||
{ | ||
|
||
public class FooRepository : IFooRepository | ||
{ | ||
public FooEntity GetById( | ||
int id) | ||
{ | ||
return new FooEntity() | ||
{ | ||
Id = id, | ||
Text = "text" | ||
}; | ||
} | ||
|
||
public Task<FooEntity> GetByIdAsync( | ||
int id, | ||
CancellationToken cancellationToken = default) | ||
{ | ||
return Task.FromResult(new FooEntity() | ||
{ | ||
Id = id, | ||
Text = "Async Text" | ||
}); | ||
} | ||
} | ||
|
||
} |
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,20 @@ | ||
using NexusAop.Console.Models; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace NexusAop.Console.Repository | ||
{ | ||
public interface IFooRepository | ||
{ | ||
FooEntity GetById(int id); | ||
|
||
Task<FooEntity> GetByIdAsync( | ||
int id, | ||
CancellationToken cancellationToken = default); | ||
} | ||
|
||
} |
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