Skip to content

Commit

Permalink
feat(orleans): added orleans aop
Browse files Browse the repository at this point in the history
  • Loading branch information
zhifenglee-aelf committed Oct 9, 2024
1 parent 8be0607 commit 660b902
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 7 deletions.
10 changes: 6 additions & 4 deletions AElf.ExceptionHandler/AOPExceptionModule.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Concurrent;
using Microsoft.Extensions.DependencyInjection;
using Orleans;
using Volo.Abp;
using Volo.Abp.Modularity;

Expand All @@ -10,9 +11,10 @@ public class AOPExceptionModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddTransient<ExceptionHandlerInterceptor>()
.AddTransient<IInterceptor, ExceptionHandler>()
.AddSingleton<ConcurrentDictionary<string, ExceptionHandlerInfo>>()
.AddSingleton<ConcurrentDictionary<string, Func<object, object[], Task>>>();
.AddTransient<IInterceptor, ExceptionHandler>()
.AddSingleton<ConcurrentDictionary<string, ExceptionHandlerInfo>>()
.AddSingleton<ConcurrentDictionary<string, Func<object, object[], Task>>>()
.AddSingleton<IIncomingGrainCallFilter, AttributeCallFilter>();

context.Services.OnRegistered(options =>
{
Expand All @@ -31,4 +33,4 @@ public override void ConfigureServices(ServiceConfigurationContext context)
}
});
}
}
}
64 changes: 64 additions & 0 deletions AElf.ExceptionHandler/AttributeCallFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using Microsoft.Extensions.DependencyInjection;
using Orleans;
using Orleans.Serialization.Invocation;

namespace AElf.ExceptionHandler;

public class AttributeCallFilter : IIncomingGrainCallFilter
{
public async Task Invoke(IIncomingGrainCallContext context)
{
if (context.ImplementationMethod.IsDefined(typeof(ExceptionHandlerAttribute), true))
{
var exceptionHandler = context.TargetContext.ActivationServices.GetService<ExceptionHandler>();

if (exceptionHandler == null)
{
throw new Exception("ExceptionHandler is not registered.");
}

var arguments = new object?[context.Request.GetArgumentCount()];
for (var i = 0; i < context.Request.GetArgumentCount(); ++i)
{
arguments[i] = context.Request.GetArgument(i);
}

var methodExecutionArgs = new MethodExecutionArgs
{
TargetObject = context.Grain,
MethodInfo = context.ImplementationMethod,
Arguments = arguments!,
ReturnValue = null,
Exception = null,
Invocation = async () =>
{
await context.Invoke();
}
};

await exceptionHandler.InterceptAsync(methodExecutionArgs);

if (methodExecutionArgs.Exception != null)
{
context.Response = new ExceptionResponse
{
Exception = methodExecutionArgs.Exception
};
}
else
{
if (methodExecutionArgs.ReturnValue != null)
{
var responseType = typeof(Response<>).MakeGenericType(methodExecutionArgs.ReturnValue.GetType());
var response = Activator.CreateInstance(responseType);
responseType.GetProperty("Result")?.SetValue(response, methodExecutionArgs.ReturnValue);
context.Response = (Response)response!;
}
}
}
else
{
await context.Invoke();
}
}
}
11 changes: 8 additions & 3 deletions AElf.ExceptionHandler/ExceptionHandler.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System.Collections.Concurrent;
using System.Linq.Expressions;
using System.Reflection;
using Volo.Abp.DependencyInjection;

namespace AElf.ExceptionHandler;

public class ExceptionHandler : IInterceptor
public class ExceptionHandler : ITransientDependency, IInterceptor
{
private readonly ConcurrentDictionary<string, ExceptionHandlerInfo> MethodCache;
private readonly ConcurrentDictionary<string, Func<object, object[], Task>> FinallyCache;
Expand Down Expand Up @@ -162,6 +163,7 @@ private bool HandleInnerException(Exception exception, MethodExecutionArgs args,

if(flowBehavior.ExceptionHandlingStrategy == ExceptionHandlingStrategy.Rethrow)
{
args.Exception = exception;
throw exception;
}

Expand All @@ -172,9 +174,12 @@ private bool HandleInnerException(Exception exception, MethodExecutionArgs args,

if(flowBehavior.ExceptionHandlingStrategy == ExceptionHandlingStrategy.Throw)
{
throw (Exception)flowBehavior.ReturnValue!;
var newException = (Exception)flowBehavior.ReturnValue!;
args.Exception = newException;
throw newException;
}


args.Exception = null;
args.ReturnValue = flowBehavior.ReturnValue;
return true;
}
Expand Down
1 change: 1 addition & 0 deletions AElf.ExceptionHandler/MethodExecutionArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ public class MethodExecutionArgs
public object[] Arguments { get; set; }

Check warning on line 9 in AElf.ExceptionHandler/MethodExecutionArgs.cs

View workflow job for this annotation

GitHub Actions / publish

Non-nullable property 'Arguments' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.
public object? ReturnValue { get; set; }
public Func<Task> Invocation { get; set; }

Check warning on line 11 in AElf.ExceptionHandler/MethodExecutionArgs.cs

View workflow job for this annotation

GitHub Actions / publish

Non-nullable property 'Invocation' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.
public Exception? Exception { get; set; }
}

0 comments on commit 660b902

Please sign in to comment.