public async Task AbleToMigrate_delayed_delivery_does_not_exist_should_indicate_problems()
        {
            var sut = new SqlTTimeoutsTarget(new TestLoggingAdapter(), connectionString, schema);

            await using var connection = new SqlConnection(connectionString);
            await connection.OpenAsync();

            await using var command = connection.CreateCommand();
            command.CommandText     = string.Format(@"
IF OBJECT_ID('{0}.{1}', 'u') IS NOT NULL
  DROP TABLE {0}.{1};
", $"{ExistingEndpointName}.Delayed", schema);
            await command.ExecuteNonQueryAsync();

            var info = new EndpointInfo
            {
                EndpointName    = ExistingEndpointName,
                ShortestTimeout = DateTime.UtcNow.AddDays(3),
                LongestTimeout  = DateTime.UtcNow.AddDays(5),
                Destinations    = new List <string>
                {
                    ExistingDestination
                }
            };
            var result = await sut.AbleToMigrate(info);

            Assert.IsFalse(result.CanMigrate);
        }
        public async Task AbleToMigrate_delayed_delivery_does_exist_should_indicate_no_problems()
        {
            var sut = new SqlTTimeoutsTarget(new TestLoggingAdapter(), connectionString, schema);

            await using var connection = new SqlConnection(connectionString);
            await connection.OpenAsync();

            await using var command = connection.CreateCommand();
            command.CommandText     = string.Format(@"
CREATE TABLE [{1}].[{0}] (
    RowVersion bigint IDENTITY(1,1) NOT NULL
);
", $"{ExistingEndpointName}.Delayed", schema);
            await command.ExecuteNonQueryAsync();

            var info = new EndpointInfo
            {
                EndpointName    = ExistingEndpointName,
                ShortestTimeout = DateTime.UtcNow.AddDays(3),
                LongestTimeout  = DateTime.UtcNow.AddDays(5),
                Destinations    = new List <string>
                {
                    ExistingDestination
                }
            };
            var result = await sut.AbleToMigrate(info);

            Assert.IsTrue(result.CanMigrate);
        }
        public async Task Can_migrate_timeouts()
        {
            var sourceEndpoint = NServiceBus.AcceptanceTesting.Customization.Conventions.EndpointNamingConvention(typeof(AspSource));
            var targetEndpoint = NServiceBus.AcceptanceTesting.Customization.Conventions.EndpointNamingConvention(typeof(SqlTTarget));

            await Scenario.Define <SourceContext>()
            .WithEndpoint <AspSource>(b => b.CustomConfig(ec =>
            {
                SetupPersistence(ec);
            })
                                      .When(async(session, c) =>
            {
                var delayedMessage = new DelayedMessage();
                var options        = new SendOptions();

                options.DelayDeliveryWith(TimeSpan.FromSeconds(15));
                options.SetDestination(targetEndpoint);

                await session.Send(delayedMessage, options);

                await WaitUntilTheTimeoutsAreSavedInAsp(sourceEndpoint, 2);

                c.TimeoutSet = true;
            }))
            .Done(c => c.TimeoutSet)
            .Run(TimeSpan.FromSeconds(30));

            var setupContext = await Scenario.Define <TargetContext>()
                               .WithEndpoint <SqlTTarget>(b => b.CustomConfig(ec =>
            {
                ec.OverrideLocalAddress(sourceEndpoint);

                ec.UseTransport <SqlServerTransport>()
                .ConnectionString(sqlConnectionString);
            }))
                               .Done(c => c.EndpointsStarted)
                               .Run(TimeSpan.FromSeconds(30));

            var logger          = new TestLoggingAdapter(setupContext);
            var timeoutStorage  = CreateTimeoutStorage(sourceEndpoint);
            var timeoutTarget   = new SqlTTimeoutsTarget(logger, sqlConnectionString, "dbo");
            var migrationRunner = new MigrationRunner(logger, timeoutStorage, timeoutTarget);

            await migrationRunner.Run(DateTime.Now.AddDays(-10), EndpointFilter.SpecificEndpoint(sourceEndpoint), new Dictionary <string, string>());

            var context = await Scenario.Define <TargetContext>()
                          .WithEndpoint <SqlTTarget>(b => b.CustomConfig(ec =>
            {
                ec.OverrideLocalAddress(sourceEndpoint);

                ec.UseTransport <SqlServerTransport>()
                .ConnectionString(sqlConnectionString);
            }))
                          .Done(c => c.GotTheDelayedMessage)
                          .Run(TimeSpan.FromSeconds(30));

            Assert.True(context.GotTheDelayedMessage);
        }
Пример #4
0
        public async Task Can_migrate_timeouts()
        {
            var sourceEndpoint = NServiceBus.AcceptanceTesting.Customization.Conventions.EndpointNamingConvention(typeof(NHibernateSource));
            var targetEndpoint = NServiceBus.AcceptanceTesting.Customization.Conventions.EndpointNamingConvention(typeof(SqlTTarget));

            using (var testSession = CreateSessionFactory().OpenSession())
            { // Explicit using scope to ensure dispose before SUT connects
                using (var testTx = testSession.BeginTransaction())
                {
                    await testSession.SaveAsync(new TimeoutEntity
                    {
                        Endpoint    = sourceEndpoint,
                        Destination = targetEndpoint,
                        SagaId      = Guid.NewGuid(),
                        Headers     = "{\"NServiceBus.EnclosedMessageTypes\": \"TimeoutMigrationTool.NHibernate.AcceptanceTests.NHibernateToSqlTEndToEnd+DelayedMessage\"}",
                        State       = Encoding.UTF8.GetBytes("{}"),
                        Time        = DateTime.UtcNow.AddSeconds(15)
                    });

                    await testTx.CommitAsync();
                }
            }

            var context = await Scenario.Define <TargetContext>()
                          .WithEndpoint <SqlTTarget>(b => b.CustomConfig(ec =>
            {
                ec.OverrideLocalAddress(sourceEndpoint);
                var transportConfig = ec.UseTransport <SqlServerTransport>();

                transportConfig.ConnectionString(connectionString);

                ec.UseSerialization <NewtonsoftSerializer>();
            })
                                                     .When(async(_, c) =>
            {
                var logger         = new TestLoggingAdapter(c);
                var timeoutsSource = new NHibernateTimeoutsSource(connectionString, 1024, DatabaseDialect);
                var timeoutTarget  = new SqlTTimeoutsTarget(logger, connectionString, "dbo");

                var migrationRunner = new MigrationRunner(logger, timeoutsSource, timeoutTarget);

                await migrationRunner.Run(DateTime.Now.AddDays(-10),
                                          EndpointFilter.SpecificEndpoint(sourceEndpoint), new Dictionary <string, string>());
            }))
                          .Done(c => c.GotTheDelayedMessage)
                          .Run(TimeSpan.FromSeconds(90));

            Assert.True(context.GotTheDelayedMessage);
        }
        public async Task Should_delete_staging_table_when_empty()
        {
            var sut = new SqlTTimeoutsTarget(new TestLoggingAdapter(), connectionString, schema);

            await using var connection = new SqlConnection(connectionString);
            await connection.OpenAsync();

            await SqlTQueueCreator.CreateStagingQueue(connection, SqlConstants.TimeoutMigrationStagingTable, schema, connection.Database, preview : false);

            await sut.Complete(ExistingEndpointName);

            var sqlStatement = $"SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = '{SqlConstants.TimeoutMigrationStagingTable}' AND TABLE_CATALOG = '{databaseName}'";

            await using var command = new SqlCommand(sqlStatement, connection)
                        {
                            CommandType = CommandType.Text
                        };
            var result = await command.ExecuteScalarAsync().ConfigureAwait(false) as int?;

            Assert.That(result, Is.EqualTo(0));
        }
        public async Task Should_delete_staging_queue_when_completing()
        {
            var sut          = new SqlTTimeoutsTarget(new TestLoggingAdapter(), connectionString, schema);
            var endpointName = "FakeEndpoint";

            await using var endpointTarget = await sut.PrepareTargetEndpointBatchMigrator(endpointName);

            await sut.Complete(endpointName);

            await using var connection = new SqlConnection(connectionString);
            await connection.OpenAsync();

            await using var command = connection.CreateCommand();
            command.CommandText     = string.Format(@"
   SELECT COUNT(*)
   FROM INFORMATION_SCHEMA.TABLES
   WHERE TABLE_SCHEMA = '{1}' AND TABLE_NAME = '{0}' AND TABLE_CATALOG = '{2}'
", SqlConstants.TimeoutMigrationStagingTable, schema, databaseName);
            var result = await command.ExecuteScalarAsync() as int?;

            Assert.That(Convert.ToBoolean(result), Is.False);
        }
        public async Task Should_throw_when_staging_table_not_empty()
        {
            var sut = new SqlTTimeoutsTarget(new TestLoggingAdapter(), connectionString, schema);

            await using var connection = new SqlConnection(connectionString);
            await connection.OpenAsync();

            await SqlTQueueCreator.CreateStagingQueue(connection, SqlConstants.TimeoutMigrationStagingTable, schema, connection.Database, preview : false);

            var sql =
                $"INSERT INTO {schema}.{SqlConstants.TimeoutMigrationStagingTable} VALUES('headers', NULL, DATEADD(DAY, 1, GETDATE()))";

            await using var command = new SqlCommand(sql, connection)
                        {
                            CommandType = CommandType.Text
                        };
            await command.ExecuteNonQueryAsync();

            Assert.ThrowsAsync <Exception>(async() =>
            {
                await sut.Complete(ExistingEndpointName);
            });
        }
        public async Task Should_migrate_into_delayed_table()
        {
            var endpointDelayedTableName = $"{ExistingEndpointName}.Delayed";

            var sut = new SqlTTimeoutsTarget(new TestLoggingAdapter(), connectionString, schema);

            await using var connection = new SqlConnection(connectionString);
            await connection.OpenAsync();

            await using var command = connection.CreateCommand();

            command.CommandText = string.Format(@"
CREATE TABLE [{1}].[{0}] (
    Headers nvarchar(max) NOT NULL,
    Body varbinary(max),
    Due datetime NOT NULL,
    RowVersion bigint IDENTITY(1,1) NOT NULL
);
", endpointDelayedTableName, schema);
            await command.ExecuteNonQueryAsync();

            const int BatchNumber = 2;

            await using var endpointTarget = await sut.PrepareTargetEndpointBatchMigrator(ExistingEndpointName);

            await endpointTarget.StageBatch(new List <TimeoutData>
            {
                new TimeoutData
                {
                    Id      = "SomeID",
                    Headers = new Dictionary <string, string>
                    {
                        { "NServiceBus.MessageId", "SomeMessageId" }
                    },
                    Destination = "SomeDestination",
                    State       = new byte[2],
                    Time        = new DateTime(2021, 12, 12, 12, 12, 12, DateTimeKind.Utc)
                },
                new TimeoutData
                {
                    Id      = "SomeOtherId",
                    Headers = new Dictionary <string, string>
                    {
                        { "NServiceBus.MessageId", "SomeOtherMessageId" }
                    },
                    Destination = "SomeOtherDestination",
                    State       = new byte[2],
                    Time        = new DateTime(2021, 12, 12, 12, 13, 13, DateTimeKind.Utc)
                },
            }, BatchNumber);

            await endpointTarget.CompleteBatch(BatchNumber);

            var endpointDelayedTableDataTable = new DataTable();

            using var endpointDelayedTableDataAdapter = new SqlDataAdapter(string.Format("SELECT * FROM [{1}].[{0}]", endpointDelayedTableName, schema), connection);
            endpointDelayedTableDataAdapter.Fill(endpointDelayedTableDataTable);

            var migrationTableDataTable = new DataTable();

            using var migrationTableDataAdapter = new SqlDataAdapter(string.Format("SELECT * FROM [{1}].[{0}]", SqlConstants.TimeoutMigrationStagingTable, schema), connection);
            migrationTableDataAdapter.Fill(migrationTableDataTable);

            Approver.Verify(endpointDelayedTableDataTable.Rows.OfType <DataRow>().SelectMany(r => r.ItemArray.Take(3)));
            Assert.IsEmpty(migrationTableDataTable.Rows);
        }
        public async Task Can_migrate_timeouts()
        {
            var sourceEndpoint = NServiceBus.AcceptanceTesting.Customization.Conventions.EndpointNamingConvention(typeof(RavenDBSource));
            var targetEndpoint = NServiceBus.AcceptanceTesting.Customization.Conventions.EndpointNamingConvention(typeof(SqlTTarget));

            var ravenTimeoutPrefix = "TimeoutDatas";
            var ravenVersion       = RavenDbVersion.Four;

            var ravenAdapter = new Raven4Adapter(serverUrl, databaseName);

            await Scenario.Define <SourceContext>()
            .WithEndpoint <RavenDBSource>(b => b.CustomConfig(ec =>
            {
                ec.UsePersistence <RavenDBPersistence>()
                .SetDefaultDocumentStore(GetDocumentStore(serverUrl, databaseName));
            })
                                          .When(async(session, c) =>
            {
                var delayedMessage = new DelayedMessage();
                var options        = new SendOptions();

                options.DelayDeliveryWith(TimeSpan.FromSeconds(20));
                options.SetDestination(targetEndpoint);

                await session.Send(delayedMessage, options);

                await WaitUntilTheTimeoutIsSavedInRaven(ravenAdapter, sourceEndpoint);

                c.TimeoutSet = true;
            }))
            .Done(c => c.TimeoutSet)
            .Run(TimeSpan.FromSeconds(15));

            var setupContext = await Scenario.Define <TargetContext>()
                               .WithEndpoint <SqlTTarget>(b => b.CustomConfig(ec =>
            {
                ec.OverrideLocalAddress(sourceEndpoint);

                ec.UseTransport <SqlServerTransport>()
                .ConnectionString(sqlConnectionString);
            }))
                               .Done(c => c.EndpointsStarted)
                               .Run(TimeSpan.FromSeconds(30));

            var logger          = new TestLoggingAdapter(setupContext);
            var timeoutsSource  = new RavenDbTimeoutsSource(logger, serverUrl, databaseName, ravenTimeoutPrefix, ravenVersion, false);
            var timeoutsTarget  = new SqlTTimeoutsTarget(logger, sqlConnectionString, "dbo");
            var migrationRunner = new MigrationRunner(logger, timeoutsSource, timeoutsTarget);

            await migrationRunner.Run(DateTime.Now.AddDays(-1), EndpointFilter.SpecificEndpoint(sourceEndpoint), new Dictionary <string, string>());

            var context = await Scenario.Define <TargetContext>()
                          .WithEndpoint <SqlTTarget>(b => b.CustomConfig(ec =>
            {
                ec.OverrideLocalAddress(sourceEndpoint);

                ec.UseTransport <SqlServerTransport>()
                .ConnectionString(sqlConnectionString);
            }))
                          .Done(c => c.GotTheDelayedMessage)
                          .Run(TimeSpan.FromSeconds(30));

            Assert.True(context.GotTheDelayedMessage);
        }