/// <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(); } } }
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); }