/// <summary>
        /// Handles the specified query.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <returns></returns>
        /// <exception cref="PoisonMessageException">An error has occured trying to re-assemble a message de-queued from SQLite</exception>
        /// <exception cref="MessageQueueId"></exception>
        public async Task <IReceivedMessageInternal> Handle(ReceiveMessageQueryAsync <IDbConnection, IDbTransaction> query)
        {
            if (!_databaseExists.Exists(_connectionInformation.ConnectionString))
            {
                return(null);
            }

            using (var connection = _dbFactory.CreateConnection(_connectionInformation.ConnectionString, false))
            {
                connection.Open();
                using (var transaction = _dbFactory.CreateTransaction(connection).BeginTransaction())
                {
                    using (var selectCommand = connection.CreateCommand())
                    {
                        selectCommand.Transaction = transaction;
                        CommandString commandString =
                            GetDeQueueCommand(_tableNameHelper.MetaDataName, _tableNameHelper.QueueName,
                                              _tableNameHelper.StatusName, query.Routes);

                        if (commandString == null)
                        {
                            throw new DotNetWorkQueueException("Failed to generate command text for de-queue of messages");
                        }

                        _buildDequeueCommand.BuildCommand(selectCommand, commandString, _options.Value, query.Routes);
                        using (var reader = await _readerAsync.ExecuteReaderAsync(selectCommand).ConfigureAwait(false))
                        {
                            return(_messageDeQueue.HandleMessage(connection, transaction, reader, commandString));
                        }
                    }
                }
            }
        }
Example #2
0
        public QueueCreationResult Handle(CreateQueueTablesAndSaveConfigurationCommand <ITable> command)
        {
            if (!_databaseExists.Exists(_connectionInformation.ConnectionString))
            { //no db file, create
                var fileName = _getFileNameFromConnection.GetFileName(_connectionInformation.ConnectionString);
                using (File.Create(fileName.FileName))
                {
                }
            }

            try
            {
                return(_decorated.Handle(command));
            }
            //if the queue already exists, return that status; otherwise, bubble the error
            catch (SQLiteException error)
            {
                if (error.ResultCode == SQLiteErrorCode.Error && error.Message.Contains("table") && error.Message.Contains("already exists"))
                {
                    return(new QueueCreationResult(QueueCreationStatus.AttemptedToCreateAlreadyExists));
                }
                throw new DotNetWorkQueueException("Failed to create table",
                                                   error);
            }
        }
Example #3
0
        /// <summary>
        /// Handles the specified query.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <returns></returns>
        public IReceivedMessageInternal Handle(ReceiveMessageQuery <IDbConnection, IDbTransaction> query)
        {
            if (!_databaseExists.Exists(_connectionInformation.ConnectionString))
            {
                return(null);
            }

            using (var connection = _dbFactory.CreateConnection(_connectionInformation.ConnectionString, false))
            {
                connection.Open();
                using (var transaction = _dbFactory.CreateTransaction(connection).BeginTransaction())
                {
                    using (var selectCommand = connection.CreateCommand())
                    {
                        selectCommand.Transaction = transaction;
                        CommandString commandString =
                            GetDeQueueCommand(_tableNameHelper.MetaDataName, _tableNameHelper.QueueName,
                                              _tableNameHelper.StatusName, query.Routes);

                        _buildDequeueCommand.BuildCommand(selectCommand, commandString, _options.Value, query.Routes);
                        using (var reader = selectCommand.ExecuteReader())
                        {
                            return(_messageDeQueue.HandleMessage(connection, transaction, reader, commandString));
                        }
                    }
                }
            }
        }
Example #4
0
 /// <summary>
 /// Handles the specified command.
 /// </summary>
 /// <param name="command">The command.</param>
 public void Handle(SetErrorCountCommand command)
 {
     if (!_databaseExists.Exists(_connectionInformation.ConnectionString))
     {
         return;
     }
     _decorated.Handle(command);
 }
