Skip to content

Commit

Permalink
Cache example
Browse files Browse the repository at this point in the history
  • Loading branch information
Asli Yigit authored and Asli Yigit committed Dec 13, 2023
1 parent 1376c71 commit 42a2693
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 2 deletions.
118 changes: 118 additions & 0 deletions samples/NexusAop.Console/Cache/CacheMethodAttribute.cs
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);
}

}

}
10 changes: 10 additions & 0 deletions samples/NexusAop.Console/Models/CacheResultModel.cs
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?>>();
}
}
21 changes: 21 additions & 0 deletions samples/NexusAop.Console/Models/FooEntity.cs
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);
}

}
}
12 changes: 12 additions & 0 deletions samples/NexusAop.Console/Program.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// See https://aka.ms/new-console-template for more information

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NexusAop.Console.Repository;
using NexusAop.Console.Service;
using NexusAop.Extensions;

Expand All @@ -15,6 +17,7 @@ public static async Task Main(
string[] arg)
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<IFooRepository, FooRepository>();
serviceCollection.AddSingletonWithCustomAop<ITestService, TestService>();

serviceCollection.AddLogging(configure =>
Expand All @@ -26,6 +29,15 @@ public static async Task Main(

var svc = provider.GetRequiredService<ITestService>();

// Id=xxx
var result= await svc.GetFooAsync(true);

// Id=xxx
var resultWithCache = await svc.GetFooAsync(true);
Thread.Sleep(20000);

// Id=yyy
var resultAfterTimeoutCache = await svc.GetFooAsync(true);

svc.MyStringMethod();

Expand Down
37 changes: 37 additions & 0 deletions samples/NexusAop.Console/Repository/FooRepository.cs
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"
});
}
}

}
20 changes: 20 additions & 0 deletions samples/NexusAop.Console/Repository/IFooRepository.cs
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);
}

}
14 changes: 13 additions & 1 deletion samples/NexusAop.Console/Service/ITestService.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
using System.Threading;
using System.Threading.Tasks;
using NexusAop.Console.Cache;
using NexusAop.Console.CustomAspect;
using NexusAop.Console.Models;

namespace NexusAop.Console.Service
{
public interface ITestService
{
{
[CacheMethod(10)]
int GetBalance(
int id);

[CacheMethod(20)]
Task<FooEntity> GetFooAsync(
bool isGoodNumber,
CancellationToken cancellationToken = default);

[CustomAspect]
void MyVoidMethod();

Expand Down
35 changes: 34 additions & 1 deletion samples/NexusAop.Console/Service/TestService.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,42 @@
using NexusAop.Console.Models;
using System.Threading;
using System;
using System.Threading.Tasks;
using NexusAop.Console.Repository;

namespace NexusAop.Console.Service
{
public class TestService : ITestService
{
{
private readonly IFooRepository _fooRepository;

public TestService(
IFooRepository fooRepository)
{
_fooRepository = fooRepository;
}
public int GetBalance(
int id)
{
System.Console.WriteLine($"Checking id for {id}!");
var balance = new Random().Next(11111);
Task.Delay(balance).GetAwaiter().GetResult();
return balance;
}

public async Task<FooEntity> GetFooAsync(
bool isGoodNumber,
CancellationToken cancellationToken = default)
{
var number = new Random().Next(9000);
await Task.Delay(number, cancellationToken);
var foo = await _fooRepository.GetByIdAsync(2, cancellationToken);
return new FooEntity()
{
Id = number,
Text = DateTime.Now.ToLongDateString()
};
}
public string MyStringMethod()
{
//System.Console.WriteLine("My string method.");
Expand Down

0 comments on commit 42a2693

Please sign in to comment.