/// <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();
            }
        }
예제 #3
0
        /// <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);
            }
        }
예제 #5
0
        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();
            }
        }
예제 #6
0
        /// <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();
            }
        }