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 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_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 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_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 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 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 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 Run() { var network = new Uri("pgm://224.0.0.7:40001"); ActorRef actor = AnonymousActor.New(inbox => { inbox.Loop(loop => { loop .Receive <A>(message => { Console.WriteLine("Received: " + message.Name); loop.Continue(); }) .Receive <B>(message => { Console.WriteLine("Received: " + message.Address); loop.Continue(); }); }); }); using (var writer = new ReliableMulticastWriter(network)) { writer.Start(); MessageHeaders.MatchHeaderChannel channel; using (var buffer = new BufferedChunkWriter(new PoolFiber(), new TimerScheduler(new PoolFiber()), writer, 64 * 1024)) { buffer.Start(); channel = new MessageHeaders.MatchHeaderChannel( new MatchHeaderChannel(new SerializeChunkChannel(buffer, new FastTextSerializer()))); MessageHeaders.MatchHeaderChannel channel2; using (var buffer2 = new BufferedChunkWriter(new PoolFiber(), new TimerScheduler(new PoolFiber()), writer, 64 * 1024) ) { buffer2.Start(); channel2 = new MessageHeaders.MatchHeaderChannel( new MatchHeaderChannel(new SerializeChunkChannel(buffer2, new FastTextSerializer()))); Console.WriteLine("Writer started"); for (int i = 0; i < 10; i++) { channel.Send(new A { Name = "Joe" }); channel2.Send(new B { Address = "American Way", }); } Console.WriteLine("Sent message"); var reader = new DeserializeChunkChannel(actor, new FastTextSerializer()); using (var listener = new ReliableMulticastListener(network, reader)) { Console.WriteLine("Listener created"); listener.Start(); Console.WriteLine("Listener started"); Thread.Sleep(2000); Console.WriteLine("Leaving Listener"); } Console.WriteLine("Listener stopped"); } } } Console.WriteLine("Sender Stopped"); }
public void Run() { Stopwatch timer = Stopwatch.StartNew(); const int actorCount = 20; const int pingCount = 4000; var actors = new ActorRef[actorCount + 1]; var complete = new Future <int>(); var latch = new CountdownLatch(actorCount * pingCount, complete.Complete); for (int i = actorCount; i >= 0; i--) { actors[i] = AnonymousActor.New(inbox => { var pong = new Pong(); var server = actors[(i + 1)]; inbox.Loop(loop => { loop.Receive <Request <Ping> >(request => { request.Respond(pong); loop.Continue(); }); }); if (i < actorCount) { var ping = new Ping(); int count = 0; Action loop = null; loop = () => { server.Request(ping, inbox) .Receive <Response <Pong> >(response => { latch.CountDown(); count++; if (count < pingCount) { loop(); } }); }; loop(); } }); } bool completed = complete.WaitUntilCompleted(5.Minutes()); timer.Stop(); for (int i = 0; i < actorCount; i++) { actors[i].Exit(); actors[i] = null; } if (!completed) { Console.WriteLine("Process did not complete"); return; } Console.WriteLine("Processed {0} messages in with {1} actors in {2}ms", pingCount, actorCount, timer.ElapsedMilliseconds); Console.WriteLine("That's {0} messages per second!", ((long)pingCount * actorCount * 2 * 1000) / timer.ElapsedMilliseconds); }