private static ActorScheduleOptions RemoveFlag(ActorScheduleOptions options, ActorScheduleOptions toRemove)
 {
     if (options.HasFlag(toRemove))
     {
         return(options ^ toRemove);
     }
     else
     {
         return(options);
     }
 }
Пример #2
0
        public void ShouldBeAbleToScheduleWorkToRepeatAtAFixedInterval(WorkType workType, ActorScheduleOptions actorScheduleOptions)
        {
            var barrier          = new TaskCompletionSource <bool>();
            var expectedInterval = TimeSpan.FromMilliseconds(100);
            var times            = new List <DateTime>();
            var sampleSize       = 5;

            void Adder()
            {
                if (times.Count < sampleSize)
                {
                    times.Add(DateTime.UtcNow);
                }

                if (times.Count == sampleSize)
                {
                    // Block here so that we can assess something that's not moving
                    barrier.Task.Wait();
                }
            }

            switch (workType)
            {
            case WorkType.Sync:
                _scheduler.Schedule((Action)Adder, expectedInterval, actorScheduleOptions);
                break;

            case WorkType.Async:
                _scheduler.Schedule(async() =>
                {
                    await Task.Yield();
                    Adder();
                },
                                    expectedInterval,
                                    actorScheduleOptions);
                break;

            default:
                throw new Exception($"Unhandled test case {workType}.");
            }

            Within.FiveSeconds(() => times.Count.Should().Be(sampleSize));

            var actualIntervals = times.Take(sampleSize - 1).Zip(times.Skip(1), (x, y) => y - x).ToList();

            // Use 75ms instead of 100ms to give it a bit of latitude: mainly we just want to make sure there is some delaying going on.
            actualIntervals.Should().OnlyContain(x => x >= TimeSpan.FromMilliseconds(75));

            barrier.SetResult(true);
        }
 /// <summary>
 /// A wrapper round IActorWorkScheduler.Schedule() that reschedules work after an unxexpected error has occurred in that work.
 /// </summary>
 /// <param name="self">The schedule.</param>
 /// <param name="work">The work to perform repeatedly.</param>
 /// <param name="interval">Interval at which the work is to be repeated.</param>
 /// <param name="options">Options.  See <see cref="ActorScheduleOptions"/> for details.</param>
 /// <param name="unexpectedErrorHandler">Handler for any unexpected exception.</param>
 /// <returns>A task: the only possible completion is due to cancellation.</returns>
 public static Task Schedule(this IActorWorkScheduler self, Func <Task> work, TimeSpan interval, ActorScheduleOptions options, Action <Exception> unexpectedErrorHandler)
 {
     return(ScheduleImpl(self.Schedule(work, interval, options), () => self.Schedule(work, interval, RemoveFlag(options, ActorScheduleOptions.NoInitialDelay)), unexpectedErrorHandler));
 }