Example #5
0
 /// <inheritdoc />
 public void Handle(DeleteStatusTableStatusCommand command)
 {
     if (!_databaseExists.Exists(_connectionInformation.ConnectionString))
     {
         return;
     }
     _decorated.Handle(command);
 }
 /// <summary>
 /// Handles the specified command.
 /// </summary>
 /// <param name="command">The command.</param>
 public void Handle(MoveRecordToErrorQueueCommand command)
 {
     if (!_databaseExists.Exists(_connectionInformation.ConnectionString))
     {
         return;
     }
     _decorated.Handle(command);
 }
        /// <summary>
        /// Handles the specified query.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <returns></returns>
        public IReceivedMessageInternal Handle(ReceiveMessageQuery query)
        {
            if (!_databaseExists.Exists())
            {
                return(null);
            }

            //ensure created
            if (!_options.IsValueCreated)
            {
                _options.Value.ValidConfiguration();
            }

            using (var db = _connectionInformation.GetDatabase())
            {
                lock (Reader)                 //we have to enforce a single de-queue action per process, as BeginTrans does not block in direct or memory mode
                {
                    db.Database.BeginTrans(); //will block in shared mode, but not direct or memory
                    try
                    {
                        var record = DequeueRecord(query, db.Database);
                        if (record != null)
                        {
                            return(_messageDeQueue.HandleMessage(record.Item1, record.Item2.QueueId,
                                                                 record.Item2.CorrelationId));
                        }
                    }
                    finally
                    {
                        db.Database.Commit();
                    }
                }
            }

            return(null);
        }
        /// <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 long Handle(SendMessageCommand commandSend)
        {
            if (!_databaseExists.Exists(_configurationSend.ConnectionInfo.ConnectionString))
            {
                return(0);
            }

            if (!_messageExpirationEnabled.HasValue)
            {
                _messageExpirationEnabled = _options.Value.EnableMessageExpiration ||
                                            _options.Value.QueueType == QueueTypes.RpcReceive ||
                                            _options.Value.QueueType == QueueTypes.RpcSend;
            }

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

                var expiration = TimeSpan.Zero;
                if (_messageExpirationEnabled.Value)
                {
                    expiration = MessageExpiration.GetExpiration(commandSend, _headers, 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;
                                    command.ExecuteNonQuery();
                                    var commandId = connection.CreateCommand();
                                    commandId.Transaction = trans;
                                    commandId.CommandText = "SELECT last_insert_rowid();";
                                    id = Convert.ToInt64(commandId.ExecuteScalar());
                                    if (id > 0)
                                    {
                                        commandMeta.Transaction = trans;

                                        var param = commandMeta.CreateParameter();
                                        param.ParameterName = "@QueueID";
                                        param.DbType        = DbType.Int64;
                                        param.Value         = id;
                                        commandMeta.Parameters.Add(param);
                                        commandMeta.ExecuteNonQuery();
                                        if (commandStatus != null)
                                        {
                                            commandStatus.Transaction = trans;

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

                                        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);
                }
            }
        }
 /// <summary>
 /// Handles the specified query.
 /// </summary>
 /// <param name="query">The query.</param>
 /// <returns></returns>
 public List <string> Handle(GetColumnNamesFromTableQuery query)
 {
     return(!_databaseExists.Exists(_connectionInformation.ConnectionString) ? new List <string>(0) : _decorated.Handle(query));
 }
Example #10
0
 /// <inheritdoc />
 public long Handle(DeleteMessageCommand command)
 {
     return(!_databaseExists.Exists(_connectionInformation.ConnectionString) ? 0 : _decorated.Handle(command));
 }
 /// <summary>
 /// Handles the specified command.
 /// </summary>
 /// <param name="command">The command.</param>
 /// <returns></returns>
 public long Handle(ResetHeartBeatCommand <long> command)
 {
     return(!_databaseExists.Exists(_connectionInformation.ConnectionString) ? 0 : _decorated.Handle(command));
 }
 /// <summary>
 /// Handles the specified query.
 /// </summary>
 /// <param name="query">The query.</param>
 /// <returns></returns>
 public bool Handle(GetTableExistsQuery query)
 {
     return(_databaseExists.Exists(_connectionInformation.ConnectionString) && _decorated.Handle(query));
 }
Example #13
0
 /// <summary>
 /// Handles the specified query.
 /// </summary>
 /// <param name="query">The query.</param>
 /// <returns></returns>
 public IEnumerable <MessageToReset <long> > Handle(FindMessagesToResetByHeartBeatQuery <long> query)
 {
     return(!_databaseExists.Exists(_connectionInformation.ConnectionString) ? Enumerable.Empty <MessageToReset <long> >() : _decorated.Handle(query));
 }
Example #14
0
 /// <summary>
 /// Handles the specified query.
 /// </summary>
 /// <param name="query">The query.</param>
 /// <returns></returns>
 public IEnumerable <long> Handle(FindExpiredMessagesToDeleteQuery query)
 {
     return(!_databaseExists.Exists(_connectionInformation.ConnectionString) ? Enumerable.Empty <long>() : _decorated.Handle(query));
 }
Example #15
0
        /// <summary>
        /// Handles the specified rollback command.
        /// </summary>
        /// <param name="rollBackCommand">The rollBackCommand.</param>
        public void Handle(RollbackMessageCommand <int> rollBackCommand)
        {
            if (!_databaseExists.Exists())
            {
                return;
            }

            using (var db = _connectionInformation.GetDatabase())
            {
                db.Database.BeginTrans();
                try
                {
                    var col = db.Database.GetCollection <Schema.MetaDataTable>(_tableNameHelper.MetaDataName);

                    var results2 = col.Query()
                                   .Where(x => x.QueueId.Equals(rollBackCommand.QueueId))
                                   .Limit(1)
                                   .ToList();

                    if (results2 != null && results2.Count == 1)
                    {
                        var record = results2[0];
                        if (record != null)
                        {
                            var process = true;
                            if (rollBackCommand.LastHeartBeat.HasValue)
                            {
                                //heartbeat must match
                                if (TrimMilliseconds(record.HeartBeat) !=
                                    TrimMilliseconds(rollBackCommand.LastHeartBeat))
                                {
                                    process = false;
                                }
                            }

                            if (process)
                            {
                                if (_options.Value.EnableDelayedProcessing &&
                                    rollBackCommand.IncreaseQueueDelay.HasValue)
                                {
                                    var dtUtcDate          = _getUtcDateQuery.Create().GetCurrentUtcDate();
                                    var dtUtcDateIncreased = dtUtcDate.Add(rollBackCommand.IncreaseQueueDelay.Value);

                                    //move to future
                                    record.QueueProcessTime = dtUtcDateIncreased;
                                }

                                if (_options.Value.EnableHeartBeat)
                                {
                                    record.HeartBeat = null;
                                }

                                record.Status = QueueStatuses.Waiting;

                                col.Update(record);

                                if (_options.Value.EnableStatusTable)
                                {
                                    var statusCol = db.Database.GetCollection <Schema.StatusTable>(_tableNameHelper.StatusName);
                                    var results   = statusCol.Query()
                                                    .Where(x => x.QueueId.Equals(record.QueueId))
                                                    .Limit(1)
                                                    .ToList();

                                    if (results.Count == 1)
                                    {
                                        var statusRecord = results[0];
                                        statusRecord.Status = record.Status;
                                        statusCol.Update(statusRecord);
                                    }
                                }
                            }
                        }
                    }

                    db.Database.Commit();
                }
                catch
                {
                    db.Database.Rollback();
                    throw;
                }
            }
        }
        public void Handle(RollbackMessageCommand <long> rollBackCommand)
        {
            if (!_databaseExists.Exists(_connectionInformation.ConnectionString))
            {
                return;
            }

            SetupSql();
            using (var connection = _dbFactory.CreateConnection(_connectionInformation.ConnectionString, false))
            {
                connection.Open();
                using (var trans = _dbFactory.CreateTransaction(connection).BeginTransaction())
                {
                    using (var command = connection.CreateCommand())
                    {
                        command.Transaction = trans;

                        var param = command.CreateParameter();
                        param.ParameterName = "@QueueID";
                        param.DbType        = DbType.Int64;
                        param.Value         = rollBackCommand.QueueId;
                        command.Parameters.Add(param);

                        if (_options.Value.EnableDelayedProcessing && rollBackCommand.IncreaseQueueDelay.HasValue)
                        {
                            if (rollBackCommand.LastHeartBeat.HasValue)
                            {
                                command.CommandText = GetRollbackSql(false, true);

                                param = command.CreateParameter();
                                param.ParameterName = "@HeartBeat";
                                param.DbType        = DbType.DateTime2;
                                param.Value         = rollBackCommand.LastHeartBeat.Value.Ticks;
                                command.Parameters.Add(param);
                            }
                            else
                            {
                                command.CommandText = GetRollbackSql(true, false);
                            }

                            var dtUtcDate          = _getUtcDateQuery.Create().GetCurrentUtcDate();
                            var dtUtcDateIncreased = dtUtcDate.Add(rollBackCommand.IncreaseQueueDelay.Value);

                            param = command.CreateParameter();
                            param.ParameterName = "@QueueProcessTime";
                            param.DbType        = DbType.DateTime2;
                            param.Value         = dtUtcDateIncreased.Ticks;
                            command.Parameters.Add(param);
                        }
                        else
                        {
                            if (rollBackCommand.LastHeartBeat.HasValue)
                            {
                                command.CommandText = GetRollbackSql(false, true);
                                param = command.CreateParameter();
                                param.ParameterName = "@HeartBeat";
                                param.DbType        = DbType.DateTime2;
                                param.Value         = rollBackCommand.LastHeartBeat.Value.Ticks;
                                command.Parameters.Add(param);
                            }
                            else
                            {
                                command.CommandText = GetRollbackSql(false, false);
                            }
                        }
                        command.ExecuteNonQuery();
                    }

                    if (_options.Value.EnableStatusTable)
                    {
                        using (var command = connection.CreateCommand())
                        {
                            command.Transaction = trans;
                            var param = command.CreateParameter();
                            param.ParameterName = "@QueueID";
                            param.DbType        = DbType.Int64;
                            param.Value         = rollBackCommand.QueueId;
                            command.Parameters.Add(param);

                            param = command.CreateParameter();
                            param.ParameterName = "@Status";
                            param.DbType        = DbType.Int32;
                            param.Value         = Convert.ToInt16(QueueStatuses.Waiting);
                            command.Parameters.Add(param);

                            command.CommandText =
                                _commandCache.GetCommand(CommandStringTypes.UpdateStatusRecord);
                            command.ExecuteNonQuery();
                        }
                    }
                    trans.Commit();
                }
            }
        }
 /// <summary>
 /// Handles the specified query.
 /// </summary>
 /// <param name="query">The query.</param>
 /// <returns></returns>
 public bool Handle(GetErrorRecordExistsQuery <long> query)
 {
     return(_databaseExists.Exists(_connectionInformation.ConnectionString) && _decorated.Handle(query));
 }
 /// <summary>
 /// Handles the specified query.
 /// </summary>
 /// <param name="query">The query.</param>
 /// <returns></returns>
 public QueueStatuses Handle(DoesJobExistQuery <IDbConnection, IDbTransaction> query)
 {
     return(!_databaseExists.Exists(_connectionInformation.ConnectionString) ? QueueStatuses.NotQueued : _decorated.Handle(query));
 }
 /// <summary>
 /// Handles the specified command.
 /// </summary>
 /// <param name="command">The command.</param>
 /// <returns></returns>
 public QueueRemoveResult Handle(DeleteQueueTablesCommand command)
 {
     return(!_databaseExists.Exists(_connectionInformation.ConnectionString) ? new QueueRemoveResult(QueueRemoveStatus.DoesNotExist) : _decorated.Handle(command));
 }
        /// <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 <int> HandleAsync(SendMessageCommand commandSend)
        {
            return(await Task.Run(() => //hack until litedb adds async methods
            {
                if (!_databaseExists.Exists())
                {
                    return 0;
                }

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


                TimeSpan?expiration = null;
                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);
                }

                int id = 0;
                using (var db = _connectionInformation.GetDatabase())
                {
                    lock (Locker) //we need to block due to jobs
                    {
                        try
                        {
                            db.Database.BeginTrans(); //only blocks on shared connections
                            if (string.IsNullOrWhiteSpace(jobName) || _jobExistsHandler.Handle(
                                    new DoesJobExistQuery(jobName, scheduledTime, db.Database)) ==
                                QueueStatuses.NotQueued)
                            {
                                var serialization =
                                    _serializer.Serializer.MessageToBytes(
                                        new MessageBody {
                                    Body = commandSend.MessageToSend.Body
                                },
                                        commandSend.MessageToSend.Headers);

                                //create queue
                                var queueData = new LiteDb.Schema.QueueTable()
                                {
                                    Body = serialization.Output
                                };
                                commandSend.MessageToSend.SetHeader(_headers.StandardHeaders.MessageInterceptorGraph,
                                                                    serialization.Graph);
                                queueData.Headers =
                                    _serializer.InternalSerializer.ConvertToBytes(commandSend.MessageToSend.Headers);

                                var col = db.Database.GetCollection <QueueTable>(_tableNameHelper.QueueName);
                                id = col.Insert(queueData).AsInt32;

                                //create metadata
                                var metaData = new LiteDb.Schema.MetaDataTable
                                {
                                    QueueId = id,
                                    CorrelationId = (Guid)commandSend.MessageData.CorrelationId.Id.Value,
                                    QueuedDateTime = DateTime.UtcNow
                                };

                                if (!string.IsNullOrWhiteSpace(jobName))
                                {
                                    metaData.QueueProcessTime = scheduledTime.UtcDateTime;
                                }
                                else if (_options.Value.EnableDelayedProcessing)
                                {
                                    var delay = commandSend.MessageData.GetDelay();
                                    if (delay.HasValue)
                                    {
                                        metaData.QueueProcessTime = DateTime.UtcNow.Add(delay.Value);
                                    }
                                }

                                if (_options.Value.EnableMessageExpiration && expiration.HasValue)
                                {
                                    metaData.ExpirationTime = DateTime.UtcNow.Add(expiration.Value);
                                }

                                if (_options.Value.EnableStatus)
                                {
                                    metaData.Status = QueueStatuses.Waiting;
                                }

                                if (_options.Value.EnableRoute)
                                {
                                    metaData.Route = commandSend.MessageData.Route;
                                }

                                var colMeta = db.Database.GetCollection <MetaDataTable>(_tableNameHelper.MetaDataName);
                                colMeta.Insert(metaData);

                                //create status table record
                                if (_options.Value.EnableStatusTable || !string.IsNullOrWhiteSpace(jobName))
                                {
                                    var statusData = new LiteDb.Schema.StatusTable()
                                    {
                                        Status = metaData.Status,
                                        CorrelationId = metaData.CorrelationId,
                                        QueueId = id
                                    };
                                    if (!string.IsNullOrWhiteSpace(jobName))
                                    {
                                        statusData.JobName = jobName;
                                    }
                                    var colStatus = db.Database.GetCollection <StatusTable>(_tableNameHelper.StatusName);
                                    colStatus.Insert(statusData);
                                }

                                //job name
                                if (!string.IsNullOrWhiteSpace(jobName))
                                {
                                    _sendJobStatus.Handle(new SetJobLastKnownEventCommand(jobName, eventTime,
                                                                                          scheduledTime, db.Database));
                                }
                            }
                            else
                            {
                                throw new DotNetWorkQueueException(
                                    "Failed to insert record - the job has already been queued or processed");
                            }

                            db.Database.Commit();
                        }
                        catch
                        {
                            db.Database.Rollback();
                            throw;
                        }
                    }
                }

                return id;
            }));
        }