/// <summary>
        /// Loads the metadata stored with the given ID
        /// </summary>
        public async Task <Dictionary <string, string> > ReadMetadata(string id)
        {
            var filePath         = GetFilePath(id, DataFileExtension);
            var metadataFilePath = GetFilePath(id, MetadataFileExtension);

            try
            {
                using (var fileStream = File.OpenRead(metadataFilePath))
                {
                    using (var reader = new StreamReader(fileStream, Encoding.UTF8))
                    {
                        var jsonText = await reader.ReadToEndAsync();

                        var metadata = _dictionarySerializer.DeserializeFromString(jsonText);

                        var fileInfo = new FileInfo(filePath);
                        metadata[MetadataKeys.Length] = fileInfo.Length.ToString();

                        return(metadata);
                    }
                }
            }
            catch (Exception exception)
            {
                throw new RebusApplicationException(exception, $"Could not read metadata for data with ID {id}");
            }
        }
        /// <summary>
        /// Gets due messages as of now, given the approximate due time that they were stored with when <see cref="M:Rebus.Timeouts.ITimeoutManager.Defer(System.DateTimeOffset,System.Collections.Generic.Dictionary{System.String,System.String},System.Byte[])" /> was called
        /// </summary>
        public async Task <DueMessagesResult> GetDueMessages()
        {
            var connection = _connectionHelper.GetConnection();

            try
            {
                using (var command = connection.CreateCommand())
                {
                    command.CommandText =
                        $@"
                        SELECT
                            id,
                            headers, 
                            body 

                        FROM {_tableName} 

                        WHERE due_time <= :current_time 

                        ORDER BY due_time
                        FOR UPDATE";
                    command.BindByName = true;
                    command.Parameters.Add(new OracleParameter("current_time", OracleDbType.TimeStampTZ, RebusTime.Now.ToUniversalTime().DateTime, ParameterDirection.Input));

                    using (var reader = await command.ExecuteReaderAsync())
                    {
                        var dueMessages = new List <DueMessage>();

                        while (reader.Read())
                        {
                            var id      = (long)reader["id"];
                            var headers = _dictionarySerializer.DeserializeFromString((string)reader["headers"]);
                            var body    = (byte[])reader["body"];

                            dueMessages.Add(new DueMessage(headers, body, async() =>
                            {
                                using (var deleteCommand = connection.CreateCommand())
                                {
                                    deleteCommand.BindByName  = true;
                                    deleteCommand.CommandText = $@"DELETE FROM {_tableName} WHERE id = :id";
                                    deleteCommand.Parameters.Add(new OracleParameter("id", OracleDbType.Int64, id, ParameterDirection.Input));
                                    await deleteCommand.ExecuteNonQueryAsync();
                                }
                            }));
                        }

                        return(new DueMessagesResult(dueMessages, async() =>
                        {
                            connection.Complete();
                            connection.Dispose();
                        }));
                    }
                }
            }
            catch (Exception)
            {
                connection.Dispose();
                throw;
            }
        }
        public IEnumerable <SagaDataSnapshot> GetAllSnapshots()
        {
            using (var connection = OracleTestHelper.ConnectionHelper.GetConnection().Result)
            {
                using (var command = connection.CreateCommand())
                {
                    command.CommandText = $@"SELECT data, metadata FROM {TableName}";

                    using (var reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            var data           = (byte[])reader["data"];
                            var metadataString = (string)reader["metadata"];

                            var objectSerializer     = new ObjectSerializer();
                            var dictionarySerializer = new DictionarySerializer();

                            var sagaData = objectSerializer.Deserialize(data);
                            var metadata = dictionarySerializer.DeserializeFromString(metadataString);

                            yield return(new SagaDataSnapshot
                            {
                                SagaData = (ISagaData)sagaData,
                                Metadata = metadata
                            });
                        }
                    }
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Gets due messages as of now, given the approximate due time that they were stored with when <see cref="M:Rebus.Timeouts.ITimeoutManager.Defer(System.DateTimeOffset,System.Collections.Generic.Dictionary{System.String,System.String},System.Byte[])" /> was called
        /// </summary>
        public async Task <DueMessagesResult> GetDueMessages()
        {
            var connection = await _connectionHelper.GetConnection();

            try
            {
                using (var command = connection.CreateCommand())
                {
                    command.CommandText =
                        $@"
                            SELECT `id`,`headers`,`body`
                            FROM `{_tableName}`
                            WHERE `due_time` <= @current_time
                            ORDER BY `due_time`
                            FOR UPDATE;";
                    command.Parameters.Add(command.CreateParameter("current_time", DbType.DateTime, _rebusTime.Now.ToUniversalTime().DateTime));

                    using (var reader = await command.ExecuteReaderAsync())
                    {
                        var dueMessages = new List <DueMessage>();

                        while (reader.Read())
                        {
                            var id      = (ulong)reader["id"];
                            var headers = _dictionarySerializer.DeserializeFromString((string)reader["headers"]);
                            var body    = (byte[])reader["body"];

                            dueMessages.Add(new DueMessage(headers, body, async() =>
                            {
                                if (connection != null)
                                {
                                    using (var deleteCommand = connection.CreateCommand())
                                    {
                                        deleteCommand.CommandText = $@"DELETE FROM `{_tableName}` WHERE `id` = @id";
                                        deleteCommand.Parameters.Add(command.CreateParameter("id", DbType.Int64, id));
                                        await deleteCommand.ExecuteNonQueryAsync();
                                    }
                                }
                            }));
                        }

                        return(new DueMessagesResult(dueMessages, async() =>
                        {
                            connection.Complete();
                            connection.Dispose();
                        }));
                    }
                }
            }
            catch (Exception)
            {
                connection.Dispose();
                throw;
            }
        }
        /// <summary>
        /// Gets due messages as of now, given the approximate due time that they were stored with when <see cref="M:Rebus.Timeouts.ITimeoutManager.Defer(System.DateTimeOffset,System.Collections.Generic.Dictionary{System.String,System.String},System.Byte[])" /> was called
        /// </summary>
        public Task <DueMessagesResult> GetDueMessages()
        {
            var connection = _connectionHelper.Open();

            try
            {
                using (var command = connection.CreateCommand())
                {
                    command.CommandText = $@"
                        SELECT id, headers, body 
                        FROM {_table} 
                        WHERE due_time <= :current_time 
                        ORDER BY due_time
                        FOR UPDATE";
                    command.Parameters.Add(new OracleParameter("current_time", _rebusTime.Now.ToOracleTimeStamp()));

                    using (var reader = command.ExecuteReader())
                    {
                        var dueMessages = new List <DueMessage>();

                        while (reader.Read())
                        {
                            var id      = (long)reader["id"];
                            var headers = _dictionarySerializer.DeserializeFromString((string)reader["headers"]);
                            var body    = (byte[])reader["body"];

                            dueMessages.Add(new DueMessage(headers, body, () =>
                            {
                                using (var deleteCommand = connection.CreateCommand())
                                {
                                    deleteCommand.CommandText = $@"DELETE FROM {_table} WHERE id = :id";
                                    deleteCommand.Parameters.Add(new OracleParameter("id", OracleDbType.Int64, id, ParameterDirection.Input));
                                    deleteCommand.ExecuteNonQuery();
                                    return(Task.CompletedTask);
                                }
                            }));
                        }

                        return(Task.FromResult(new DueMessagesResult(dueMessages, () =>
                        {
                            connection.Complete();
                            connection.Dispose();
                            return Task.CompletedTask;
                        })));
                    }
                }
            }
            catch (Exception)
            {
                connection.Dispose();
                throw;
            }
        }
    async Task UpdateLastReadTime(string id)
    {
        var metadataFilePath = GetFilePath(id, MetadataFileExtension);

        try
        {
            using (var file = File.Open(metadataFilePath, FileMode.Open, FileAccess.ReadWrite))
            {
                using (var reader = new StreamReader(file, Encoding.UTF8))
                {
                    var jsonText = await reader.ReadToEndAsync();

                    var metadata = _dictionarySerializer.DeserializeFromString(jsonText);

                    metadata[MetadataKeys.ReadTime] = _rebusTime.Now.ToString("O");

                    var newJsonText = _dictionarySerializer.SerializeToString(metadata);

                    file.Position = 0;

                    using (var writer = new StreamWriter(file, Encoding.UTF8))
                    {
                        await writer.WriteAsync(newJsonText);
                    }
                }
            }
        }
        catch (IOException)
        {
            // this exception is most likely caused by a locked file because someone else is updating the
            // last read time  - that's ok :)
        }
        catch (Exception exception)
        {
            throw new RebusApplicationException(exception, $"Could not update metadata for data with ID {id}");
        }
    }
        /// <summary>
        /// Loads the metadata stored with the given ID
        /// </summary>
        public async Task <Dictionary <string, string> > ReadMetadata(string id)
        {
            try
            {
                using (var connection = await _connectionProvider.GetConnection())
                {
                    using (var command = connection.CreateCommand())
                    {
                        command.CommandText = $"SELECT TOP 1 [Meta], [LastReadTime], DATALENGTH([Data]) AS 'Length' FROM {_tableName.QualifiedName} WITH (NOLOCK) WHERE [Id] = @id";
                        command.Parameters.Add("id", SqlDbType.VarChar, 200).Value = id;

                        using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false))
                        {
                            if (!await reader.ReadAsync().ConfigureAwait(false))
                            {
                                throw new ArgumentException($"Row with ID {id} not found");
                            }

                            var bytes  = (byte[])reader["Meta"];
                            var length = (long)reader["Length"];
                            var lastReadTimeDbValue = reader["LastReadTime"];

                            var jsonText = TextEncoding.GetString(bytes);
                            var metadata = _dictionarySerializer.DeserializeFromString(jsonText);

                            metadata[MetadataKeys.Length] = length.ToString();

                            if (lastReadTimeDbValue != DBNull.Value)
                            {
                                var lastReadTime = (DateTimeOffset)lastReadTimeDbValue;

                                metadata[MetadataKeys.ReadTime] = lastReadTime.ToString("O");
                            }

                            return(metadata);
                        }
                    }
                }
            }
            catch (ArgumentException)
            {
                throw;
            }
            catch (Exception exception)
            {
                throw new RebusApplicationException(exception, $"Could not load metadata for data with ID {id}");
            }
        }
        /// <summary>
        /// Loads the metadata stored with the given ID
        /// </summary>
        public Task <Dictionary <string, string> > ReadMetadata(string id)
        {
            try
            {
                using (var connection = _connectionHelper.Open())
                    using (var command = connection.CreateCommand())
                    {
                        command.CommandText = $"SELECT meta, creationTime, lastReadTime, LENGTHB(data) AS dataLength FROM {_table} WHERE id = :id";
                        command.Parameters.Add("id", id);

                        using (var reader = command.ExecuteReader(CommandBehavior.SingleRow))
                        {
                            if (!reader.Read())
                            {
                                throw new ArgumentException($"DataBus row with ID {id} not found");
                            }

                            var metaDbValue       = reader["meta"];
                            var dataLength        = reader.GetInt64(reader.GetOrdinal("dataLength"));
                            var creationTime      = reader.GetOracleTimeStampTZ(reader.GetOrdinal("creationTime")).ToDateTimeOffset();
                            var lastReadTimeIndex = reader.GetOrdinal("lastReadTime");
                            var lastReadTime      = reader.IsDBNull(lastReadTimeIndex) ?
                                                    (DateTimeOffset?)null :
                                                    reader.GetOracleTimeStampTZ(lastReadTimeIndex).ToDateTimeOffset();

                            var metadata = metaDbValue is DBNull ?
                                           new Dictionary <string, string>() :
                                           _dictionarySerializer.DeserializeFromString(TextEncoding.GetString((byte[])metaDbValue));

                            metadata[MetadataKeys.Length]   = dataLength.ToString();
                            metadata[MetadataKeys.SaveTime] = creationTime.ToString("O");

                            if (lastReadTime != null)
                            {
                                metadata[MetadataKeys.ReadTime] = lastReadTime.Value.ToString("O");
                            }

                            return(Task.FromResult(metadata));
                        }
                    }
            }
            catch (Exception exception) when(!(exception is ArgumentException))
            {
                throw new RebusApplicationException(exception, $"Could not load metadata for data with ID {id}");
            }
        }
