Skip to content

Commit a690f8d

Browse files
authored
Add ReenterAfter override (#1915)
* Add ReenterAfter override that takes in an action with a Task with a result * Add a test for ReenterAfter with result
1 parent 18d3ffb commit a690f8d

File tree

4 files changed

+52
-0
lines changed

4 files changed

+52
-0
lines changed

src/Proto.Actor/Context/ActorContext.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,23 @@ public void ReenterAfter(Task target, Action<Task> action)
280280
ScheduleContinuation(target, cont);
281281
}
282282

283+
public void ReenterAfter<T>(Task<T> target, Action<Task<T>> action)
284+
{
285+
var msg = _messageOrEnvelope;
286+
287+
var cont = new Continuation(
288+
() =>
289+
{
290+
action(target);
291+
292+
return Task.CompletedTask;
293+
},
294+
msg,
295+
Actor);
296+
297+
ScheduleContinuation(target, cont);
298+
}
299+
283300
public void ReenterAfter(Task target, Func<Task, Task> action)
284301
{
285302
var msg = _messageOrEnvelope;

src/Proto.Actor/Context/ActorContextDecorator.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ public virtual void ReenterAfter<T>(Task<T> target, Func<Task<T>, Task> action)
6767

6868
public void ReenterAfter(Task target, Action<Task> action) => _context.ReenterAfter(target, action);
6969

70+
public void ReenterAfter<T>(Task<T> target, Action<Task<T>> action) => _context.ReenterAfter(target, action);
71+
7072
public void ReenterAfter(Task target, Func<Task, Task> action) => _context.ReenterAfter(target, action);
7173

7274
public CapturedContext Capture() => _context.Capture();

src/Proto.Actor/Context/IContext.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,16 @@ public interface IContext : ISenderContext, IReceiverContext, ISpawnerContext, I
111111
/// <param name="action">The continuation to call once the task is completed. The awaited task is passed in as a parameter.</param>
112112
void ReenterAfter(Task target, Action<Task> action);
113113

114+
/// <summary>
115+
/// Awaits the given target task and once completed, the given action is then completed within the actors concurrency
116+
/// constraint.
117+
/// The concept is called Reentrancy, where an actor can continue to process messages while also awaiting that some
118+
/// asynchronous operation completes.
119+
/// </summary>
120+
/// <param name="target">The Task to await</param>
121+
/// <param name="action">The continuation to call once the task is completed. The awaited task is passed in as a parameter.</param>
122+
void ReenterAfter<T>(Task<T> target, Action<Task<T>> action);
123+
114124
/// <summary>
115125
/// Awaits the given target task and once completed, the given action is then completed within the actors concurrency
116126
/// constraint.

tests/Proto.Actor.Tests/ReenterTests.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,29 @@ public async Task ReenterAfterCompletedTask()
6969
Assert.Equal("response", res);
7070
}
7171

72+
[Fact]
73+
public async Task ReenterTaskWithResult()
74+
{
75+
const int expectedResult = 2;
76+
77+
var props = Props.FromFunc(ctx =>
78+
{
79+
if (ctx.Message is "reenter")
80+
{
81+
var task = Task.FromResult(expectedResult);
82+
ctx.ReenterAfter(task, completedTask => { ctx.Respond(completedTask.Result); });
83+
}
84+
85+
return Task.CompletedTask;
86+
}
87+
);
88+
89+
var pid = Context.Spawn(props);
90+
91+
var res = await Context.RequestAsync<int>(pid, "reenter", TimeSpan.FromSeconds(5));
92+
Assert.Equal(expectedResult, res);
93+
}
94+
7295
[Fact]
7396
public async Task ReenterAfterTimerCancelledToken()
7497
{

0 commit comments

Comments
 (0)