/// <summary> /// Creates the subscriptions table if no table with the specified name exists /// </summary> public void EnsureTableIsCreated() { AsyncHelpers.RunSync(async() => { using (var connection = await _connectionHelper.GetConnection()) { var tableNames = connection.GetTableNames(); if (tableNames.Contains(_tableName)) { return; } _log.Info("Table {tableName} does not exist - it will be created now", _tableName); using (var command = connection.CreateCommand()) { command.CommandText = $@" CREATE TABLE ""{_tableName }"" ( ""topic"" VARCHAR(200) NOT NULL, ""address"" VARCHAR(200) NOT NULL, PRIMARY KEY (""topic"", ""address"") ); "; command.ExecuteNonQuery(); } await connection.Complete(); } }); }
/// <summary> /// Saves the <paramref name="sagaData"/> snapshot and the accompanying <paramref name="sagaAuditMetadata"/> /// </summary> public async Task Save(ISagaData sagaData, Dictionary <string, string> sagaAuditMetadata) { using (var connection = await _connectionHelper.GetConnection()) { using (var command = connection.CreateCommand()) { command.CommandText = $@" INSERT INTO ""{_tableName}"" (""id"", ""revision"", ""data"", ""metadata"") VALUES (@id, @revision, @data, @metadata); "; command.Parameters.Add("id", NpgsqlDbType.Uuid).Value = sagaData.Id; command.Parameters.Add("revision", NpgsqlDbType.Integer).Value = sagaData.Revision; command.Parameters.Add("data", NpgsqlDbType.Bytea).Value = _objectSerializer.Serialize(sagaData); command.Parameters.Add("metadata", NpgsqlDbType.Jsonb).Value = _dictionarySerializer.SerializeToString(sagaAuditMetadata); await command.ExecuteNonQueryAsync(); } await connection.Complete(); } }
/// <summary> /// Stores the message with the given headers and body data, delaying it until the specified <paramref name="approximateDueTime" /> /// </summary> public async Task Defer(DateTimeOffset approximateDueTime, Dictionary <string, string> headers, byte[] body) { using (var connection = await _connectionHelper.GetConnection()) { using (var command = connection.CreateCommand()) { command.CommandText = $@" INSERT INTO ""{_tableName}"" (""due_time"", ""headers"", ""body"") VALUES (@due_time, @headers, @body)"; command.Parameters.Add("due_time", NpgsqlDbType.Timestamp).Value = approximateDueTime.ToUniversalTime().DateTime; command.Parameters.Add("headers", NpgsqlDbType.Text).Value = _dictionarySerializer.SerializeToString(headers); command.Parameters.Add("body", NpgsqlDbType.Bytea).Value = body; await command.ExecuteNonQueryAsync(); } await connection.Complete(); } }
async Task PerformExpiredMessagesCleanupCycle() { var results = 0; var stopwatch = Stopwatch.StartNew(); while (true) { using (var connection = await _connectionHelper.GetConnection()) { int affectedRows; using (var command = connection.CreateCommand()) { command.CommandText = $@" delete from {_tableName} where recipient = @recipient and expiration < clock_timestamp() "; command.Parameters.Add("recipient", NpgsqlDbType.Text).Value = _inputQueueName; affectedRows = await command.ExecuteNonQueryAsync(); } results += affectedRows; await connection.Complete(); if (affectedRows == 0) { break; } } } if (results > 0) { _log.Info( "Performed expired messages cleanup in {0} - {1} expired messages with recipient {2} were deleted", stopwatch.Elapsed, results, _inputQueueName); } }
public static void DropTable(string tableName) { using (var connection = PostgresConnectionHelper.GetConnection().Result) { using (var comand = connection.CreateCommand()) { comand.CommandText = $@"drop table ""{tableName}"";"; try { comand.ExecuteNonQuery(); Console.WriteLine("Dropped postgres table '{0}'", tableName); } catch (PostgresException exception) when(exception.SqlState == TableDoesNotExist) { } } connection.Complete(); } }
/// <summary> /// Checks to see if the configured saga data and saga index table exists. If they both exist, we'll continue, if /// neigther of them exists, we'll try to create them. If one of them exists, we'll throw an error. /// </summary> public void EnsureTablesAreCreated() { using (var connection = _connectionHelper.GetConnection().Result) { var tableNames = connection.GetTableNames().ToHashSet(); var hasDataTable = tableNames.Contains(_dataTableName); var hasIndexTable = tableNames.Contains(_indexTableName); if (hasDataTable && hasIndexTable) { return; } if (hasDataTable) { throw new RebusApplicationException( $"The saga index table '{_indexTableName}' does not exist, so the automatic saga schema generation tried to run - but there was already a table named '{_dataTableName}', which was supposed to be created as the data table"); } if (hasIndexTable) { throw new RebusApplicationException( $"The saga data table '{_dataTableName}' does not exist, so the automatic saga schema generation tried to run - but there was already a table named '{_indexTableName}', which was supposed to be created as the index table"); } _log.Info("Saga tables {tableName} (data) and {tableName} (index) do not exist - they will be created now", _dataTableName, _indexTableName); using (var command = connection.CreateCommand()) { command.CommandText = $@" CREATE TABLE ""{_dataTableName}"" ( ""id"" UUID NOT NULL, ""revision"" INTEGER NOT NULL, ""data"" BYTEA NOT NULL, PRIMARY KEY (""id"") ); "; command.ExecuteNonQuery(); } using (var command = connection.CreateCommand()) { command.CommandText = $@" CREATE TABLE ""{_indexTableName}"" ( ""saga_type"" TEXT NOT NULL, ""key"" TEXT NOT NULL, ""value"" TEXT NOT NULL, ""saga_id"" UUID NOT NULL, PRIMARY KEY (""key"", ""value"", ""saga_type"") ); CREATE INDEX ON ""{_indexTableName}"" (""saga_id""); "; command.ExecuteNonQuery(); } Task.Run(async() => await connection.Complete()).Wait(); } }