Supervision,The literal meaning of supervision is that the parent actor discovers that there is an exception to the child actor, the child actor production policy processing mechanism, if the parent actor does not process, then pass up.
The strategies for post processing of sub Actor exception are:
Resume:Immediate recovery
Restart:Stop Actor before resuming and recreate it.
Stop:Stop it
Escalate:Reporting to parent level
SupervisorImplemented by Props. WithChildSupervisor Starategy (), the first parameter of this method is to receive the exception and the Actor’s PID to handle the exception in a certain way, the second parameter is the number of restarts, and the third parameter is twoThe interval between two consecutive reboots (according to official documents, two consecutive reboots are longer than the interval, the number of reboots is reset, but the interval does not work) reaches the maximum number of data, and the child actor is regenerated.
Code friend see code:
1 using Proto; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Threading.Tasks; 6 7 namespace P006_Supervision 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //Set up monitoring policy, point to SupervisiorMode method, restart number 3, two interval 1s 14 var props = Actor.FromProducer(() => new ShopingCatActor()).WithChildSupervisorStrategy(new OneForOneStrategy(SupervisorMode.Decide, 3, TimeSpan.FromSeconds(1))); 15 var pid = Actor.Spawn(props); 16 var user = new User { UserName = "gsw" }; 17 18 var sn = 1; 19 while (true) 20 { 21 Console.WriteLine($"{sn++}--------------------begin-----------------"); 22 foreach (var goods in user.ShopingCat.Goodses) 23 { 24 Console.WriteLine(goods); 25 } 26 Console.WriteLine("---------------------end------------------"); 27 Console.ReadLine(); 28 pid.Request(user, pid); 29 } 30 } 31 } 32 /// <summary> 33 /// Supervisor Pattern 34 /// </summary> 35 class SupervisorMode 36 { 37 /// <summary> 38 /// Follow up operations to handle exceptions 39 /// </summary> 40 /// <param name="pid">PID</param> 41 /// <param name="reason">Exception reason, Exception type</param> 42 /// <returns></returns> 43 public static SupervisorDirective Decide(PID pid, Exception reason) 44 { 45 Console.WriteLine(" Abnormality occurs:" + reason.Message + " " + pid); 46 switch (reason) 47 { 48 //Abnormality started again 49 case RecoverableException _: 50 return SupervisorDirective.Restart; 51 //Stop abnormality 52 case FatalException _: 53 return SupervisorDirective.Stop; 54 //Others are reported. 55 default: 56 return SupervisorDirective.Escalate; 57 } 58 } 59 } 60 /// <summary> 61 /// Shopping cart actor 62 /// </summary> 63 class ShopingCatActor : IActor 64 { 65 ShopingCat _shopingCat; 66 public ShopingCatActor() 67 { 68 _shopingCat = new ShopingCat(); 69 Console.WriteLine("*******************actor ShopingCatActor************************"); 70 } 71 public Task ReceiveAsync(IContext context) 72 { 73 PID childPid; 74 if (context.Children == null || context.Children.Count == 0) 75 { 76 var props = Actor.FromProducer(() => new GoodsActor()); 77 childPid = context.Spawn(props); 78 } 79 else 80 { 81 childPid = context.Children.First(); 82 } 83 switch (context.Message) 84 { 85 case User user: 86 childPid.Request(_shopingCat, childPid); 87 user.ShopingCat = _shopingCat; 88 break; 89 } 90 return Actor.Done; 91 } 92 } 93 /// <summary> 94 /// Commodity actor 95 /// </summary> 96 class GoodsActor : IActor 97 { 98 public Task ReceiveAsync(IContext context) 99 { 100 switch (context.Message) 101 { 102 case ShopingCat shopingCat: 103 104 var goods = new Goods { Name = "Black tea", Price = 3.0m, Describe = "Unified" }; 105 //Used to generate random anomalies. 106 var random = new Random(); 107 goods.Quantity = random.Next(1, 3) - 1; 108 if (goods.Quantity <= 0) 109 { 110 throw new RecoverableException("The quantity should not be less than or equal to 0."); 111 } 112 else 113 { 114 shopingCat.Goodses.Add(goods); 115 Console.WriteLine($"Add {goods} to shopping cart"); 116 } 117 break; 118 } 119 return Actor.Done; 120 } 121 } 122 /// <summary> 123 /// user124 /// </summary> 125 class User 126 { 127 public ShopingCat ShopingCat { get; set; } = new ShopingCat(); 128 public string UserName { get; set; } 129 } 130 /// <summary> 131 /// Shopping Cart132 /// </summary> 133 class ShopingCat 134 { 135 public List<Goods> Goodses 136 { get; set; } = new List<Goods>(); 137 } 138 /// <summary> 139 /// commodity140 /// </summary> 141 class Goods 142 { 143 public string Name { get; set; } 144 145 public int Quantity { get; set; } 146 147 public decimal Price { get; set; } 148 149 public string Describe { get; set; } 150 public override string ToString() 151 { 152 return $"Name={Name},Quantity={Quantity},Price={Price},Describe={Describe}"; 153 } 154 } 155 156 }
DemoThere are three entity classes, user classes, shopping cart classes, commodity classes, their relationship at a glance to understand, aggregate relationships. There are two Actors, Shoping Cat Actor, Goods Actor, and Goods Actor.The vehicle Actor sub Actor; ShopingCatActor under the supervision strategy, in the
SupervisorModeIn the next Decide method, we handle different exceptions and adopt different Actor strategies. In GoodsActor, when adding goods, the number is determined according to the number of anomalies.
Look at the results:
Note that ID $1 /$2 is generated after four exceptions (this is different from the documented statement, maybe I understand the problem, restart three times, not three times)