예제 #1
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 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();
            }
        }
예제 #3
0
        public async Task ExecuteAsync(PostId postId, QueueId queueId)
        {
            postId.AssertNotNull("postId");
            queueId.AssertNotNull("queueId");

            var nextLiveDate = await this.getLiveDateOfNewQueuedPost.ExecuteAsync(queueId);

            var post = new Post(postId.Value)
            {
                QueueId  = queueId.Value,
                LiveDate = nextLiveDate
            };

            var parameters = new SqlGenerationParameters <Post, Post.Fields>(post)
            {
                UpdateMask = Post.Fields.QueueId | Post.Fields.LiveDate,
                Conditions = new[]
                {
                    WherePostLiveDateUniqueToQueue, // Perform locks in 'descending supersets' to avoid deadlock.
                    WherePostNotInQueue
                }
            };

            using (var connection = this.connectionFactory.CreateConnection())
            {
                var failedConditionIndex = await connection.UpdateAsync(parameters);

                var concurrencyFailure = failedConditionIndex == 0;

                if (concurrencyFailure)
                {
                    throw new OptimisticConcurrencyException(string.Format("Failed to optimistically queue post with queue {0}", queueId));
                }
            }
        }
        public async Task <DateTime> ExecuteAsync(QueueId queueId)
        {
            queueId.AssertNotNull("queueId");

            var exclusiveLowerBound = await this.getNewQueuedPostLiveDateLowerBound.ExecuteAsync(queueId, DateTime.UtcNow);

            var weeklyReleaseSchedule = await this.getWeeklyReleaseSchedule.ExecuteAsync(queueId);

            return(this.queuedPostLiveDateCalculator.GetNextLiveDate(
                       exclusiveLowerBound,
                       weeklyReleaseSchedule));
        }
예제 #5
0
        public async Task ExecuteAsync(QueueId queueId)
        {
            queueId.AssertNotNull("queueId");

            using (var connection = this.connectionFactory.CreateConnection())
            {
                await connection.ExecuteAsync(
                    DeleteSql,
                    new
                {
                    QueueId = queueId.Value
                });
            }
        }
        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();
            }
        }
예제 #7
0
        public async Task <int> ExecuteAsync(QueueId queueId, DateTime now)
        {
            queueId.AssertNotNull("queueId");
            now.AssertUtc("now");

            var parameters = new
            {
                QueueId = queueId.Value,
                Now     = now
            };

            using (var connection = this.connectionFactory.CreateConnection())
            {
                return(await connection.ExecuteScalarAsync <int>(Sql, parameters));
            }
        }
        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 async Task ExecuteAsync(QueueId queueId, IReadOnlyList <DateTime> ascendingLiveDates, DateTime now)
        {
            queueId.AssertNotNull("queueId");
            ascendingLiveDates.AssertNotNull("ascendingLiveDates");
            ascendingLiveDates.AssertNonEmpty("ascendingLiveDates");
            now.AssertUtc("now");

            if (ascendingLiveDates.Any(_ => _.Kind != DateTimeKind.Utc))
            {
                throw new ArgumentException("All dates must be UTC", "ascendingLiveDates");
            }

            if (ascendingLiveDates.First() <= now)
            {
                throw new ArgumentException("All dates must be in future", "ascendingLiveDates");
            }

            ascendingLiveDates.Aggregate((previous, current) =>
            {
                if (previous >= current)
                {
                    throw new ArgumentException("Must be in ascending order with no duplicates", "ascendingLiveDates");
                }

                return(current);
            });

            var parameters = new DynamicParameters(new
            {
                QueueId = queueId.Value,
                Now     = now
            });

            var sql = new StringBuilder();

            sql.AppendLine(SqlPreInserts);
            for (var i = 0; i < ascendingLiveDates.Count; i++)
            {
                var rowNumber = i + 1; // Need to match the output of ROW_NUMBER, which is 1-based.
                sql.Append("INSERT INTO #NewLiveDates VALUES (@LiveDate");
                sql.Append(rowNumber);
                sql.Append(", ");
                sql.Append(rowNumber);
                sql.AppendLine(");");

                var liveDate = ascendingLiveDates[i];
                parameters.Add("LiveDate" + rowNumber, liveDate);
            }

            sql.AppendLine(SqlPostInserts);

            using (var connection = this.connectionFactory.CreateConnection())
            {
                var queueOverflow = await connection.ExecuteScalarAsync <int>(sql.ToString(), parameters);

                if (queueOverflow != -1)
                {
                    throw new ArgumentException(
                              string.Format(
                                  "Insufficient quantity of live dates provided. Given {0}. Required at least {1}.",
                                  ascendingLiveDates.Count,
                                  queueOverflow),
                              "ascendingLiveDates");
                }
            }
        }