public void A_loopback_registry() { Address = new Uri("loopback://localhost/"); ReceivedA = new Future <A>(); Registry = ActorRegistryFactory.New(x => { x.Remote(r => { r.ListenTo(Address); }); }); ActorId = Guid.NewGuid(); Actor = AnonymousActor.New(inbox => { inbox.Loop(loop => { loop.Receive <Message <A> >(message => { ReceivedA.Complete(message.Body); loop.Continue(); }); }); }); Registry.Register(ActorId, Actor); }
public void Newly_created_account_should_have_correct_balence_and_credit() { ActorRef account = ActorFactory.Create(inbox => new AccountActor(inbox, 100.0m)).GetActor(); Future <bool> result = new Future <bool>(); decimal balance = 0xDEADBEEF; decimal availableCredit = 0xDEADBEEF; decimal creditLimit = 0xDEADBEEF; AnonymousActor.New(inbox => { account.Request(new QueryAccountBalance(), inbox) .Receive <AccountBalance>(message => { balance = message.Balance; availableCredit = message.AvailableCredit; creditLimit = message.CreditLimit; Console.WriteLine("Balance={0}, Credit={1}, Limit={2}", balance, availableCredit, creditLimit); result.Complete(true); }); }); result.WaitUntilCompleted(5.Seconds()); Assert.True(balance == 0 && availableCredit == 100.0m && creditLimit == 100.0m); }
public void Should_properly_handle_the_response() { var response = new FutureChannel <Purchased>(); decimal price = 0.0m; AnonymousActor.New(inbox => { Auction.Request(new Ask(Id), inbox) .Within(30.Seconds()) .Receive <Response <Status> >(m => status => { price = status.Body.CurrentBid; Auction.Request(new Buy(status.Body.Token, 1), inbox) .Within(30.Seconds()) .Receive <Response <Purchased> >(pm => pmsg => response.Complete(pmsg.Body)) .Otherwise(() => {}); }) .Receive <Response <Ended> >(m => ended => {}); }); response.WaitUntilCompleted(4.Seconds()).ShouldBeTrue("Timeout waiting for response"); response.Value.AuctionId.ShouldEqual(Id); response.Value.Quantity.ShouldEqual(1); response.Value.Price.ShouldEqual(price); }
public void When_actor_handles_messages_Then_it_calls_the_correct_handler() { var receivedStrings = new List <string>(); var receivedInts = new List <int>(); var receivedFloats = new List <float>(); var receivedObjects = new List <object>(); var allRecievedMessages = new List <object>(); Func <Actor> actorFactory = () => AnonymousActor.Create(c => { // ReSharper disable ConvertClosureToMethodGroup c.AddReceiver(typeof(object), msg => { allRecievedMessages.Add(msg); return(false); }); c.Receive <float>(f => receivedFloats.Add(f)); c.Receive <int>(i => receivedInts.Add(i)); c.ReceiveAny(o => receivedObjects.Add(o)); c.Receive <string>(s => receivedStrings.Add(s)); //Since we have a Catch-all above then no floats should end up here // ReSharper restore ConvertClosureToMethodGroup }); var actor = ActorHelper.CreateInitializedActorDirectly(actorFactory); actor.HandleMessage(1.0f); actor.HandleMessage(2); actor.HandleMessage(true); actor.HandleMessage("4"); receivedFloats.Should().BeEquivalentTo(1.0f); receivedInts.Should().BeEquivalentTo(2); receivedObjects.Should().BeEquivalentTo(true, "4"); receivedStrings.Should().BeEmpty(); allRecievedMessages.Should().BeEquivalentTo(1.0f, 2, true, "4"); }
public void Should_properly_serialize_a_response() { var actor = AnonymousActor.New(inbox => { _channel.Respond(new Test { Name = "Magic" }, "21"); }); ThreadUtil.Sleep(1.Seconds()); }
public void An_exit_is_sent_to_an_actor() { _receivedA = new Future <A>(); _actor = AnonymousActor.New(inbox => { inbox.Receive <A>(message => { _receivedA.Complete(message); }); }); }
public void Should_prevent_the_actor_from_exiting() { AnonymousActor.New(inbox => { _actor.Request <Exit>(inbox) .Within(5.Seconds()) .Receive <Response <Exit> >(x => { }); }); _intercepted.WaitUntilCompleted(5.Seconds()).ShouldBeTrue("Exit was not intercepted"); _actor.Send(new A()); _receivedA.WaitUntilCompleted(5.Seconds()).ShouldBeTrue("A was not handled, did actor exit?"); }
public void Should_support_the_repeat_syntax() { var completed = new Future <Status>(); ActorRef auction = AnonymousActor.New(inbox => { decimal currentBid = 0.0m; inbox.Loop(loop => { loop.Receive <Request <Bid> >(request => { if (request.Body.MaximumBid > currentBid) { currentBid = request.Body.MaximumBid; } request.Respond(new StatusImpl { CurrentBid = currentBid }); loop.Continue(); }) .Receive <Request <Ask> >(request => { request.Respond(new StatusImpl { CurrentBid = currentBid }); loop.Continue(); }); }); }); ActorRef bidder = AnonymousActor.New(inbox => { auction.Request(new BidImpl(13.5m), inbox) .Receive <Response <Status> >(bidResponse => { auction.Request <Ask>(inbox) .Receive <Response <Status> >(askResponse => completed.Complete(askResponse.Body)); }); }); completed.WaitUntilCompleted(5.Seconds()).ShouldBeTrue(); bidder.Exit(); auction.Exit(); }
public void Should_not_receive_a_response_to_a_stupid_message() { var response = new FutureChannel <bool>(); AnonymousActor.New(inbox => { Auction.Request(new Ask(new Guid()), inbox) .Within(1.Seconds()) .Receive <Response <Status> >(m => status => {}) .Otherwise(() => response.Complete(true)); }); response.WaitUntilCompleted(4.Seconds()).ShouldBeTrue("Timeout waiting for otherwise to be called"); }
public void A_stream_of_messages_is_received() { ActorFactory <Agent> agentFactory = ActorFactory.Create(inbox => new Agent(inbox)); ActorRef agent = agentFactory.GetActor(); for (int i = 0; i < _count; i++) { agent.Send(new Add { Value = i }); if (i == 100) { agent.Send <Suspend>(); } if (i == 500) { agent.Send <Resume>(); } } _response = new Future <Status>(); var actor = AnonymousActor.New(inbox => { Action loop = null; loop = () => { agent.Request(new Status(), inbox) .Receive <Response <Status> >(response => { if (response.Body.Count == _count) { _response.Complete(response.Body); } else { loop(); } }); }; loop(); }); _response.WaitUntilCompleted(8.Seconds()); }
public void Should_receive_the_expected_value() { var response = new FutureChannel <Status>(); AnonymousActor.New(inbox => { Auction.Request(new Ask(Id), inbox) .Within(30.Seconds()) .Receive <Response <Status> >(m => status => response.Complete(status.Body)) .Receive <Response <Ended> >(m => ended => {}); }); response.WaitUntilCompleted(4.Seconds()).ShouldBeTrue("Timeout waiting for response"); response.Value.AuctionId.ShouldEqual(Id); }
public void Easy_syntax_love() { ActorFactory <QuoteService> factory = StateMachineActorFactory.Create <QuoteServiceWorkflow, QuoteService>(inbox => new QuoteService(inbox), x => { x.AccessCurrentState(s => s.CurrentState); x.Initially() .When(e => e.GetQuoteRequest) .Then(i => i.SendQuoteRequest) .TransitionTo(s => s.WaitingForResponse); x.During(s => s.WaitingForResponse) .When(e => e.CancelRequest) .Then(i => i.Cancel) .Finalize(); }); ActorRef service = factory.GetActor(); var response = new Future <Response <RequestSent> >(); var actor = AnonymousActor.New(inbox => { service.Request(new GetQuote { Symbol = "MSFT" }, inbox) .Receive <Response <RequestSent> >(r => { service.Request(new GetQuote { Symbol = "AAPL" }, inbox) .Receive <Response <RequestSent> >(rr => { response.Complete(r); }); }); }); response.WaitUntilCompleted(5.Seconds()).ShouldBeTrue(); service.Exit(); }
public ParentWithFailingChildActor(Mailbox failingChildMailbox, IEnumerable <Mailbox> siblingMailboxes, SupervisorStrategy supervisorStrategy = null) { _supervisorStrategy = supervisorStrategy; var failingChildProps = new DelegateActorCreationProperties(() => AnonymousActor.Create <object>(_ => { throw new Exception(); })) { MailboxCreator = () => failingChildMailbox }; Func <Mailbox, ActorCreationProperties> createSibling = m => new DelegateActorCreationProperties(() => new NoopActor()) { MailboxCreator = () => m }; var failingChild = CreateActor(failingChildProps, "FailingChild"); siblingMailboxes.ForEach((m, i) => CreateActor(createSibling(m), "Sibling" + i)); ReceiveAnyAndForward(failingChild); }
public void Should_receive_the_alternate_ending_if_it_is_such() { Auction.Send(new End()); var response = new FutureChannel <Ended>(); AnonymousActor.New(inbox => { Auction.Request(new Ask(Id), inbox) .Within(30.Seconds()) .Receive <Response <Status> >(m => status => {}) .Receive <Response <Ended> >(m => ended => response.Complete(ended.Body)); }); response.WaitUntilCompleted(4.Seconds()).ShouldBeTrue("Timeout waiting for response"); response.Value.AuctionId.ShouldEqual(Id); }
public void Should_receive_a_fault_message() { var received = new Future <Fault>(); AnonymousActor.New(inbox => { inbox.Receive <Fault>(fault => { received.Complete(fault); }); throw new NotImplementedException("A"); }); received.WaitUntilCompleted(5.Seconds()).ShouldBeTrue(); received.Value.Message.ShouldEqual("A"); Trace.WriteLine(received.Value.StackTrace); }
public void An_exit_is_sent_to_an_actor_that_intercepts_exit() { _intercepted = new Future <Exit>(); _receivedA = new Future <A>(); _actor = AnonymousActor.New(inbox => { inbox.Receive <Request <Exit> >(request => { _intercepted.Complete(request.Body); request.Respond(request.Body); }); inbox.Receive <A>(message => { _receivedA.Complete(message); }); }); }
public void When_an_actor_crashes_during_handling_message_Then_the_actors_mailbox_gets_suspended() { var system = new TestActorSystem(); system.Start(); var mailbox = new TestMailbox(system.CreateDefaultMailbox()); var props = new DelegateActorCreationProperties(() => AnonymousActor.Create <object>(_ => { throw new Exception(); })) { MailboxCreator = () => mailbox }; var actor = system.CreateActor(props); actor.Send("A trigger message that will cause actor to fail", null); var suspendCalls = mailbox.GetStateChangesFor(TestMailbox.StateChange.Suspend); suspendCalls.Count.Should().Be(1); }
public void Send(ConnectionContext context) { AnonymousActor.New(inbox => { _serviceCoordinator.Send <Request <ServiceStatus> >(new RequestImpl <ServiceStatus>(inbox, new ServiceStatus())); inbox.Receive <Response <ServiceStatus> >(response => { var view = new DashboardView(response.Body.Services); context.Response.RenderSparkView(view, "dashboard.html"); context.Complete(); }, 30.Seconds(), () => { context.Response.StatusCode = (int)HttpStatusCode.RequestTimeout; context.Complete(); }); }); }
public void When_two_actors_are_linked() { _a = AnonymousActor.New(inbox => { inbox.Receive <Die>(x => { inbox.Exit(); }); }); _b = AnonymousActor.New(inbox => { _a.Link(inbox); inbox.Receive <Die>(x => { }); }); }
public void Something() { ActorRef actor = AnonymousActor.New(inbox => { inbox.Loop(loop => { loop.Receive <Request <Add> >(message => { int result = message.Body.Left + message.Body.Right; Trace.WriteLine("Responding with " + result + " on thread " + Thread.CurrentThread.ManagedThreadId); message.Respond(new AddResult { Result = result }); loop.Continue(); }); loop.Receive <Exit>(msg => { inbox.Exit(); loop.Continue(); }); }); }); var future = new Future <AddResult>(); AnonymousActor.New(inbox => actor.Request(new Add { Left = 56, Right = 23 }, inbox) .Receive <AddResult>(response => future.Complete(response))); future.WaitUntilCompleted(8.Seconds()).ShouldBeTrue("Didn't responsd"); }
public void When_watching_another_actor_Then_a_Watch_message_is_sent_to_that_actor() { var system = new TestActorSystem(); system.Start(); var mailbox = new TestMailbox(system.CreateDefaultMailbox()); var watchedActorProps = new DelegateActorCreationProperties(() => AnonymousActor.Create <object>(_ => { })) { MailboxCreator = () => mailbox }; var watchedActor = system.CreateActor(watchedActorProps, "WatchedActor"); var watcher = system.CreateActor(ActorCreationProperties.Create(() => new WatchingActor(watchedActor)), "Watcher"); watcher.Send("watch", null); var watchMessages = mailbox.GetEnquedSystemMessagesOfType <WatchActor>(); watchMessages.Should().HaveCount(1); watchMessages[0].Watcher.Should().BeSameAs(watcher); }
public void Should_not_call_the_other_receive_handlers() { var statusResponse = new FutureChannel <Status>(); var endedResponse = new FutureChannel <Ended>(); AnonymousActor.New(inbox => { Auction.Request(new Ask(Id), inbox) .Within(10.Seconds()) .Receive <Response <Status> >(m => status => { statusResponse.Complete(status.Body); Auction.Send(new End()); Auction.Request(new Ask(Id), inbox); }) .Receive <Response <Ended> >(m => ended => endedResponse.Complete(ended.Body)); }); statusResponse.WaitUntilCompleted(4.Seconds()).ShouldBeTrue("Timeout waiting for response"); endedResponse.WaitUntilCompleted(2.Seconds()).ShouldBeFalse("The receiver for Ended should not have been called."); }
public void Run() { Trace.Listeners.Add(new ConsoleTraceListener()); const string remoteAddress = "rm://234.0.0.7:40001/"; Guid id = CombGuid.Generate(); ActorRegistry registry = ActorRegistryFactory.New(x => { x.Remote(r => r.ListenTo(remoteAddress)); }); ActorRef server = AnonymousActor.New(inbox => { inbox.Receive <Response <Hello> >(message => { Console.WriteLine("Hi!"); Console.WriteLine("Request ID: " + message.RequestId); }); }); registry.Register(id, server); var actorAddress = new ActorUrn(remoteAddress, id); registry.Select(actorAddress, actor => { actor.Send <Response <Hello> >(new ResponseImpl <Hello>(new Hello { MyNameIs = "Joe", }, "27")); }, () => {}); ThreadUtil.Sleep(5.Seconds()); registry.Shutdown(); }
public void HandleStop(Request <Stop> request) { IEnumerator <ActorRef> next = _inbox.LinkedActors.GetEnumerator(); if (next.MoveNext()) { AnonymousActor.New(x => x.Loop(loop => { next.Current.Request <Stop>(x) .Receive <Response <Stop> >(response => { if (next.MoveNext()) { loop.Continue(); } else { request.Respond(); } }); })); } }
public void Adding_an_actor_to_a_registry() { _auctionFactory = ActorFactory.Create(inbox => new Auction(inbox)); _auctionId = CombGuid.Generate(); ActorRef auction = _auctionFactory.GetActor(); ActorRegistry registry = ActorRegistryFactory.New(x => { //x.Remote(r => r.ListenTo("rm://234.0.0.7:40001")); }); registry.Register(_auctionId, auction); _response = new Future <Response <Bid> >(); AnonymousActor.New(inbox => { registry.Request <Bid>(new BidImpl(27.42m), header => { header.DestinationAddress = new ActorUrn(_auctionId); }, inbox) .Receive <Response <Bid> >(x => _response.Complete); }); _response.WaitUntilCompleted(5.Seconds()).ShouldBeTrue(); // need to proxy the channel with headers somehow... // untyped channel => channel mapper -> actor instance // DestinationAddress -> set by outbound channel proxy on message<> // SourceAddress -> set by outbound channel proxy when available (not likely) // ResponseAddress -> set by outbound channel for ResponseChannel on Request to map to channel // Id -> system assigned id // DestinationAddress = urn:actor:554FC958-4661-4FE9-94F5-21D190417BCC }
public void Should_not_require_extensive_namespace_references() { var responded = new Future <MyResponse>(); ActorRef server = AnonymousActor.New(inbox => { inbox.Receive <Request <MyRequest> >(request => { // send our response request.Respond(new MyResponse()); }); }); ActorRef client = AnonymousActor.New(inbox => { server.Request(new MyRequest(), inbox) .Receive <Response <MyResponse> >(response => responded.Complete(response.Body)); }); responded.WaitUntilCompleted(2.Seconds()).ShouldBeTrue(); server.Exit(); client.Exit(); }
public void Charging_an_account_async_should_still_adjust_the_balence() { ActorRef account = ActorFactory.Create(inbox => new AccountActor(inbox, 100.0m)).GetActor(); decimal balance = 0xDEADBEEF; decimal availableCredit = 0xDEADBEEF; decimal creditLimit = 0xDEADBEEF; #region Charge 3 times with 10.0 async AnonymousActor.New(inbox => { account.Send(new ChargeAccount() { Amount = 10 }); }); AnonymousActor.New(inbox => { account.Send(new ChargeAccount() { Amount = 10 }); }); AnonymousActor.New(inbox => { account.Send(new ChargeAccount() { Amount = 10 }); }); #endregion #region Loop until available credit is correct but fail if more than 50 times for (int i = 0; availableCredit != 70.0m && i < 100; i++) { Future <bool> result = new Future <bool>(); //Fire of listeners serially and with some time apart AnonymousActor.New(inbox => { account.Request(new QueryAccountBalance(), inbox) .Receive <AccountBalance>(message => { balance = message.Balance; availableCredit = message.AvailableCredit; creditLimit = message.CreditLimit; Console.WriteLine("Balance={0}, Credit={1}, Limit={2}", balance, availableCredit, creditLimit); Thread.Sleep(1000); result.Complete(true); }); }); result.WaitUntilCompleted(5.Seconds()); Console.WriteLine("Listener {0} completed", i); Thread.Sleep(1000); Assert.True(i < 50); } #endregion Assert.True(balance == 30 && availableCredit == 70.0m && creditLimit == 100.0m); }
public void When_an_actor_crashes_during_handling_message_Then_it_gets_recreated() { var system = new TestActorSystem(); system.Start(); var numberOfCreateCalls = 0; var props = new DelegateActorCreationProperties(() => { numberOfCreateCalls++; return(AnonymousActor.Create <object>(_ => { throw new Exception(); })); }); var actor = system.CreateActor(props); numberOfCreateCalls.Should().Be(1); actor.Send("A trigger message that will cause actor to fail", null); numberOfCreateCalls.Should().Be(2); }
public void When_actor_forwards_messages_of_specific_types_Then_it_calls_send_on_receiving_actor() { var testActorSystem = new TestActorSystem(); testActorSystem.Start(); TestActor recipientActor = null; var recipient = testActorSystem.CreateActor(ActorCreationProperties.Create(() => { recipientActor = new TestActor(); return(recipientActor); })); var receivedObjects = new List <object>(); var sut = testActorSystem.CreateActor(ActorCreationProperties.Create(() => AnonymousActor.Create(c => { // ReSharper disable ConvertClosureToMethodGroup c.ReceiveAndForward <int>(recipient); c.ReceiveAndForward <float>(recipient); c.ReceiveAny(o => receivedObjects.Add(o)); // ReSharper restore ConvertClosureToMethodGroup }))); var senderActor = testActorSystem.CreateActor(ActorCreationProperties.Create(() => new SendingActor(sut, 1, "2", 3.0f))); senderActor.Send("Send 1 2 and 3.0", null); recipientActor.ReceivedMessages.Should().HaveCount(2); recipientActor.ReceivedMessages[0].Item1.Should().BeSameAs(senderActor); recipientActor.ReceivedMessages[0].Item2.Should().Be(1); recipientActor.ReceivedMessages[1].Item1.Should().BeSameAs(senderActor); recipientActor.ReceivedMessages[1].Item2.Should().Be(3.0f); receivedObjects.Should().BeEquivalentTo(new object[] { "2" }); }
public TestActor(ActorSystem system, bool childMailboxShouldBeOpen = true) { Replies = new List <string>(); var childMailbox = new DelayedTestMailbox(system.CreateDefaultMailbox()); var child = CreateActor(new DelegateActorCreationProperties(() => AnonymousActor.Create(c => c.ReceiveAny((msg, sender) => sender.Reply(msg)))) { MailboxCreator = () => childMailbox }, "Child"); if (childMailboxShouldBeOpen) { childMailbox.Open(); } Watch(child); Receive <WatchedActorTerminated>(terminated => ReceivedTerminate = true, m => m.TerminatedActor == child); //Record that child terminated Receive <string>(_ => child.Send(StopActor.Instance, Self), s => s == "stopChild"); //Send Stop to child when any other message is received Receive <string>(_ => childMailbox.Open(), s => s == "openChildMailbox"); Receive <string>(s => Replies.Add(s), _ => Sender.Path == child.Path); //Record replies from child ReceiveAny(m => child.Send(m, Self)); //Forward all other messages }