public void OneForOneStrategy_WhenRestartedLessThanMaximumAllowedRetriesWithinSpecifiedTimePeriod_ShouldNotStopChild() { var childMailboxStats = new TestMailboxStatistics(msg => msg is Stopped); var strategy = new OneForOneStrategy((pid, reason) => SupervisorDirective.Restart, 3, TimeSpan.FromMilliseconds(100)); var childProps = Props.FromProducer(() => new ChildActor()) .WithMailbox(() => UnboundedMailbox.Create(childMailboxStats)); var parentProps = Props.FromProducer(() => new ParentActor(childProps)) .WithChildSupervisorStrategy(strategy); var parent = Context.Spawn(parentProps); Context.Send(parent, "1st restart"); Context.Send(parent, "2nd restart"); Context.Send(parent, "3rd restart"); // wait more than the time period Thread.Sleep(500); Assert.DoesNotContain(Stop.Instance, childMailboxStats.Posted); Assert.DoesNotContain(Stop.Instance, childMailboxStats.Received); Context.Send(parent, "4th restart"); childMailboxStats.Reset.Wait(500); Assert.DoesNotContain(Stop.Instance, childMailboxStats.Posted); Assert.DoesNotContain(Stop.Instance, childMailboxStats.Received); }
public async Task GivenNonCompletedSystemMessageTaskThrewException_ShouldEscalateFailure() { var mailboxHandler = new TestMailboxHandler(); var mailbox = UnboundedMailbox.Create(); mailbox.RegisterHandlers(mailboxHandler, mailboxHandler); var msg1 = new TestMessageWithTaskCompletionSource(); mailbox.PostSystemMessage(msg1); //make sure the message is being processed by the mailboxHandler //e.g. await mailboxHandler.GotMessage() await Task.Delay(10); //fail the current task being processed var taskException = new Exception(); msg1.TaskCompletionSource.SetException(taskException); await mailboxHandler.HasFailures; Assert.Single(mailboxHandler.EscalatedFailures); var e = Assert.IsType <Exception>(mailboxHandler.EscalatedFailures[0]); Assert.Equal(taskException, e); }
public void OneForOneStrategy_WhenEscalateDirectiveWithoutGrandparent_ShouldRevertToDefaultDirective() { var parentMailboxStats = new TestMailboxStatistics(msg => msg is Stopped); var strategy = new OneForOneStrategy((pid, reason) => SupervisorDirective.Escalate, 1, null); var childProps = Props.FromProducer(() => new ThrowOnStartedChildActor()); var parentProps = Props.FromProducer(() => new ParentActor(childProps)) .WithChildSupervisorStrategy(strategy) .WithMailbox(() => UnboundedMailbox.Create(parentMailboxStats)); var parent = Context.Spawn(parentProps); Context.Send(parent, "hello"); parentMailboxStats.Reset.Wait(1000); // Default directive allows 10 restarts so we expect 11 Failure messages before the child is stopped Assert.Equal(11, parentMailboxStats.Received.OfType <Failure>().Count()); var failures = parentMailboxStats.Received.OfType <Failure>(); // subsequent failures are wrapped in AggregateException foreach (var failure in failures) { if (failure.Reason is AggregateException ae) { Assert.IsType <Exception>(ae.InnerException); } else { Assert.IsType <Exception>(failure.Reason); } } }
public static void Main(string[] args) { Func <IMailbox> unboundedMailbox = () => UnboundedMailbox.Create(); RunTest(unboundedMailbox, "Unbounded mailbox"); Console.ReadLine(); }
private static void HookedActor() { // The Props are used to configure and construct the Actor and it's Context. Props props = new Props() // the producer is a delegate that returns a new instance of an IActor .WithProducer(() => new HelloActor()) // the default dispatcher uses the thread pool and limits throughput to 300 messages per mailbox run .WithDispatcher(new ThreadPoolDispatcher { Throughput = 300 }) // the default mailbox uses unbounded queues .WithMailbox(() => UnboundedMailbox.Create()) // the default strategy restarts child actors a maximum of 10 times within a 10 second window .WithChildSupervisorStrategy(new OneForOneStrategy((who, reason) => SupervisorDirective.Restart, 10, TimeSpan.FromSeconds(10))) // middlewares can be chained to intercept incoming and outgoing messages // receive middlewares are invoked before the actor receives the message // sender middlewares are invoked before the message is sent to the target PID .WithReceiveMiddleware( next => async c => { Console.WriteLine($"RECEIVING {c.Message.GetType()}:{c.Message}"); await next(c); Console.WriteLine($"RECEIVED"); }, next => async c => { Console.WriteLine($"GETTING {c.Message.GetType()}:{c.Message}"); await next(c); Console.WriteLine($"GOTTEN"); }) .WithSenderMiddleware( next => async(c, target, envelope) => { Console.WriteLine($"SENDING {c.Message.GetType()}:{c.Message}"); await next(c, target, envelope); Console.WriteLine($"SENT {c.Message.GetType()}:{c.Message}"); }, next => async(c, target, envelope) => { Console.WriteLine($"POSTING {c.Message.GetType()}:{c.Message}"); await next(c, target, envelope); Console.WriteLine($"POSTED {c.Message.GetType()}:{c.Message}"); }) // the default spawner constructs the Actor, Context and Process .WithSpawner(Props.DefaultSpawner); PID pid = Actor.Spawn(props); // create actor according to the properties definition pid.Tell(new Hello { Who = "Bnaya" }); pid.Tell(new Hello { Who = "Bnaya" }); }
static void Main(string[] args) { var props = new Props() //用道具代理返回一个IActor实例 .WithProducer(() => new MyActor()) //默认调度器用线程池,邮箱中最多300个消息吞吐量 .WithDispatcher(new ThreadPoolDispatcher { Throughput = 300 }) //默认邮箱使用无界队列 .WithMailbox(() => UnboundedMailbox.Create()) //默认策略在10秒的窗口内最多重新启动子Actor 10次 .WithChildSupervisorStrategy(new OneForOneStrategy((who, reason) => SupervisorDirective.Restart, 10, TimeSpan.FromSeconds(10))) //可以将中间件链接起来以拦截传入和传出消息 //接收中间件在Actor接收消息之前被调用 //发送者中间件在消息发送到目标PID之前被调用 .WithReceiveMiddleware( next => async c => { Console.WriteLine($"Receive中间件 1 开始,{c.Message.GetType()}:{c.Message}"); await next(c); Console.WriteLine($"Receive中间件 1 结束,{c.Message.GetType()}:{c.Message}"); }, next => async c => { Console.WriteLine($"Receive中间件 2 开始,{c.Message.GetType()}:{c.Message}"); await next(c); Console.WriteLine($"Receive中间件 2 结束,{c.Message.GetType()}:{c.Message}"); }) .WithSenderMiddleware( next => async(c, target, envelope) => { Console.WriteLine($"Sender中间件 1 开始, {c.Message.GetType()}:{c.Message}"); await next(c, target, envelope); Console.WriteLine($"Sender中间件 1 结束,{c.Message.GetType()}:{c.Message}"); }, next => async(c, target, envelope) => { Console.WriteLine($"Sender中间件 2 开始,{c.Message.GetType()}:{c.Message}"); await next(c, target, envelope); Console.WriteLine($"Sender中间件 2 结束,{c.Message.GetType()}:{c.Message}"); }) // 默认的 spawner 构造 Actor, Context 和 Process .WithSpawner(Props.DefaultSpawner); //从props衍生pid,pid代理一个actor的地址 var pid = Actor.Spawn(props); //把Hello对象交给HelloActor处理 pid.Tell(new MyEntity { Message = "我是MyEntity的Message,请求" }); Console.ReadLine(); }
static void Main(string[] args) { Func <IMailbox> unboundedMailbox = () => UnboundedMailbox.Create(); //Func<IMailbox> boundedMailbox = // () => BoundedMailbox.Create(1024 * 1024); //RunTest(boundedMailbox, "Bounded mailbox"); RunTest(unboundedMailbox, "Unbounded mailbox"); Console.ReadLine(); }
static void Main(string[] args) { var props = new Props() // the producer is a delegate that returns a new instance of an IActor .WithProducer(() => new MyActor()) // the default dispatcher uses the thread pool and limits throughput to 300 messages per mailbox run .WithDispatcher(new ThreadPoolDispatcher { Throughput = 300 }) // the default mailbox uses unbounded queues .WithMailbox(() => UnboundedMailbox.Create(new MyMailboxStatistics())) // the default strategy restarts child actors a maximum of 10 times within a 10 second window .WithChildSupervisorStrategy(new OneForOneStrategy((who, reason) => SupervisorDirective.Restart, 10, TimeSpan.FromSeconds(10))) // middlewares can be chained to intercept incoming and outgoing messages // receive middlewares are invoked before the actor receives the message // sender middlewares are invoked before the message is sent to the target PID .WithReceiveMiddleware( next => async c => { Console.WriteLine($"Receive middleware 1 enter {c.Message.GetType()}:{c.Message}"); await next(c); Console.WriteLine($"Receive middleware 1 exit"); }, next => async c => { Console.WriteLine($"Receive middleware 2 enter {c.Message.GetType()}:{c.Message}"); await next(c); Console.WriteLine($"Receive middleware 2 exit"); }) .WithSenderMiddleware( next => async(c, target, envelope) => { Console.WriteLine($"Sender middleware 1 enter {c.Message.GetType()}:{c.Message}"); await next(c, target, envelope); Console.WriteLine($"Sender middleware 1 enter {c.Message.GetType()}:{c.Message}"); }, next => async(c, target, envelope) => { Console.WriteLine($"Sender middleware 2 enter {c.Message.GetType()}:{c.Message}"); await next(c, target, envelope); Console.WriteLine($"Sender middleware 2 enter {c.Message.GetType()}:{c.Message}"); }) // the default spawner constructs the Actor, Context and Process .WithSpawner(Props.DefaultSpawner); var pid = Actor.Spawn(props); pid.Tell(new Hello { Who = "孙菲菲" }); Console.ReadLine(); }
public void OneForOneStrategy_Should_StopChildOnFailureWhenStarted() { var childMailboxStats = new TestMailboxStatistics(msg => msg is Stopped); var strategy = new OneForOneStrategy((pid, reason) => SupervisorDirective.Stop, 1, null); var childProps = Props.FromProducer(() => new ThrowOnStartedChildActor()) .WithMailbox(() => UnboundedMailbox.Create(childMailboxStats)); var parentProps = Props.FromProducer(() => new ParentActor(childProps)) .WithChildSupervisorStrategy(strategy); var parent = Context.Spawn(parentProps); childMailboxStats.Reset.Wait(1000); Assert.Contains(Stop.Instance, childMailboxStats.Posted); Assert.Contains(Stop.Instance, childMailboxStats.Received); }
public void OneForOneStrategy_Should_PassExceptionOnRestart() { var childMailboxStats = new TestMailboxStatistics(msg => msg is Stopped); var strategy = new OneForOneStrategy((pid, reason) => SupervisorDirective.Restart, 1, null); var childProps = Props.FromProducer(() => new ChildActor()) .WithMailbox(() => UnboundedMailbox.Create(childMailboxStats)); var parentProps = Props.FromProducer(() => new ParentActor(childProps)) .WithChildSupervisorStrategy(strategy); var parent = Context.Spawn(parentProps); Context.Send(parent, "hello"); childMailboxStats.Reset.Wait(1000); Assert.Contains(childMailboxStats.Posted, msg => (msg is Restart r) && r.Reason == Exception); Assert.Contains(childMailboxStats.Received, msg => (msg is Restart r) && r.Reason == Exception); }
public void OneForOneStrategy_Should_RestartParentOnEscalateFailure() { var parentMailboxStats = new TestMailboxStatistics(msg => msg is Restart); var strategy = new OneForOneStrategy((pid, reason) => SupervisorDirective.Escalate, 0, null); var childProps = Props.FromProducer(() => new ThrowOnStartedChildActor()); var parentProps = Props.FromProducer(() => new ParentActor(childProps)) .WithChildSupervisorStrategy(strategy) .WithMailbox(() => UnboundedMailbox.Create(parentMailboxStats)); var grandParentProps = Props.FromProducer(() => new ParentActor(parentProps)) .WithChildSupervisorStrategy(new OneForOneStrategy((pid, reason) => SupervisorDirective.Restart, 1, TimeSpan.FromSeconds(1))); var grandParent = Context.Spawn(grandParentProps); parentMailboxStats.Reset.Wait(1000); Thread.Sleep(1000); //parentMailboxStats.Received could still be modified without a wait here Assert.Contains(parentMailboxStats.Received, msg => msg is Restart); }
public void OneForOneStrategy_Should_RestartChildOnFailure() { var childMailboxStats = new TestMailboxStatistics(msg => msg is Stopped); var strategy = new OneForOneStrategy((pid, reason) => SupervisorDirective.Restart, 1, null); var childProps = Actor.FromProducer(() => new ChildActor()) .WithMailbox(() => UnboundedMailbox.Create(childMailboxStats)); var parentProps = Actor.FromProducer(() => new ParentActor(childProps)) .WithSupervisor(strategy); var parent = Actor.Spawn(parentProps); parent.Tell("hello"); childMailboxStats.Reset.Wait(1000); Assert.Contains(Restart.Instance, childMailboxStats.Posted); Assert.Contains(Restart.Instance, childMailboxStats.Received); }
public async Task GivenCompletedSystemMessageTaskGotCancelled_ShouldEscalateFailure() { var mailboxHandler = new TestMailboxHandler(); var mailbox = UnboundedMailbox.Create(); mailbox.RegisterHandlers(mailboxHandler, mailboxHandler); var msg1 = new TestMessageWithTaskCompletionSource(); msg1.TaskCompletionSource.SetCanceled(); mailbox.PostSystemMessage(msg1); await mailboxHandler.HasFailures; Assert.Single(mailboxHandler.EscalatedFailures); Assert.IsType <TaskCanceledException>(mailboxHandler.EscalatedFailures[0]); }
public void WhenActorResumed_DisposeIsNotCalled() { var childMailboxStats = new TestMailboxStatistics(msg => msg is Stopped); var disposeCalled = false; var strategy = new OneForOneStrategy((pid, reason) => SupervisorDirective.Resume, 0, null); var childProps = Actor.FromProducer(() => new DisposableActor(() => disposeCalled = true)) .WithMailbox(() => UnboundedMailbox.Create(childMailboxStats)) .WithChildSupervisorStrategy(strategy); var props = Actor.FromProducer(() => new SupervisingActor(childProps)) .WithMailbox(() => new TestMailbox()) .WithChildSupervisorStrategy(strategy); var parentPID = Actor.Spawn(props); parentPID.Tell("crash"); childMailboxStats.Reset.Wait(1000); Assert.False(disposeCalled); }
public void OneForOneStrategy_Should_EscalateFailureToParent() { var parentMailboxStats = new TestMailboxStatistics(msg => msg is Stopped); var strategy = new OneForOneStrategy((pid, reason) => SupervisorDirective.Escalate, 1, null); var childProps = Actor.FromProducer(() => new ChildActor()); var parentProps = Actor.FromProducer(() => new ParentActor(childProps)) .WithSupervisor(strategy) .WithMailbox(() => UnboundedMailbox.Create(parentMailboxStats)); var parent = Actor.Spawn(parentProps); parent.Tell("hello"); parentMailboxStats.Reset.Wait(1000); var failure = parentMailboxStats.Received.OfType <Failure>().Single(); Assert.IsType <Exception>(failure.Reason); }
public void GivenCompletedSystemMessageTaskThrewException_ShouldEscalateFailure() { var mailboxHandler = new TestMailboxHandler(); var mailbox = UnboundedMailbox.Create(); mailbox.RegisterHandlers(mailboxHandler, mailboxHandler); var msg1 = new TestMessage(); var taskException = new Exception(); msg1.TaskCompletionSource.SetException(taskException); mailbox.PostSystemMessage(msg1); Assert.Equal(1, mailboxHandler.EscalatedFailures.Count); var e = Assert.IsType <AggregateException>(mailboxHandler.EscalatedFailures[0]); Assert.Equal(taskException, e.InnerException); }
static void Main(string[] args) { var props = new Props() // 用道具代理返回一个IActor实例 .WithProducer(() => new MyActor()) //默认邮箱使用无界队列 .WithMailbox(() => UnboundedMailbox.Create(new MyMailboxStatistics())) // 默认的 spawner 构造 Actor, Context 和 Process .WithSpawner(Props.DefaultSpawner); //从props衍生pid,pid代理一个actor的地址 var pid = Actor.Spawn(props); //把Hello对象交给HelloActor处理 pid.Tell(new MyEntity { Message = "this is message" }); Console.ReadLine(); }
public async Task GivenCompletedSystemMessageTaskThrewException_ShouldEscalateFailure() { var mailboxHandler = new TestMailboxHandler(); var mailbox = UnboundedMailbox.Create(); mailbox.RegisterHandlers(mailboxHandler, mailboxHandler); var msg1 = new TestMessageWithTaskCompletionSource(); var taskException = new Exception(); msg1.TaskCompletionSource.SetException(taskException); mailbox.PostSystemMessage(msg1); await mailboxHandler.HasFailures; Assert.Single(mailboxHandler.EscalatedFailures); var e = Assert.IsType <Exception>(mailboxHandler.EscalatedFailures[0]); Assert.Equal(taskException, e); }
public void AllForOneStrategy_Should_ResumeChildOnFailure() { var child1MailboxStats = new TestMailboxStatistics(msg => msg is ResumeMailbox); var child2MailboxStats = new TestMailboxStatistics(msg => msg is ResumeMailbox); var strategy = new AllForOneStrategy((pid, reason) => SupervisorDirective.Resume, 1, null); var child1Props = Props.FromProducer(() => new ChildActor()) .WithMailbox(() => UnboundedMailbox.Create(child1MailboxStats)); var child2Props = Props.FromProducer(() => new ChildActor()) .WithMailbox(() => UnboundedMailbox.Create(child2MailboxStats)); var parentProps = Props.FromProducer(() => new ParentActor(child1Props, child2Props)) .WithChildSupervisorStrategy(strategy); var parent = Context.Spawn(parentProps); Context.Send(parent, "hello"); child1MailboxStats.Reset.Wait(1000); Assert.Contains(ResumeMailbox.Instance, child1MailboxStats.Posted); Assert.Contains(ResumeMailbox.Instance, child1MailboxStats.Received); Assert.DoesNotContain(ResumeMailbox.Instance, child2MailboxStats.Posted); Assert.DoesNotContain(ResumeMailbox.Instance, child2MailboxStats.Received); }
public async Task GivenNonCompletedSystemMessageTaskThrewException_ShouldEscalateFailure() { var mailboxHandler = new TestMailboxHandler(); var mailbox = UnboundedMailbox.Create(); mailbox.RegisterHandlers(mailboxHandler, mailboxHandler); var msg1 = new TestMessage(); mailbox.PostSystemMessage(msg1); var taskException = new Exception(); Action resumeMailboxTrigger = () => msg1.TaskCompletionSource.SetException(taskException); await mailboxHandler.ResumeMailboxProcessingAndWaitAsync(resumeMailboxTrigger) .ConfigureAwait(false); Assert.Equal(1, mailboxHandler.EscalatedFailures.Count); var e = Assert.IsType <AggregateException>(mailboxHandler.EscalatedFailures[0]); Assert.Equal(taskException, e.InnerException); }
public void WhenActorWithChildrenStopped_DisposeIsCalledInEachChild() { bool child1Disposed = false; bool child2Disposed = false; var child1MailboxStats = new TestMailboxStatistics(msg => msg is Stopped); var child2MailboxStats = new TestMailboxStatistics(msg => msg is Stopped); var strategy = new AllForOneStrategy((pid, reason) => SupervisorDirective.Stop, 1, null); var child1Props = Actor.FromProducer(() => new DisposableActor(() => child1Disposed = true)) .WithMailbox(() => UnboundedMailbox.Create(child1MailboxStats)); var child2Props = Actor.FromProducer(() => new DisposableActor(() => child2Disposed = true)) .WithMailbox(() => UnboundedMailbox.Create(child2MailboxStats)); var parentProps = Actor.FromProducer(() => new ParentWithMultipleChildrenActor(child1Props, child2Props)) .WithChildSupervisorStrategy(strategy); var parent = Actor.Spawn(parentProps); parent.Tell("crash"); child1MailboxStats.Reset.Wait(1000); child2MailboxStats.Reset.Wait(1000); Assert.True(child1Disposed); Assert.True(child2Disposed); }
public override IMessageQueue Create(IActorRef owner, ActorSystem system) { var m = new UnboundedMailbox(); return(new VisualMailbox(m.Create(owner, system), owner, system)); }
private static IMailbox ProduceDefaultMailbox() => UnboundedMailbox.Create();
public Task Unbounded() => RunTest(() => UnboundedMailbox.Create());
private static void Main(string[] args) { var benchmarkSettings = Configuration.GetConfiguration <InprocBenchmarkSettings>("InprocBenchmarkSettings"); Console.WriteLine($"Is Server GC {GCSettings.IsServerGC}"); int messageCount = benchmarkSettings.MessageCount; int batchSize = benchmarkSettings.BatchSize; Console.WriteLine("Dispatcher\t\tElapsed\t\tMsg/sec"); var tps = benchmarkSettings.Throughputs; var msgSecs = new List <int>(); foreach (var t in tps) { var d = new ThreadPoolDispatcher { Throughput = t }; var clientCount = Environment.ProcessorCount * 1; var clients = new PID[clientCount]; var echos = new PID[clientCount]; var completions = new TaskCompletionSource <bool> [clientCount]; var echoProps = Actor.FromProducer(() => new EchoActor()) .WithDispatcher(d) .WithMailbox(() => benchmarkSettings.MailboxType == "bounded-mailbox" ? BoundedMailbox.Create(2048) : UnboundedMailbox.Create()); for (var i = 0; i < clientCount; i++) { var tsc = new TaskCompletionSource <bool>(); completions[i] = tsc; var clientProps = Actor.FromProducer(() => new PingActor(tsc, messageCount, batchSize)) .WithDispatcher(d) .WithMailbox(() => benchmarkSettings.MailboxType == "bounded-mailbox" ? BoundedMailbox.Create(2048) : UnboundedMailbox.Create()); clients[i] = Actor.Spawn(clientProps); echos[i] = Actor.Spawn(echoProps); } var tasks = completions.Select(tsc => tsc.Task).ToArray(); var sw = Stopwatch.StartNew(); for (var i = 0; i < clientCount; i++) { var client = clients[i]; var echo = echos[i]; client.Tell(new Start(echo)); } Task.WaitAll(tasks); sw.Stop(); var totalMessages = messageCount * 2 * clientCount; var x = (int)(totalMessages / (double)sw.ElapsedMilliseconds * 1000.0d); Console.WriteLine($"{t}\t\t\t{sw.ElapsedMilliseconds}\t\t{x}"); msgSecs.Add(x); Thread.Sleep(2000); } Console.WriteLine($"Avg Msg/sec : {msgSecs.Average()}"); Console.ReadLine(); }