public async Task ExecuteAsync(QueueId queueId, WeeklyReleaseSchedule weeklyReleaseSchedule)
        {
            queueId.AssertNotNull("queueId");
            weeklyReleaseSchedule.AssertNotNull("weeklyReleaseSchedule");

            var newWeeklyReleaseTimes = weeklyReleaseSchedule.Value.Select(
                _ => new WeeklyReleaseTime(queueId.Value, null, (byte)_.Value));

            var deletionParameters = new
            {
                QueueId = queueId.Value
            };

            // Transaction required on the following, as database must always contain at least one weekly release time per
            // collection. The absence of weekly release times would cause a breaking inconsistency.
            using (var transaction = TransactionScopeBuilder.CreateAsync())
            {
                using (var connection = this.connectionFactory.CreateConnection())
                {
                    await connection.ExecuteAsync(DeleteWeeklyReleaseTimesSql, deletionParameters);

                    await connection.InsertAsync(newWeeklyReleaseTimes);
                }

                transaction.Complete();
            }
        }
Exemple #2
0
        public async Task <WeeklyReleaseSchedule> ExecuteAsync(QueueId queueId)
        {
            queueId.AssertNotNull("queueId");

            var parameters = new
            {
                QueueId = queueId.Value
            };

            using (var connection = this.connectionFactory.CreateConnection())
            {
                var releaseTimes = await connection.QueryAsync <WeeklyReleaseTime>(Sql, parameters);

                var hoursOfWeek = releaseTimes.Select(_ => HourOfWeek.Parse(_.HourOfWeek)).ToArray();

                if (hoursOfWeek.Length == 0)
                {
                    throw new Exception(
                              string.Format(
                                  "Queue does not have any weekly release times defined. At least one should exist per collection at all times. {0}",
                                  queueId));
                }

                return(WeeklyReleaseSchedule.Parse(hoursOfWeek));
            }
        }
 public void ItShouldRequireUtcStartTime()
 {
     foreach (var schedule in Schedules)
     {
         this.target.GetNextLiveDates(DateTime.Now, WeeklyReleaseSchedule.Parse(schedule), 1);
     }
 }
        public void ItShouldReturnDatesThatAlignWithReleaseTimes()
        {
            foreach (var schedule in Schedules)
            {
                foreach (var date in Dates)
                {
                    var results = this.target.GetNextLiveDates(date, WeeklyReleaseSchedule.Parse(schedule), 10);

                    var expectedFirstReleaseTime = 0;
                    var currentHourOfWeek        = HourOfWeek.Parse(date);
                    for (var i = 0; i < schedule.Count; i++)
                    {
                        // If this never evaluates, it means the current date is beyond any scheduled date for this week,
                        // so we wrap around to the start of next week, which is 0 (initialized above).
                        if (currentHourOfWeek.Value < schedule[i].Value)
                        {
                            expectedFirstReleaseTime = i;
                            break;
                        }
                    }

                    for (var i = 0; i < results.Count; i++)
                    {
                        var expectedWeeklyReleaseTime = schedule[(i + expectedFirstReleaseTime) % schedule.Count];
                        var actualWeeklyReleaseTime   = HourOfWeek.Parse(results[i]);

                        Assert.AreEqual(expectedWeeklyReleaseTime, actualWeeklyReleaseTime);
                    }
                }
            }
        }
 public void ItShouldAllowZeroCount()
 {
     foreach (var schedule in Schedules)
     {
         foreach (var date in Dates)
         {
             this.target.GetNextLiveDates(date, WeeklyReleaseSchedule.Parse(schedule), 0);
         }
     }
 }
 public void ItShouldRequireNonNegativeCount()
 {
     foreach (var schedule in Schedules)
     {
         foreach (var date in Dates)
         {
             this.target.GetNextLiveDates(date, WeeklyReleaseSchedule.Parse(schedule), -1);
         }
     }
 }
 public void ItShouldReturnDatesGreaterThanTheLowerBound()
 {
     foreach (var schedule in Schedules)
     {
         foreach (var date in Dates)
         {
             foreach (var result in this.target.GetNextLiveDates(date, WeeklyReleaseSchedule.Parse(schedule), 10))
             {
                 Assert.IsTrue(result > date);
             }
         }
     }
 }
 public void ItShouldReturnDatesInUtc()
 {
     foreach (var schedule in Schedules)
     {
         foreach (var date in Dates)
         {
             foreach (var result in this.target.GetNextLiveDates(date, WeeklyReleaseSchedule.Parse(schedule), 10))
             {
                 Assert.AreEqual(result.Kind, DateTimeKind.Utc);
             }
         }
     }
 }
 public void ItShouldReturnListWithSameSizeAsCount()
 {
     foreach (var schedule in Schedules)
     {
         foreach (var date in Dates)
         {
             var weeklyReleaseSchedule = WeeklyReleaseSchedule.Parse(schedule);
             Assert.AreEqual(0, this.target.GetNextLiveDates(date, weeklyReleaseSchedule, 0).Count);
             Assert.AreEqual(1, this.target.GetNextLiveDates(date, weeklyReleaseSchedule, 1).Count);
             Assert.AreEqual(10, this.target.GetNextLiveDates(date, weeklyReleaseSchedule, 10).Count);
         }
     }
 }
        public async Task ExecuteAsync(QueueId queueId, WeeklyReleaseSchedule weeklyReleaseSchedule, DateTime now)
        {
            queueId.AssertNotNull("queueId");
            weeklyReleaseSchedule.AssertNotNull("weeklyReleaseSchedule");
            now.AssertUtc("now");

            // Transaction required on the following, as we don't want user to see a queue that does not match the collection's release times.
            using (var transaction = TransactionScopeBuilder.CreateAsync())
            {
                await this.replaceWeeklyReleaseTimes.ExecuteAsync(queueId, weeklyReleaseSchedule);

                await this.defragmentQueue.ExecuteAsync(queueId, weeklyReleaseSchedule, now);

                transaction.Complete();
            }
        }
