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