Skip to content

Commit

Permalink
Only support .net 8, fixed actor struct reply bug
Browse files Browse the repository at this point in the history
  • Loading branch information
andresgutierrez committed Jul 31, 2024
1 parent 400197c commit 644a261
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 62 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,14 @@ jobs:
GIT_COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
steps:
- name: Check out repository code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Install .NET
uses: actions/setup-dotnet@v2
uses: actions/setup-dotnet@v3
with:
dotnet-version: |
8.0.x
7.0.x
6.0.x
- name: Install dotCover
run: dotnet tool install JetBrains.dotCover.GlobalTool -g
- name: Run Tests
Expand Down
2 changes: 1 addition & 1 deletion Nixie.Tests/Nixie.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
Expand Down
6 changes: 4 additions & 2 deletions Nixie/ActorMessageReply.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

using DotNext.Threading.Tasks;

namespace Nixie;

/// <summary>
Expand Down Expand Up @@ -26,15 +28,15 @@ public sealed record ActorMessageReply<TRequest, TResponse>
/// <summary>
/// Returns the task completion source of the reply
/// </summary>
public TaskCompletionSource<TResponse?> Promise { get; }
public ValueTaskCompletionSource<TResponse?> Promise { get; }

/// <summary>
/// Constructor
/// </summary>
/// <param name="request"></param>
/// <param name="sender"></param>
/// <param name="promise"></param>
public ActorMessageReply(TRequest request, IGenericActorRef? sender, TaskCompletionSource<TResponse?> promise)
public ActorMessageReply(TRequest request, IGenericActorRef? sender, ValueTaskCompletionSource<TResponse?> promise)
{
Request = request;
Sender = sender;
Expand Down
34 changes: 18 additions & 16 deletions Nixie/ActorRefReply.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

using DotNext.Threading.Tasks;

namespace Nixie;

/// <summary>
Expand Down Expand Up @@ -62,9 +64,9 @@ public void Send(TRequest message, ActorMessageReply<TRequest, TResponse>? paren
/// <returns></returns>
public async Task<TResponse?> Ask(TRequest message)
{
TaskCompletionSource<TResponse?> promise = runner.SendAndTryDeliver(message, null, null);
ValueTaskCompletionSource<TResponse?> promise = runner.SendAndTryDeliver(message, null, null);

return await promise.Task;
return await promise.CreateTask(TimeSpan.FromHours(1), default);
}

/// <summary>
Expand All @@ -79,18 +81,18 @@ public void Send(TRequest message, ActorMessageReply<TRequest, TResponse>? paren
{
using CancellationTokenSource timeoutCancellationTokenSource = new();

TaskCompletionSource<TResponse?> completionSource = runner.SendAndTryDeliver(message, null, null);
ValueTaskCompletionSource<TResponse?> completionSource = runner.SendAndTryDeliver(message, null, null);

Task<TResponse?> task = completionSource.Task;
Task<TResponse?> task = completionSource.CreateTask(TimeSpan.FromHours(1), default).AsTask();

Task completedTask = await Task.WhenAny(
task,
Task.Delay(timeout, timeoutCancellationTokenSource.Token)
);
task,
Task.Delay(timeout, timeoutCancellationTokenSource.Token)
);

if (completedTask == task)
{
timeoutCancellationTokenSource.Cancel();
await timeoutCancellationTokenSource.CancelAsync();
return await task;
}

Expand All @@ -105,9 +107,9 @@ public void Send(TRequest message, ActorMessageReply<TRequest, TResponse>? paren
/// <returns></returns>
public async Task<TResponse?> Ask(TRequest message, IGenericActorRef sender)
{
TaskCompletionSource<TResponse?> promise = runner.SendAndTryDeliver(message, sender, null);
ValueTaskCompletionSource<TResponse?> promise = runner.SendAndTryDeliver(message, sender, null);

return await promise.Task;
return await promise.CreateTask(TimeSpan.FromHours(1), default);
}

/// <summary>
Expand All @@ -123,18 +125,18 @@ public void Send(TRequest message, ActorMessageReply<TRequest, TResponse>? paren
{
using CancellationTokenSource timeoutCancellationTokenSource = new();

TaskCompletionSource<TResponse?> completionSource = runner.SendAndTryDeliver(message, sender, null);
ValueTaskCompletionSource<TResponse?> completionSource = runner.SendAndTryDeliver(message, sender, null);

Task<TResponse?> task = completionSource.Task;
Task<TResponse?> task = completionSource.CreateTask(TimeSpan.FromHours(1), default).AsTask();

Task completedTask = await Task.WhenAny(
task,
Task.Delay(timeout, timeoutCancellationTokenSource.Token)
);
task,
Task.Delay(timeout, timeoutCancellationTokenSource.Token)
);

if (completedTask == task)
{
timeoutCancellationTokenSource.Cancel();
await timeoutCancellationTokenSource.CancelAsync();
return await task;
}

Expand Down
24 changes: 13 additions & 11 deletions Nixie/ActorRefStructReply.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

using DotNext.Threading.Tasks;

namespace Nixie;

/// <summary>
Expand Down Expand Up @@ -62,9 +64,9 @@ public void Send(TRequest message, ActorMessageReply<TRequest, TResponse>? paren
/// <returns></returns>
public async Task<TResponse> Ask(TRequest message)
{
TaskCompletionSource<TResponse> promise = runner.SendAndTryDeliver(message, null, null);
ValueTaskCompletionSource<TResponse> promise = runner.SendAndTryDeliver(message, null, null);

return await promise.Task;
return await promise.CreateTask(TimeSpan.FromHours(1), default);
}

/// <summary>
Expand All @@ -79,18 +81,18 @@ public async Task<TResponse> Ask(TRequest message, TimeSpan timeout)
{
using CancellationTokenSource timeoutCancellationTokenSource = new();

TaskCompletionSource<TResponse> completionSource = runner.SendAndTryDeliver(message, null, null);

Task<TResponse> task = completionSource.Task;
ValueTaskCompletionSource<TResponse> completionSource = runner.SendAndTryDeliver(message, null, null);

Task<TResponse> task = completionSource.CreateTask(TimeSpan.FromHours(1), default).AsTask();

Task completedTask = await Task.WhenAny(
task,
Task.Delay(timeout, timeoutCancellationTokenSource.Token)
);

if (completedTask == task)
{
timeoutCancellationTokenSource.Cancel();
await timeoutCancellationTokenSource.CancelAsync();
return await task;
}

Expand All @@ -105,9 +107,9 @@ public async Task<TResponse> Ask(TRequest message, TimeSpan timeout)
/// <returns></returns>
public async Task<TResponse> Ask(TRequest message, IGenericActorRef sender)
{
TaskCompletionSource<TResponse> promise = runner.SendAndTryDeliver(message, sender, null);
ValueTaskCompletionSource<TResponse> promise = runner.SendAndTryDeliver(message, sender, null);

return await promise.Task;
return await promise.CreateTask(TimeSpan.FromHours(1), default);
}

/// <summary>
Expand All @@ -123,9 +125,9 @@ public async Task<TResponse> Ask(TRequest message, IGenericActorRef sender, Time
{
using CancellationTokenSource timeoutCancellationTokenSource = new();

TaskCompletionSource<TResponse> completionSource = runner.SendAndTryDeliver(message, sender, null);
ValueTaskCompletionSource<TResponse> completionSource = runner.SendAndTryDeliver(message, sender, null);

Task<TResponse> task = completionSource.Task;
Task<TResponse> task = completionSource.CreateTask(TimeSpan.Zero, default).AsTask();

Task completedTask = await Task.WhenAny(
task,
Expand All @@ -134,7 +136,7 @@ public async Task<TResponse> Ask(TRequest message, IGenericActorRef sender, Time

if (completedTask == task)
{
timeoutCancellationTokenSource.Cancel();
await timeoutCancellationTokenSource.CancelAsync();
return await task;
}

Expand Down
19 changes: 7 additions & 12 deletions Nixie/ActorRunnerReply.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

using System.Collections.Concurrent;
using DotNext.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Nixie.Utils;

namespace Nixie;

Expand Down Expand Up @@ -82,20 +82,15 @@ public ActorRunner(ActorSystem actorSystem, ILogger? logger, string name)
/// <param name="sender"></param>
/// <param name="parentReply"></param>
/// <returns></returns>
public TaskCompletionSource<TResponse?> SendAndTryDeliver(TRequest message, IGenericActorRef? sender, ActorMessageReply<TRequest, TResponse>? parentReply)
public ValueTaskCompletionSource<TResponse?> SendAndTryDeliver(TRequest message, IGenericActorRef? sender, ActorMessageReply<TRequest, TResponse>? parentReply)
{
ActorMessageReply<TRequest, TResponse> messageReply;
ValueTaskCompletionSource<TResponse?> promise = new(runContinuationsAsynchronously: true);

TaskCompletionSource<TResponse?> promise = new(TaskCreationOptions.RunContinuationsAsynchronously);

if (parentReply is not null)
messageReply = parentReply;
else
messageReply = new(message, sender, promise);
ActorMessageReply<TRequest, TResponse> messageReply = parentReply ?? new(message, sender, promise);

if (shutdown == 0)
{
promise.SetCanceled();
promise.TrySetCanceled(TimeSpan.MaxValue, default);
return promise;
}

Expand Down Expand Up @@ -181,11 +176,11 @@ private async Task DeliverMessages()
TResponse? response = await Actor.Receive(message.Request);

if (!ActorContext.ByPassReply)
message.Promise.SetResult(response);
message.Promise.TrySetResult(response);
}
catch (Exception ex)
{
message.Promise.SetResult(null);
message.Promise.TrySetResult(null);

logger?.LogError("[{Actor}] {Exception}: {Message}\n{StackTrace}", Name, ex.GetType().Name, ex.Message, ex.StackTrace);
}
Expand Down
20 changes: 8 additions & 12 deletions Nixie/ActorRunnerStructReply.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

using System.Collections.Concurrent;
using DotNext.Threading.Tasks;
using Microsoft.Extensions.Logging;

namespace Nixie;
Expand Down Expand Up @@ -81,20 +82,15 @@ public ActorRunnerStruct(ActorSystem actorSystem, ILogger? logger, string name)
/// <param name="sender"></param>
/// <param name="parentReply"></param>
/// <returns></returns>
public TaskCompletionSource<TResponse> SendAndTryDeliver(TRequest message, IGenericActorRef? sender, ActorMessageReply<TRequest, TResponse>? parentReply)
public ValueTaskCompletionSource<TResponse> SendAndTryDeliver(TRequest message, IGenericActorRef? sender, ActorMessageReply<TRequest, TResponse>? parentReply)
{
ActorMessageReply<TRequest, TResponse> messageReply;
ValueTaskCompletionSource<TResponse> promise = new(runContinuationsAsynchronously: true);

TaskCompletionSource<TResponse> promise = new(TaskCreationOptions.RunContinuationsAsynchronously);

if (parentReply is not null)
messageReply = parentReply;
else
messageReply = new(message, sender, promise);
ActorMessageReply<TRequest, TResponse> messageReply = parentReply ?? new(message, sender, promise);

if (shutdown == 0)
{
promise.SetCanceled();
promise.TrySetCanceled(TimeSpan.MaxValue, default);
return promise;
}

Expand Down Expand Up @@ -177,14 +173,14 @@ private async Task DeliverMessages()

try
{
TResponse? response = await Actor.Receive(message.Request);
TResponse response = await Actor.Receive(message.Request);

if (!ActorContext.ByPassReply)
message.Promise.SetResult(default);
message.Promise.TrySetResult(response);
}
catch (Exception ex)
{
message.Promise.SetResult(default);
message.Promise.TrySetResult(default);

logger?.LogError("[{Actor}] {Exception}: {Message}\n{StackTrace}", Name, ex.GetType().Name, ex.Message, ex.StackTrace);
}
Expand Down
5 changes: 3 additions & 2 deletions Nixie/Nixie.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>true</IsPackable>
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PackageId>Nixie</PackageId>
<Version>1.0.6</Version>
<Version>1.0.7</Version>
<Description>A Lightweight Actor Model Implementation for C#/.NET</Description>
<Authors>Andres Gutierrez</Authors>
<Company>Andres Gutierrez</Company>
Expand Down Expand Up @@ -39,5 +39,6 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="DotNext.Threading" Version="5.10.0" />
</ItemGroup>
</Project>
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ To install Nixie into your C#/.NET project, you can use the .NET CLI or the NuGe
#### Using .NET CLI

```shell
dotnet add package Nixie --version 1.0.6
dotnet add package Nixie --version 1.0.7
```

### Using NuGet Package Manager

Search for Nixie and install it from the NuGet package manager UI, or use the Package Manager Console:

```shell
Install-Package Nixie -Version 1.0.6
Install-Package Nixie -Version 1.0.7
```

## Usage
Expand Down

0 comments on commit 644a261

Please sign in to comment.