Exemple #11
0
        private async Task AssertSuccessAsync(WeeklyReleaseSchedule schedule, IEnumerable <HourOfWeek> expectedInserts, IEnumerable <HourOfWeek> expectedDeletes)
        {
            await this.DatabaseTestAsync(async testDatabase =>
            {
                this.InitializeTarget(testDatabase);
                await this.CreateEntitiesAsync(testDatabase);
                await testDatabase.TakeSnapshotAsync();

                await this.target.ExecuteAsync(QueueId, schedule);

                return(new ExpectedSideEffects
                {
                    Inserts = expectedInserts.Select(_ => new WeeklyReleaseTime(QueueId.Value, null, (byte)_.Value)).ToArray(),
                    Deletes = expectedDeletes.Select(_ => new WeeklyReleaseTime(QueueId.Value, null, (byte)_.Value)).ToArray()
                });
            });
        }
        public async Task ExecuteAsync(QueueId queueId, WeeklyReleaseSchedule weeklyReleaseSchedule, DateTime now)
        {
            queueId.AssertNotNull("queueId");
            weeklyReleaseSchedule.AssertNotNull("weeklyReleaseSchedule");
            now.AssertUtc("now");

            var queueSize = await this.getQueueSize.ExecuteAsync(queueId, now);

            if (queueSize == 0)
            {
                return;
            }

            var unfragmentedLiveDates = this.liveDateCalculator.GetNextLiveDates(now, weeklyReleaseSchedule, queueSize);

            await this.updateAllLiveDatesInQueue.ExecuteAsync(queueId, unfragmentedLiveDates, now);
        }
        public void ItShouldReturnDatesInAnIncreasingSequence()
        {
            foreach (var schedule in Schedules)
            {
                foreach (var date in Dates)
                {
                    var result = this.target.GetNextLiveDates(date, WeeklyReleaseSchedule.Parse(schedule), 10);

                    result.Aggregate(
                        date,
                        (previous, current) =>
                    {
                        Assert.IsTrue(current > previous);
                        return(current);
                    });
                }
            }
        }
Exemple #14
0
        public IReadOnlyList <DateTime> GetNextLiveDates(
            DateTime exclusiveLowerBound,
            WeeklyReleaseSchedule weeklyReleaseSchedule,
            int numberOfLiveDatesToReturn)
        {
            exclusiveLowerBound.AssertUtc("exclusiveLowerBound");
            weeklyReleaseSchedule.AssertNotNull("weeklyReleaseSchedule");
            numberOfLiveDatesToReturn.AssertNonNegative("numberOfLiveDatesToReturn");

            var startTimeWithWeekReset = new DateTime(
                exclusiveLowerBound.Year,
                exclusiveLowerBound.Month,
                exclusiveLowerBound.Day,
                0,
                0,
                0,
                DateTimeKind.Utc)
                                         .AddDays(-1 * (int)exclusiveLowerBound.DayOfWeek);

            var ascendingWeeklyReleaseTimes     = weeklyReleaseSchedule.Value;
            var releasesPerWeek                 = ascendingWeeklyReleaseTimes.Count;
            var currentHourOfWeek               = HourOfWeek.Parse(exclusiveLowerBound).Value;
            var nextReleaseTimeAfterCurrentTime = ascendingWeeklyReleaseTimes.FirstOrDefault(_ => _.Value > currentHourOfWeek);
            var startFromNextWeek               = nextReleaseTimeAfterCurrentTime == null;
            var releaseTimeIndexOffset          = startFromNextWeek ? releasesPerWeek : ascendingWeeklyReleaseTimes.IndexOf(nextReleaseTimeAfterCurrentTime);

            var result = new List <DateTime>();

            for (var i = releaseTimeIndexOffset; i < numberOfLiveDatesToReturn + releaseTimeIndexOffset; i++)
            {
                var weeksFilled       = i / releasesPerWeek;
                var releaseTimeIndex  = i % releasesPerWeek;
                var releaseHourOfWeek = ascendingWeeklyReleaseTimes[releaseTimeIndex].Value;

                var releaseWeek = startTimeWithWeekReset.AddDays(weeksFilled * 7);
                var releaseTime = releaseWeek.AddHours(releaseHourOfWeek);

                result.Add(releaseTime);
            }

            return(result);
        }
        public void ItShouldReturnDatesClippedToTheHour()
        {
            foreach (var schedule in Schedules)
            {
                foreach (var date in Dates)
                {
                    foreach (var result in this.target.GetNextLiveDates(date, WeeklyReleaseSchedule.Parse(schedule), 10))
                    {
                        var timeWithHourPrecision = new DateTime(
                            result.Year,
                            result.Month,
                            result.Day,
                            result.Hour,
                            minute: 0,
                            second: 0,
                            kind: DateTimeKind.Utc);

                        Assert.AreEqual(result, timeWithHourPrecision);
                    }
                }
            }
        }
Exemple #16
0
 public DateTime GetNextLiveDate(DateTime exclusiveLowerBound, WeeklyReleaseSchedule weeklyReleaseSchedule)
 {
     return(this.GetNextLiveDates(exclusiveLowerBound, weeklyReleaseSchedule, 1)[0]);
 }