/// <summary> /// Sends a message to the collection of routees. /// </summary> /// <param name="message">The message that is being sent.</param> /// <param name="sender">The actor sending the message.</param> public override void Send(object message, IActorRef sender) { _routees.Shuffle(); var routeeIndex = new AtomicCounter(0); var completion = new TaskCompletionSource<object>(); var cancelable = new Cancelable(_scheduler); completion.Task .ContinueWith(task => cancelable.Cancel(false)); if (_routees.Length == 0) { completion.TrySetResult(NoRoutee); } else { _scheduler.Advanced.ScheduleRepeatedly(TimeSpan.Zero, _interval, async () => { var currentIndex = routeeIndex.GetAndIncrement(); if (currentIndex >= _routees.Length) return; try { completion.TrySetResult(await ((Task<object>)_routees[currentIndex].Ask(message, _within))); } catch (TaskCanceledException) { completion.TrySetResult( new Status.Failure( new AskTimeoutException(String.Format("Ask timed out on {0} after {1}", sender, _within)))); } }, cancelable); } completion.Task.PipeTo(sender); }
/// <summary> /// Sends a message to the tail chopping router's collection of routees. /// </summary> /// <param name="message">The message to send.</param> /// <param name="sender">The sender of the message.</param> public override void Send(object message, ActorRef sender) { routees.Shuffle(); var routeeIndex = new AtomicCounter(0); var completion = new TaskCompletionSource<object>(); var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; var scheduledSends = scheduler.Schedule(TimeSpan.Zero, interval, async () => { var currentIndex = routeeIndex.GetAndIncrement(); if(currentIndex < routees.Length) { completion.TrySetResult(await ((Task<object>)routees[currentIndex].Ask(message, null))); } }, token); var withinTimeout = scheduler.ScheduleOnce(within, () => { completion.TrySetException(new TimeoutException(String.Format("Ask timed out on {0} after {1}", sender, within))); }, token); var request = completion.Task; completion.Task.ContinueWith((task) => { tokenSource.Cancel(false); }); request.PipeTo(sender); }