-
-
Notifications
You must be signed in to change notification settings - Fork 295
Expand file tree
/
Copy pathProgram.cs
More file actions
146 lines (120 loc) · 3.98 KB
/
Program.cs
File metadata and controls
146 lines (120 loc) · 3.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// -----------------------------------------------------------------------
// <copyright file="Program.cs" company="Asynkron AB">
// Copyright (C) 2015-2024 Asynkron AB All rights reserved
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Proto;
internal class Program
{
private static async Task Main()
{
var context = new RootContext(new ActorSystem());
Log.SetLoggerFactory(LoggerFactory.Create(b => b.AddConsole().SetMinimumLevel(LogLevel.Debug)));
var props = Props.FromProducer(() => new ParentActor())
.WithChildSupervisorStrategy(new OneForOneStrategy(Decider.Decide, 1, null));
var actor = context.Spawn(props);
context.Send(
actor, new Hello
{
Who = "Alex"
}
);
context.Send(actor, new Recoverable());
context.Send(actor, new Fatal());
//why wait?
//Stop is a system message and is not processed through the user message mailbox
//thus, it will be handled _before_ any user message
//we only do this to show the correct order of events in the console
await Task.Delay(TimeSpan.FromSeconds(1));
context.Stop(actor);
Console.ReadLine();
}
private static class Decider
{
public static SupervisorDirective Decide(PID pid, Exception reason) =>
reason switch
{
RecoverableException _ => SupervisorDirective.Restart,
FatalException _ => SupervisorDirective.Stop,
_ => SupervisorDirective.Escalate
};
}
private class ParentActor : IActor
{
public Task ReceiveAsync(IContext context)
{
PID child;
if (context.Children is null || context.Children.Count == 0)
{
var props = Props.FromProducer(() => new ChildActor());
child = context.Spawn(props);
}
else
{
child = context.Children.First();
}
switch (context.Message)
{
case Hello _:
case Recoverable _:
case Fatal _:
context.Forward(child);
break;
case Terminated r:
Console.WriteLine("Watched actor was Terminated, {0}", r.Who);
break;
}
return Task.CompletedTask;
}
}
private class ChildActor : IActor
{
private readonly ILogger _logger = Log.CreateLogger<ChildActor>();
public Task ReceiveAsync(IContext context)
{
switch (context.Message)
{
case Hello r:
_logger.LogDebug($"Hello {r.Who}");
break;
case Recoverable _:
throw new RecoverableException();
case Fatal _:
throw new FatalException();
case Started _:
_logger.LogDebug("Started, initialize actor here");
break;
case Stopping _:
_logger.LogDebug("Stopping, actor is about shut down");
break;
case Stopped _:
_logger.LogDebug("Stopped, actor and it's children are stopped");
break;
case Restarting _:
_logger.LogDebug("Restarting, actor is about restart");
break;
}
return Task.CompletedTask;
}
}
private class Hello
{
public string Who;
}
private class RecoverableException : Exception
{
}
private class FatalException : Exception
{
}
private class Fatal
{
}
private class Recoverable
{
}
}