Бэкенд отмены задачи
This commit is contained in:
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Example.Shared;
|
using Example.Shared;
|
||||||
using mROA.Implementation.Attributes;
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
@@ -26,5 +28,10 @@ namespace Example.Backend
|
|||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task AsyncTest(CancellationToken token)
|
||||||
|
{
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(5), token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,8 @@ class Program
|
|||||||
builder.Modules.Add(new CreativeRepresentationModuleProducer(
|
builder.Modules.Add(new CreativeRepresentationModuleProducer(
|
||||||
new IInjectableModule[] { builder.GetModule<JsonSerializationToolkit>()! },
|
new IInjectableModule[] { builder.GetModule<JsonSerializationToolkit>()! },
|
||||||
typeof(RepresentationModule)));
|
typeof(RepresentationModule)));
|
||||||
|
builder.Modules.Add(new CancellationRepository());
|
||||||
|
|
||||||
builder.Build();
|
builder.Build();
|
||||||
new RemoteTypeBinder();
|
new RemoteTypeBinder();
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ class Program
|
|||||||
|
|
||||||
var name = printer.Value.GetName();
|
var name = printer.Value.GetName();
|
||||||
Console.WriteLine("Printer name : {0}", name);
|
Console.WriteLine("Printer name : {0}", name);
|
||||||
|
|
||||||
Thread.Sleep(100);
|
Thread.Sleep(100);
|
||||||
|
|
||||||
factory.Register(new SharedObject<IPrinter>(new ClientBasedPrinter()));
|
factory.Register(new SharedObject<IPrinter>(new ClientBasedPrinter()));
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using mROA.Implementation.Attributes;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using mROA.Implementation.Attributes;
|
||||||
|
|
||||||
namespace Example.Shared
|
namespace Example.Shared
|
||||||
{
|
{
|
||||||
@@ -9,6 +11,8 @@ namespace Example.Shared
|
|||||||
int Last(int next);
|
int Last(int next);
|
||||||
void C();
|
void C();
|
||||||
void A();
|
void A();
|
||||||
|
|
||||||
|
Task AsyncTest(CancellationToken token = default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -120,7 +121,8 @@ namespace {Namespace}
|
|||||||
|
|
||||||
|
|
||||||
bool isAsync = method.ReturnType.Name == "Task";
|
bool isAsync = method.ReturnType.Name == "Task";
|
||||||
bool isVoid = method.ReturnType.Name == "Void" || method.ReturnType.ToString() == "Task";
|
bool isVoid = method.ReturnType.Name == "Void" ||
|
||||||
|
method.ReturnType.ToString() == "System.Threading.Tasks.Task";
|
||||||
bool isParametrized = method.Parameters.Length == 1 && !isAsync ||
|
bool isParametrized = method.Parameters.Length == 1 && !isAsync ||
|
||||||
method.Parameters.Length == 2 && isAsync;
|
method.Parameters.Length == 2 && isAsync;
|
||||||
|
|
||||||
@@ -135,9 +137,16 @@ namespace {Namespace}
|
|||||||
var prefix = isAsync ? "await " : "";
|
var prefix = isAsync ? "await " : "";
|
||||||
var postfix = !isAsync ? (isVoid ? ".Wait()" : ".GetAwaiter().GetResult()") : "";
|
var postfix = !isAsync ? (isVoid ? ".Wait()" : ".GetAwaiter().GetResult()") : "";
|
||||||
var parameterLink = isParametrized ? ", " + method.Parameters.First().Name : string.Empty;
|
var parameterLink = isParametrized ? ", " + method.Parameters.First().Name : string.Empty;
|
||||||
var caller = isVoid ? $"CallAsync({index}{parameterLink})" :
|
var tokenInsert = isAsync
|
||||||
isAsync ? $"GetResultAsync<{ExtractTaskType(method.ReturnType)}>({index}{parameterLink})" :
|
? isParametrized
|
||||||
$"GetResultAsync<{ToFullString(method.ReturnType)}>({index}{parameterLink})";
|
? ", cancellationToken : " + method.Parameters[1].Name
|
||||||
|
: ", cancellationToken : " + method.Parameters[0].Name
|
||||||
|
: String.Empty;
|
||||||
|
var caller = isVoid
|
||||||
|
? $"CallAsync({index}{parameterLink}{tokenInsert})"
|
||||||
|
: isAsync
|
||||||
|
? $"GetResultAsync<{ExtractTaskType(method.ReturnType)}>({index}{parameterLink}{tokenInsert})"
|
||||||
|
: $"GetResultAsync<{ToFullString(method.ReturnType)}>({index}{parameterLink}{tokenInsert})";
|
||||||
|
|
||||||
if (!isVoid)
|
if (!isVoid)
|
||||||
prefix = "return " + prefix;
|
prefix = "return " + prefix;
|
||||||
@@ -195,7 +204,6 @@ namespace {namespaceName}
|
|||||||
";
|
";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Add the source code to the compilation.
|
// Add the source code to the compilation.
|
||||||
context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8));
|
context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8));
|
||||||
|
|
||||||
@@ -250,7 +258,7 @@ namespace mROA.Codegen
|
|||||||
";
|
";
|
||||||
context.AddSource($"CoCodegenMethodRepository.g.cs", SourceText.From(coCodegenRepoCode, Encoding.UTF8));
|
context.AddSource($"CoCodegenMethodRepository.g.cs", SourceText.From(coCodegenRepoCode, Encoding.UTF8));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frontendContextRepo.Count != 0)
|
if (frontendContextRepo.Count != 0)
|
||||||
{
|
{
|
||||||
var fronendRepoCode = @$"// <auto-generated/>
|
var fronendRepoCode = @$"// <auto-generated/>
|
||||||
@@ -324,7 +332,7 @@ namespace mROA.Codegen
|
|||||||
|
|
||||||
GenerateCode(context, context.Compilation, interfaces.ToImmutableArray());
|
GenerateCode(context, context.Compilation, interfaces.ToImmutableArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ContainsSOIAttribute(SyntaxList<AttributeListSyntax> attributes, GeneratorExecutionContext context,
|
private bool ContainsSOIAttribute(SyntaxList<AttributeListSyntax> attributes, GeneratorExecutionContext context,
|
||||||
InterfaceDeclarationSyntax interfaceDeclarationSyntax)
|
InterfaceDeclarationSyntax interfaceDeclarationSyntax)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace mROA.Abstract
|
||||||
|
{
|
||||||
|
public interface ICancellationRepository : IInjectableModule
|
||||||
|
{
|
||||||
|
void RegisterCancellation(Guid id, CancellationTokenSource cts);
|
||||||
|
CancellationTokenSource? GetCancellation(Guid id);
|
||||||
|
void FreeCancelation(Guid id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,6 @@ namespace mROA.Abstract
|
|||||||
{
|
{
|
||||||
public interface IExecuteModule : IInjectableModule
|
public interface IExecuteModule : IInjectableModule
|
||||||
{
|
{
|
||||||
ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository);
|
ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository, IRepresentationModule representationModule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,20 +10,26 @@ namespace mROA.Implementation.Backend
|
|||||||
public class BasicExecutionModule : IExecuteModule
|
public class BasicExecutionModule : IExecuteModule
|
||||||
{
|
{
|
||||||
private IMethodRepository? _methodRepo;
|
private IMethodRepository? _methodRepo;
|
||||||
|
private ICancellationRepository? _cancellationRepo;
|
||||||
|
|
||||||
public void Inject<T>(T dependency)
|
public void Inject<T>(T dependency)
|
||||||
{
|
{
|
||||||
if (dependency is IMethodRepository methodRepo) _methodRepo = methodRepo;
|
if (dependency is IMethodRepository methodRepo) _methodRepo = methodRepo;
|
||||||
|
if (dependency is ICancellationRepository cancellationRepo) _cancellationRepo = cancellationRepo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository)
|
public ICommandExecution Execute(ICallRequest command, IContextRepository contextRepository,
|
||||||
|
IRepresentationModule representationModule)
|
||||||
{
|
{
|
||||||
|
if (_cancellationRepo is null)
|
||||||
|
throw new NullReferenceException("Method repository was not defined");
|
||||||
|
|
||||||
if (_methodRepo is null)
|
if (_methodRepo is null)
|
||||||
throw new NullReferenceException("Method repository was not defined");
|
throw new NullReferenceException("Method repository was not defined");
|
||||||
|
|
||||||
if (contextRepository is null)
|
if (contextRepository is null)
|
||||||
throw new NullReferenceException("Context repository was not defined");
|
throw new NullReferenceException("Context repository was not defined");
|
||||||
|
|
||||||
var currentCommand = _methodRepo.GetMethod(command.CommandId);
|
var currentCommand = _methodRepo.GetMethod(command.CommandId);
|
||||||
if (currentCommand == null)
|
if (currentCommand == null)
|
||||||
throw new Exception($"Command {command.CommandId} not found");
|
throw new Exception($"Command {command.CommandId} not found");
|
||||||
@@ -35,10 +41,10 @@ namespace mROA.Implementation.Backend
|
|||||||
|
|
||||||
if (currentCommand.ReturnType.BaseType == typeof(Task) &&
|
if (currentCommand.ReturnType.BaseType == typeof(Task) &&
|
||||||
currentCommand.ReturnType.GenericTypeArguments.Length == 1)
|
currentCommand.ReturnType.GenericTypeArguments.Length == 1)
|
||||||
return TypedExecuteAsync(currentCommand, context, parameter, command);
|
return TypedExecuteAsync(currentCommand, context, parameter, command, _cancellationRepo, representationModule);
|
||||||
|
|
||||||
if (currentCommand.ReturnType == typeof(Task))
|
if (currentCommand.ReturnType == typeof(Task))
|
||||||
return ExecuteAsync(currentCommand, context, parameter, command);
|
return ExecuteAsync(currentCommand, context, parameter, command, _cancellationRepo, representationModule);
|
||||||
|
|
||||||
return Execute(currentCommand, context, parameter, command);
|
return Execute(currentCommand, context, parameter, command);
|
||||||
}
|
}
|
||||||
@@ -48,8 +54,10 @@ namespace mROA.Implementation.Backend
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var finalResult = currentCommand.Invoke(context, parameter is null ? new object[0] : new[]
|
var finalResult = currentCommand.Invoke(context, parameter is null
|
||||||
{ parameter });
|
? new object[0]
|
||||||
|
: new[]
|
||||||
|
{ parameter });
|
||||||
return new TypedFinalCommandExecution
|
return new TypedFinalCommandExecution
|
||||||
{
|
{
|
||||||
CommandId = command.CommandId, Result = finalResult,
|
CommandId = command.CommandId, Result = finalResult,
|
||||||
@@ -68,20 +76,34 @@ namespace mROA.Implementation.Backend
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static ICommandExecution ExecuteAsync(MethodInfo currentCommand, object context, object? parameter,
|
private static ICommandExecution ExecuteAsync(MethodInfo currentCommand, object context, object? parameter,
|
||||||
ICallRequest command)
|
ICallRequest command, ICancellationRepository cancellationRepository, IRepresentationModule representationModule)
|
||||||
{
|
{
|
||||||
var tokenSource = new CancellationTokenSource();
|
var tokenSource = new CancellationTokenSource();
|
||||||
|
cancellationRepository.RegisterCancellation(command.Id, tokenSource);
|
||||||
var token = tokenSource.Token;
|
var token = tokenSource.Token;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = (Task)currentCommand.Invoke(context, parameter is null ? new object[] { token } : new[]
|
var result = (Task)currentCommand.Invoke(context, parameter is null
|
||||||
{ parameter, token })!;
|
? new object[] { token }
|
||||||
|
: new[]
|
||||||
|
{ parameter, token })!;
|
||||||
|
|
||||||
|
|
||||||
result.Wait(token);
|
result.ContinueWith(_ =>
|
||||||
|
{
|
||||||
|
var payload = new FinalCommandExecution
|
||||||
|
{
|
||||||
|
Id = command.Id,
|
||||||
|
CommandId = command.CommandId
|
||||||
|
};
|
||||||
|
representationModule.PostCallMessage(command.Id, MessageType.FinishedCommandExecution, payload);
|
||||||
|
}, token);
|
||||||
|
|
||||||
|
return new AsyncCommandExecution
|
||||||
return new FinalCommandExecution { CommandId = command.CommandId, Id = command.Id };
|
{
|
||||||
|
Id = command.Id, CommandId = command.CommandId
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -94,25 +116,36 @@ namespace mROA.Implementation.Backend
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static ICommandExecution TypedExecuteAsync(MethodInfo currentCommand, object context, object? parameter,
|
private static ICommandExecution TypedExecuteAsync(MethodInfo currentCommand, object context, object? parameter,
|
||||||
ICallRequest command)
|
ICallRequest command, ICancellationRepository cancellationRepository, IRepresentationModule representationModule)
|
||||||
{
|
{
|
||||||
var tokenSource = new CancellationTokenSource();
|
var tokenSource = new CancellationTokenSource();
|
||||||
|
cancellationRepository.RegisterCancellation(command.Id, tokenSource);
|
||||||
|
|
||||||
var token = tokenSource.Token;
|
var token = tokenSource.Token;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result =
|
var result =
|
||||||
(Task)currentCommand.Invoke(context, parameter is null ? new object[] { token } : new[]
|
(Task)currentCommand.Invoke(context, parameter is null
|
||||||
{ parameter, token })!;
|
? new object[] { token }
|
||||||
|
: new[]
|
||||||
|
{ parameter, token })!;
|
||||||
|
|
||||||
result.Wait(token);
|
result.ContinueWith(t =>
|
||||||
|
|
||||||
var finalResult = result.GetType().GetProperty("Result")?.GetValue(result);
|
|
||||||
return new TypedFinalCommandExecution
|
|
||||||
{
|
{
|
||||||
Id = command.Id,
|
var finalResult = t.GetType().GetProperty("Result")?.GetValue(t);
|
||||||
Result = finalResult,
|
var payload = new TypedFinalCommandExecution
|
||||||
CommandId = command.CommandId,
|
{
|
||||||
Type = finalResult?.GetType()
|
Id = command.Id,
|
||||||
|
Result = finalResult,
|
||||||
|
CommandId = command.CommandId,
|
||||||
|
Type = finalResult?.GetType()
|
||||||
|
};
|
||||||
|
representationModule.PostCallMessage(command.Id, MessageType.FinishedCommandExecution, payload);
|
||||||
|
}, token);
|
||||||
|
|
||||||
|
return new AsyncCommandExecution
|
||||||
|
{
|
||||||
|
Id = command.Id, CommandId = command.CommandId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using mROA.Abstract;
|
||||||
|
|
||||||
|
namespace mROA.Implementation
|
||||||
|
{
|
||||||
|
public class CancellationRepository : ICancellationRepository
|
||||||
|
{
|
||||||
|
private Dictionary<Guid, CancellationTokenSource> _cancellations = new();
|
||||||
|
public void RegisterCancellation(Guid id, CancellationTokenSource cts)
|
||||||
|
{
|
||||||
|
_cancellations.TryAdd(id, cts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CancellationTokenSource? GetCancellation(Guid id)
|
||||||
|
{
|
||||||
|
return _cancellations.GetValueOrDefault(id, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FreeCancelation(Guid id)
|
||||||
|
{
|
||||||
|
_cancellations.Remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Inject<T>(T dependency)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,4 +16,11 @@ namespace mROA.Implementation.CommandExecution
|
|||||||
return new RemoteException(Exception) { CallRequestId = Id };
|
return new RemoteException(Exception) { CallRequestId = Id };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class AsyncCommandExecution : ICommandExecution
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public int ClientId { get; set; }
|
||||||
|
public int CommandId { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ namespace mROA.Implementation.Frontend
|
|||||||
request.Parameter = _serializationToolkit.Cast(request.Parameter, parameterType);
|
request.Parameter = _serializationToolkit.Cast(request.Parameter, parameterType);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = _executeModule.Execute(request, _contextRepository);
|
var result = _executeModule.Execute(request, _contextRepository, _representationModule);
|
||||||
|
|
||||||
var resultType = result is FinalCommandExecution
|
var resultType = result is FinalCommandExecution
|
||||||
? MessageType.FinishedCommandExecution
|
? MessageType.FinishedCommandExecution
|
||||||
|
|||||||
Reference in New Issue
Block a user