Beispiel #1
0
        /// <summary>
        /// Enqueues the specified message.
        /// </summary>
        /// <param name="messageDescriptors">The <see cref="IEnumerable{T}">sequence</see> of <see cref="IMessageDescriptor">message descriptors</see> to enqueue.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken">token</see> that can be used to cancel the operation.</param>
        /// <returns>A <see cref="Task">task</see> representing the asynchronous operation.</returns>
        protected virtual async Task Enqueue(IEnumerable <IMessageDescriptor> messageDescriptors, CancellationToken cancellationToken)
        {
            Arg.NotNull(messageDescriptors, nameof(messageDescriptors));

            var clock       = Configuration.Clock;
            var enqueueTime = clock.Now.UtcDateTime;

            using (var connection = Configuration.CreateConnection())
            {
                await connection.OpenAsync(cancellationToken).ConfigureAwait(false);

                using (var transaction = connection.BeginTransaction())
                {
                    foreach (var messageDescriptor in messageDescriptors)
                    {
                        var item = new SqlMessageQueueItem()
                        {
                            EnqueueTime = enqueueTime,
                            DueTime     = messageDescriptor.Options.GetDeliveryTime(clock).UtcDateTime,
                            MessageType = messageDescriptor.MessageType,
                            Revision    = messageDescriptor.Message.Revision,
                            Message     = messageSerializer.Serialize(messageDescriptor.Message),
                            Transaction = transaction,
                        };

                        await Configuration.Enqueue(connection, item, cancellationToken).ConfigureAwait(false);
                    }

                    transaction.Commit();
                }
            }
        }
Beispiel #2
0
        internal SqlDequeueOperation(SqlMessageQueueItem item, DbTransaction transaction)
        {
            Contract.Requires(item != null);
            Contract.Requires(transaction != null);

            Item             = item;
            this.transaction = transaction;
        }
        /// <summary>
        /// Dequeues a single item using the specified connection.
        /// </summary>
        /// <param name="connection">The <see cref="DbConnection">connection</see> to dequeue an item with.</param>
        /// <param name="subscriptionId">The associated subscription identifier.</param>
        /// <param name="dueTime">The due <see cref="DateTimeOffset">date and time</see> for the next item to be dequeued.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken">token</see> that can be used to cancel the operation.</param>
        /// <returns>A <see cref="Task{TResult}">task</see> containing the <see cref="ISqlDequeueOperation">dequeue operation</see>.</returns>
        public virtual async Task <ISqlDequeueOperation> Dequeue(DbConnection connection, Guid subscriptionId, DateTimeOffset dueTime, CancellationToken cancellationToken)
        {
            Arg.NotNull(connection, nameof(connection));
            Contract.Ensures(Contract.Result <Task <ISqlDequeueOperation> >() != null);

            using (var command = connection.CreateCommand())
            {
                var parameter = command.CreateParameter();

                parameter.DbType        = DbType.Guid;
                parameter.ParameterName = "SubscriptionId";
                parameter.Value         = subscriptionId;
                command.Parameters.Add(parameter);

                parameter               = command.CreateParameter();
                parameter.DbType        = DbType.DateTime2;
                parameter.ParameterName = "DueTime";
                parameter.Value         = dueTime.UtcDateTime;
                command.Parameters.Add(parameter);

                command.CommandText = Sql.SubscriptionQueue.Dequeue;

                var transaction = connection.BeginTransaction();

                command.Transaction = transaction;

                using (var reader = await command.ExecuteReaderAsync(SingleRow, cancellationToken).ConfigureAwait(false))
                {
                    if (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
                    {
                        var item = new SqlMessageQueueItem()
                        {
                            SubscriptionId  = subscriptionId,
                            MessageId       = reader.GetGuid(0),
                            EnqueueTime     = reader.GetDateTime(1),
                            DequeueAttempts = reader.GetInt32(2),
                            DueTime         = reader.GetDateTime(3),
                            MessageType     = reader.GetString(4),
                            Revision        = reader.GetInt32(5),
                            Message         = reader.GetStream(6),
                            Transaction     = transaction,
                        };

                        return(new SqlDequeueOperation(item, transaction));
                    }
                }

                transaction.Commit();
                return(SqlDequeueOperation.Empty);
            }
        }
        /// <summary>
        /// Enqueues the specified item using the provided connection.
        /// </summary>
        /// <param name="connection">The <see cref="DbConnection">connection</see> to enqueue an item with.</param>
        /// <param name="item">The <see cref="SqlMessageQueueItem">item</see> to enqueue.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken">token</see> that can be used to cancel the operation.</param>
        /// <returns>A <see cref="Task">task</see> representing the asynchronous operation.</returns>
        public virtual async Task Enqueue(DbConnection connection, SqlMessageQueueItem item, CancellationToken cancellationToken)
        {
            Arg.NotNull(connection, nameof(connection));
            Arg.NotNull(item, nameof(item));

            using (var command = NewEnqueueCommand(newMessage: item.DequeueAttempts == 0))
            {
                command.Connection = connection;

                if (command.Transaction == null)
                {
                    command.Transaction = item.Transaction;
                }

                await Enqueue(command, item, cancellationToken).ConfigureAwait(false);
            }
        }
        /// <summary>
        /// Enqueues the specified item using the provided command.
        /// </summary>
        /// <param name="command">The <see cref="DbCommand">command</see> to enqueue an item with.</param>
        /// <param name="item">The <see cref="SqlMessageQueueItem">item</see> to enqueue.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken">token</see> that can be used to cancel the operation.</param>
        /// <returns>A <see cref="Task">task</see> representing the asynchronous operation.</returns>
        public virtual async Task Enqueue(DbCommand command, SqlMessageQueueItem item, CancellationToken cancellationToken)
        {
            Arg.NotNull(command, nameof(command));
            Arg.NotNull(item, nameof(item));

            command.Parameters["EnqueueTime"].Value = item.EnqueueTime;
            command.Parameters["DueTime"].Value     = item.DueTime;
            command.Parameters["Type"].Value        = item.MessageType;
            command.Parameters["Revision"].Value    = item.Revision;
            command.Parameters["Message"].Value     = item.Message;

            if (item.DequeueAttempts > 0)
            {
                command.Parameters["SubscriptionId"].Value  = item.SubscriptionId;
                command.Parameters["MessageId"].Value       = item.MessageId;
                command.Parameters["DequeueAttempts"].Value = item.DequeueAttempts;
            }

            await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
        }