Skip to content

Commit

Permalink
Added missing ScheduleOnceStruct/GracefulShutdownStruct flavors
Browse files Browse the repository at this point in the history
  • Loading branch information
andresgutierrez committed Jul 26, 2024
1 parent ddd505e commit 34fd124
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 6 deletions.
21 changes: 21 additions & 0 deletions Nixie/ActorRepositoryStruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,4 +239,25 @@ public async Task<bool> GracefulShutdown(string name, TimeSpan maxWait)

return true;
}

/// <summary>
/// Tries to shutdown an actor by its name and returns a task whose result confirms shutdown within the specified timespan
/// </summary>
/// <param name="actorRef"></param>
/// <param name="maxWait"></param>
/// <returns></returns>
public async Task<bool> GracefulShutdown(IActorRefStruct<TActor, TRequest> actorRef, TimeSpan maxWait)
{
string name = actorRef.Runner.Name;

if (actors.TryGetValue(name, out Lazy<(ActorRunnerStruct<TActor, TRequest> runner, ActorRefStruct<TActor, TRequest> actorRef)>? actor))
{
bool success = await actor.Value.runner.GracefulShutdown(maxWait);
actors.TryRemove(name, out _);
actorSystem.StopAllTimers(actor.Value.actorRef);
return success;
}

return true;
}
}
49 changes: 49 additions & 0 deletions Nixie/ActorScheduler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,43 @@ public Timer ScheduleOnce<TActor, TRequest>(IActorRef<TActor, TRequest> actorRef
return timer.Value;
}

/// <summary>
/// Schedules a message to be sent to an actor once after a specified delay.
/// </summary>
/// <typeparam name="TActor"></typeparam>
/// <typeparam name="TRequest"></typeparam>
/// <typeparam name="TResponse"></typeparam>
/// <param name="actorRef"></param>
/// <param name="request"></param>
/// <param name="delay"></param>
/// <returns></returns>
public Timer ScheduleOnceStruct<TActor, TRequest, TResponse>(IActorRefStruct<TActor, TRequest, TResponse> actorRef, TRequest request, TimeSpan delay)
where TActor : IActorStruct<TRequest, TResponse> where TRequest : struct where TResponse : struct
{
long seq = Interlocked.Increment(ref sequence);
Lazy<ConcurrentDictionary<long, Lazy<Timer>>> timers = onceTimers.GetOrAdd(actorRef, (object _) => new());
Lazy<Timer> timer = timers.Value.GetOrAdd(seq, (long key) => new(() => ScheduleOnceTimerStruct(actorRef, request, delay, seq)));
return timer.Value;
}

/// <summary>
/// Schedules a message to be sent to an actor once after a specified delay.
/// </summary>
/// <typeparam name="TActor"></typeparam>
/// <typeparam name="TRequest"></typeparam>
/// <param name="actorRef"></param>
/// <param name="request"></param>
/// <param name="delay"></param>
/// <returns></returns>
public Timer ScheduleOnceStruct<TActor, TRequest>(IActorRefStruct<TActor, TRequest> actorRef, TRequest request, TimeSpan delay)
where TActor : IActorStruct<TRequest> where TRequest : struct
{
long seq = Interlocked.Increment(ref sequence);
Lazy<ConcurrentDictionary<long, Lazy<Timer>>> timers = onceTimers.GetOrAdd(actorRef, (object _) => new());
Lazy<Timer> timer = timers.Value.GetOrAdd(seq, (long key) => new(() => ScheduleOnceTimerStruct(actorRef, request, delay, seq)));
return timer.Value;
}

/// <summary>
/// Stops a periodic timer
/// </summary>
Expand Down Expand Up @@ -275,6 +312,18 @@ private Timer ScheduleOnceTimer<TActor, TRequest, TResponse>(IActorRef<TActor, T
return new((state) => SendScheduledMessage(actorRef, request, random), null, delay, TimeSpan.Zero);
}

private Timer ScheduleOnceTimerStruct<TActor, TRequest>(IActorRefStruct<TActor, TRequest> actorRef, TRequest request, TimeSpan delay, long random)
where TActor : IActorStruct<TRequest> where TRequest : struct
{
return new((state) => SendScheduledMessage(actorRef, request, random), null, delay, TimeSpan.Zero);
}

private Timer ScheduleOnceTimerStruct<TActor, TRequest, TResponse>(IActorRefStruct<TActor, TRequest, TResponse> actorRef, TRequest request, TimeSpan delay, long random)
where TActor : IActorStruct<TRequest, TResponse> where TRequest : struct where TResponse : struct
{
return new((state) => SendScheduledMessage(actorRef, request, random), null, delay, TimeSpan.Zero);
}