Beispiel #9
0
        /// <summary>
        /// Gets due messages as of now, given the approximate due time that they were stored with when <see cref="M:Rebus.Timeouts.ITimeoutManager.Defer(System.DateTimeOffset,System.Collections.Generic.Dictionary{System.String,System.String},System.Byte[])" /> was called
        /// </summary>
        public async Task <DueMessagesResult> GetDueMessages()
        {
            var connection = await _connectionHelper.GetConnection();

            try
            {
                using (var command = connection.CreateCommand())
                {
                    command.CommandText =
                        $@"

SELECT
    ""id"",
    ""headers"", 
    ""body"" 

FROM ""{_tableName}"" 

WHERE ""due_time"" <= @current_time 

ORDER BY ""due_time""

FOR UPDATE;

";
                    command.Parameters.Add("current_time", NpgsqlDbType.Timestamp).Value = _rebusTime.Now.ToUniversalTime().DateTime;

                    using (var reader = await command.ExecuteReaderAsync())
                    {
                        var dueMessages = new List <DueMessage>();

                        while (reader.Read())
                        {
                            var id      = (long)reader["id"];
                            var headers = _dictionarySerializer.DeserializeFromString((string)reader["headers"]);
                            var body    = (byte[])reader["body"];

                            dueMessages.Add(new DueMessage(headers, body, async() =>
                            {
                                using (var deleteCommand = connection.CreateCommand())
                                {
                                    deleteCommand.CommandText = $@"DELETE FROM ""{_tableName}"" WHERE ""id"" = @id";
                                    deleteCommand.Parameters.Add("id", NpgsqlDbType.Bigint).Value = id;
                                    await deleteCommand.ExecuteNonQueryAsync();
                                }
                            }));
                        }

                        return(new DueMessagesResult(dueMessages, async() =>
                        {
                            await connection.Complete();
                            connection.Dispose();
                        }));
                    }
                }
            }
            catch (Exception)
            {
                connection.Dispose();
                throw;
            }
        }