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(); } }
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(); } }
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); }); } } }
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); } } } }
public DateTime GetNextLiveDate(DateTime exclusiveLowerBound, WeeklyReleaseSchedule weeklyReleaseSchedule) { return(this.GetNextLiveDates(exclusiveLowerBound, weeklyReleaseSchedule, 1)[0]); }