private void SendScheduledMessage<TActor, TRequest>(IActorRef<TActor, TRequest> actorRef, TRequest request, long random)
where TActor : IActor<TRequest> where TRequest : class
{
Expand Down
52 changes: 49 additions & 3 deletions Nixie/ActorSystem.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@

using Microsoft.Extensions.Logging;
using Nixie.Actors;
using Nixie.Utils;
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
using System.Diagnostics;

namespace Nixie;

Expand Down Expand Up @@ -351,7 +350,7 @@ public async Task<bool> GracefulShutdownStruct<TActor, TRequest>(string name, Ti
/// <typeparam name="TActor"></typeparam>
/// <typeparam name="TRequest"></typeparam>
/// <typeparam name="TResponse"></typeparam>
/// <param name="name"></param>
/// <param name="actorRef"></param>
/// <param name="maxWait"></param>
/// <returns></returns>
public async Task<bool> GracefulShutdownStruct<TActor, TRequest, TResponse>(IActorRefStruct<TActor, TRequest, TResponse> actorRef, TimeSpan maxWait)
Expand All @@ -362,6 +361,22 @@ public async Task<bool> GracefulShutdownStruct<TActor, TRequest, TResponse>(IAct
return await repository.GracefulShutdown(actorRef, maxWait);
}

/// <summary>
/// Shutdowns an actor by its reference
/// </summary>
/// <typeparam name="TActor"></typeparam>
/// <typeparam name="TRequest"></typeparam>
/// <param name="actorRef"></param>
/// <param name="maxWait"></param>
/// <returns></returns>
public async Task<bool> GracefulShutdownStruct<TActor, TRequest>(IActorRefStruct<TActor, TRequest> actorRef, TimeSpan maxWait)
where TActor : IActorStruct<TRequest> where TRequest : struct
{
ActorRepositoryStruct<TActor, TRequest> repository = GetRepositoryStruct<TActor, TRequest>();

return await repository.GracefulShutdown(actorRef, maxWait);
}

/// <summary>
/// Returns the repository where the current references to request/response actors are stored.
/// </summary>
Expand Down Expand Up @@ -569,6 +584,37 @@ public void ScheduleOnce<TActor, TRequest>(IActorRef<TActor, TRequest> actorRef,
scheduler.ScheduleOnce(actorRef, request, delay);
}

/// <summary>
/// Schedules a message to be sent to an actor once after a specified delay.
/// </summary>
/// <typeparam name="TActor"></typeparam>
/// <typeparam name="TRequest"></typeparam>
/// <typeparam name="TResponse"></typeparam>
/// <param name="actorRef"></param>
/// <param name="request"></param>
/// <param name="delay"></param>
/// <returns></returns>
public void ScheduleOnceStruct<TActor, TRequest, TResponse>(IActorRefStruct<TActor, TRequest, TResponse> actorRef, TRequest request, TimeSpan delay)
where TActor : IActorStruct<TRequest, TResponse> where TRequest : struct where TResponse : struct
{
scheduler.ScheduleOnceStruct(actorRef, request, delay);
}

/// <summary>
/// Schedules a message to be sent to an actor once after a specified delay.
/// </summary>
/// <typeparam name="TActor"></typeparam>
/// <typeparam name="TRequest"></typeparam>
/// <param name="actorRef"></param>
/// <param name="request"></param>
/// <param name="delay"></param>
/// <returns></returns>
public void ScheduleOnceStruct<TActor, TRequest>(IActorRefStruct<TActor, TRequest> actorRef, TRequest request, TimeSpan delay)
where TActor : IActorStruct<TRequest> where TRequest : struct
{
scheduler.ScheduleOnceStruct(actorRef, request, delay);
}

/// <summary>
/// Stops a periodic timer
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion Nixie/Nixie.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PackageId>Nixie</PackageId>
<Version>1.0.2</Version>
<Version>1.0.3</Version>
<Description>A Lightweight Actor Model Implementation for C#/.NET</Description>
<Authors>Andres Gutierrez</Authors>
<Company>Andres Gutierrez</Company>
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,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.2
dotnet add package Nixie --version 1.0.3
```

### 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.2
Install-Package Nixie -Version 1.0.3
```

## Usage
Expand Down

0 comments on commit 34fd124

Please sign in to comment.