Ejemplo n.º 1
0
        /// <summary>
        /// Returns the next message, if any.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="connectionHolder">The connection.</param>
        /// <param name="noMessageFoundActon">The no message found action.</param>
        /// <param name="routes">The routes.</param>
        /// <returns>
        /// A message if one is found; null otherwise
        /// </returns>
        public async Task <IReceivedMessageInternal> GetMessageAsync(IMessageContext context, IConnectionHolder <NpgsqlConnection, NpgsqlTransaction, NpgsqlCommand> connectionHolder,
                                                                     Action <IConnectionHolder <NpgsqlConnection, NpgsqlTransaction, NpgsqlCommand> > noMessageFoundActon, List <string> routes)
        {
            //if stopping, exit now
            if (_cancelToken.Tokens.Any(t => t.IsCancellationRequested))
            {
                noMessageFoundActon(connectionHolder);
                return(null);
            }

            //ask for the next message, or a specific message if we have a messageID
            var receivedTransportMessage = await
                                           _receiveMessageAsync.Handle(new ReceiveMessageQueryAsync <NpgsqlConnection, NpgsqlTransaction>(connectionHolder.Connection,
                                                                                                                                          connectionHolder.Transaction, routes)).ConfigureAwait(false);

            return(ProcessMessage(receivedTransportMessage, connectionHolder, context, noMessageFoundActon));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Returns the next message, if any.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="connectionHolder">The connection.</param>
        /// <param name="noMessageFoundActon">The no message found action.</param>
        /// <param name="routes">The routes.</param>
        /// <returns>
        /// A message if one is found; null otherwise
        /// </returns>
        public IReceivedMessageInternal GetMessage(IMessageContext context, IConnectionHolder <NpgsqlConnection, NpgsqlTransaction, NpgsqlCommand> connectionHolder,
                                                   Action <IConnectionHolder <NpgsqlConnection, NpgsqlTransaction, NpgsqlCommand> > noMessageFoundActon, List <string> routes)
        {
            //if stopping, exit now
            if (_cancelToken.Tokens.Any(t => t.IsCancellationRequested))
            {
                noMessageFoundActon(connectionHolder);
                return(null);
            }

            //ask for the next message
            var receivedTransportMessage =
                _receiveMessage.Handle(new ReceiveMessageQuery <NpgsqlConnection, NpgsqlTransaction>(connectionHolder.Connection,
                                                                                                     connectionHolder.Transaction, routes));

            return(ProcessMessage(receivedTransportMessage, connectionHolder, context, noMessageFoundActon));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Returns the next message, if any.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="connectionHolder">The connection.</param>
        /// <param name="noMessageFoundActon">The no message found action.</param>
        /// <returns>
        /// A message if one is found; null otherwise
        /// </returns>
        public IReceivedMessageInternal GetMessage(IMessageContext context, IConnectionHolder <SqlConnection, SqlTransaction, SqlCommand> connectionHolder,
                                                   Action <IConnectionHolder <SqlConnection, SqlTransaction, SqlCommand> > noMessageFoundActon)
        {
            //if stopping, exit now
            if (_cancelToken.Tokens.Any(t => t.IsCancellationRequested))
            {
                noMessageFoundActon(connectionHolder);
                return(null);
            }

            //ask for the next message
            var receivedTransportMessage =
                _receiveMessage.Handle(new ReceiveMessageQuery <SqlConnection, SqlTransaction>(connectionHolder.Connection,
                                                                                               connectionHolder.Transaction, _configuration.Routes));

            //if no message (null) run the no message action and return
            if (receivedTransportMessage == null)
            {
                noMessageFoundActon(connectionHolder);
                return(null);
            }

            //set the message ID on the context for later usage
            context.SetMessageAndHeaders(receivedTransportMessage.MessageId, receivedTransportMessage.Headers);

            //if we are holding open transactions, we need to update the status table in a separate call
            //When not using held transactions, this is part of the de-queue statement and so not needed here

            //TODO - we could consider using a task to update the status table
            //the status table drives nothing internally, however it may drive external processes
            //because of that, we are not returning the message until the status table is updated.
            //we could make this a configurable option in the future?
            if (_configuration.Options().EnableHoldTransactionUntilMessageCommitted&&
                _configuration.Options().EnableStatusTable)
            {
                _setStatusCommandHandler.Handle(
                    new SetStatusTableStatusCommand(
                        (long)receivedTransportMessage.MessageId.Id.Value, QueueStatuses.Processing));
            }
            return(receivedTransportMessage);
        }
        /// <summary>
        /// Handles the specified command.
        /// </summary>
        /// <param name="commandSend">The command.</param>
        /// <returns></returns>
        /// <exception cref="DotNetWorkQueueException">Failed to insert record - the ID of the new record returned by SQLite was 0</exception>
        public async Task <long> HandleAsync(SendMessageCommand commandSend)
        {
            if (!_databaseExists.Exists(_configurationSend.ConnectionInfo.ConnectionString))
            {
                return(0);
            }

            if (!_messageExpirationEnabled.HasValue)
            {
                _messageExpirationEnabled = _options.Value.EnableMessageExpiration;
            }

            using (var connection = _dbFactory.CreateConnection(_configurationSend.ConnectionInfo.ConnectionString, false))
            {
                connection.Open();

                var expiration = TimeSpan.Zero;
                if (_messageExpirationEnabled.Value)
                {
                    expiration = MessageExpiration.GetExpiration(commandSend, data => data.GetExpiration());
                }

                var jobName       = _jobSchedulerMetaData.GetJobName(commandSend.MessageData);
                var scheduledTime = DateTimeOffset.MinValue;
                var eventTime     = DateTimeOffset.MinValue;
                if (!string.IsNullOrWhiteSpace(jobName))
                {
                    scheduledTime = _jobSchedulerMetaData.GetScheduledTime(commandSend.MessageData);
                    eventTime     = _jobSchedulerMetaData.GetEventTime(commandSend.MessageData);
                }

                IDbCommand commandStatus = null;
                using (var command = SendMessage.GetMainCommand(commandSend, connection, _commandCache, _headers, _serializer))
                {
                    long id;
                    using (var commandMeta = SendMessage.CreateMetaDataRecord(commandSend.MessageData.GetDelay(), expiration,
                                                                              connection, commandSend.MessageToSend, commandSend.MessageData, _tableNameHelper, _headers,
                                                                              _options.Value, _getTime))
                    {
                        if (_options.Value.EnableStatusTable)
                        {
                            commandStatus = CreateStatusRecord(connection, commandSend.MessageToSend,
                                                               commandSend.MessageData);
                        }

                        using (var trans = _dbFactory.CreateTransaction(connection).BeginTransaction())
                        {
                            try
                            {
                                if (string.IsNullOrWhiteSpace(jobName) ||
                                    _jobExistsHandler.Handle(new DoesJobExistQuery <IDbConnection, IDbTransaction>(jobName, scheduledTime, connection,
                                                                                                                   trans)) ==
                                    QueueStatuses.NotQueued)
                                {
                                    command.Transaction = trans;
                                    await _readerAsync.ExecuteNonQueryAsync(command).ConfigureAwait(false);

                                    var commandId = connection.CreateCommand();
                                    commandId.Transaction = trans;
                                    commandId.CommandText = "SELECT last_insert_rowid();";
                                    id = Convert.ToInt64(await _readerAsync.ExecuteScalarAsync(commandId).ConfigureAwait(false));
                                    if (id > 0)
                                    {
                                        commandMeta.Transaction = trans;
                                        var param = commandMeta.CreateParameter();
                                        param.ParameterName = "@QueueID";
                                        param.DbType        = DbType.Int64;
                                        param.Value         = id;
                                        commandMeta.Parameters.Add(param);
                                        await _readerAsync.ExecuteNonQueryAsync(commandMeta).ConfigureAwait(false);

                                        if (commandStatus != null)
                                        {
                                            commandStatus.Transaction = trans;

                                            param = commandStatus.CreateParameter();
                                            param.ParameterName = "@QueueID";
                                            param.DbType        = DbType.Int64;
                                            param.Value         = id;
                                            commandStatus.Parameters.Add(param);

                                            await _readerAsync.ExecuteNonQueryAsync(commandStatus).ConfigureAwait(false);
                                        }
                                        if (!string.IsNullOrWhiteSpace(jobName))
                                        {
                                            _sendJobStatus.Handle(new SetJobLastKnownEventCommand <IDbConnection, IDbTransaction>(jobName, eventTime,
                                                                                                                                  scheduledTime, connection, trans));
                                        }
                                        trans.Commit();
                                    }
                                    else
                                    {
                                        throw new DotNetWorkQueueException(
                                                  "Failed to insert record - the ID of the new record returned by SQLite was 0");
                                    }
                                }
                                else
                                {
                                    throw new DotNetWorkQueueException(
                                              "Failed to insert record - the job has already been queued or processed");
                                }
                            }
                            finally
                            {
                                commandStatus?.Dispose();
                            }
                        }
                    }
                    return(id);
                }
            }
        }
        /// <inheritdoc />
        public async Task <long> HandleAsync(SendMessageCommand commandSend)
        {
            if (!_messageExpirationEnabled.HasValue)
            {
                _messageExpirationEnabled = _options.Value.EnableMessageExpiration;
            }

            var jobName       = _jobSchedulerMetaData.GetJobName(commandSend.MessageData);
            var scheduledTime = DateTimeOffset.MinValue;
            var eventTime     = DateTimeOffset.MinValue;

            if (!string.IsNullOrWhiteSpace(jobName))
            {
                scheduledTime = _jobSchedulerMetaData.GetScheduledTime(commandSend.MessageData);
                eventTime     = _jobSchedulerMetaData.GetEventTime(commandSend.MessageData);
            }

            using (var connection = new NpgsqlConnection(_configurationSend.ConnectionInfo.ConnectionString))
            {
                connection.Open();
                using (var trans = connection.BeginTransaction())
                {
                    if (string.IsNullOrWhiteSpace(jobName) || _jobExistsHandler.Handle(new DoesJobExistQuery <NpgsqlConnection, NpgsqlTransaction>(jobName, scheduledTime, connection, trans)) ==
                        QueueStatuses.NotQueued)
                    {
                        using (var command = connection.CreateCommand())
                        {
                            command.CommandText = _commandCache.GetCommand(CommandStringTypes.InsertMessageBody);
                            command.Transaction = trans;
                            var serialization =
                                _serializer.Serializer.MessageToBytes(new MessageBody
                            {
                                Body = commandSend.MessageToSend.Body
                            }, commandSend.MessageToSend.Headers);

                            command.Parameters.Add("@body", NpgsqlDbType.Bytea, -1);
                            command.Parameters["@body"].Value = serialization.Output;

                            commandSend.MessageToSend.SetHeader(_headers.StandardHeaders.MessageInterceptorGraph,
                                                                serialization.Graph);

                            command.Parameters.Add("@headers", NpgsqlDbType.Bytea, -1);
                            command.Parameters["@headers"].Value =
                                _serializer.InternalSerializer.ConvertToBytes(commandSend.MessageToSend.Headers);

                            var id = Convert.ToInt64(await command.ExecuteScalarAsync().ConfigureAwait(false));
                            if (id > 0)
                            {
                                var expiration = TimeSpan.Zero;
                                if (_messageExpirationEnabled.Value)
                                {
                                    expiration = MessageExpiration.GetExpiration(commandSend, data => data.GetExpiration());
                                }

                                await
                                CreateMetaDataRecordAsync(commandSend.MessageData.GetDelay(), expiration, connection,
                                                          id,
                                                          commandSend.MessageToSend, commandSend.MessageData, trans, _getTime.GetCurrentUtcDate()).ConfigureAwait(false);

                                if (_options.Value.EnableStatusTable)
                                {
                                    await
                                    CreateStatusRecordAsync(connection, id, commandSend.MessageToSend,
                                                            commandSend.MessageData, trans).ConfigureAwait(false);
                                }

                                if (!string.IsNullOrWhiteSpace(jobName))
                                {
                                    _sendJobStatus.Handle(new SetJobLastKnownEventCommand <NpgsqlConnection, NpgsqlTransaction>(jobName, eventTime,
                                                                                                                                scheduledTime, connection, trans));
                                }
                            }
                            else
                            {
                                throw new DotNetWorkQueueException(
                                          "Failed to insert record - the ID of the new record returned by the server was 0");
                            }
                            trans.Commit();
                            return(id);
                        }
                    }
                    throw new DotNetWorkQueueException(
                              "Failed to insert record - the job has already been queued or processed");
                }
            }
        }