I just upgrade my state machine saga projects to DotNet6 and Masstransit version 8.0.5.
Some how I can't find any way to config delay message schedule in my unit testing.
version 7.3.0
var provider = new ServiceCollection()
.AddMassTransitInMemoryTestHarness(cfg =>
{
cfg.AddSagaStateMachine<OldSaga, OldState>()
.InMemoryRepository();
cfg.AddSagaTestHarness<OldState>();
})
.BuildServiceProvider(true);
var harness = provider.GetRequiredService<InMemoryTestHarness>();
harness.OnConfigureInMemoryBus += configurator =>
{
configurator.UseDelayedMessageScheduler();
};
var sagaHarness = provider.GetRequiredService<ISagaTestHarness<OldState>>();
Version 8.0.5
var provider = new ServiceCollection().AddMassTransitTestHarness(cfg =>
{
cfg.AddSagaStateMachine<NewSaga, NewState>();
})
.BuildServiceProvider(true);
var harness = provider.GetTestHarness();
var sagaHarness = harness.GetSagaStateMachineHarness<NewSaga,NewState>();
**cfg.AddSagaTestHarness<NewState>(); is obsolete**
and can't GetRequiredService<InMemoryTestHarness>();
The changes are documented. The delayed message scheduler is added by default unless you specify your own transport configuration for the test harness. The AddXxxHarness are no longer required – the harnesses are automatically added by the underlying test harness.
Related
Thanks to this answer: Integration test and hosting ASP.NET Core 6.0 without Startup class
I have been able to perform integration tests with API.
WebApplicationFactory<Program>? app = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
});
});
HttpClient? client = app.CreateClient();
This has worked using the appsettings.json from the API project. Am now trying to use integrationtestsettings.json instead using:
IConfiguration configuration = new ConfigurationBuilder()
.SetBasePath(ProjectDirectoryLocator.GetProjectDirectory())
.AddJsonFile("integrationtestsettings.json")
.Build();
WebApplicationFactory<Program>? app = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureAppConfiguration(cfg => cfg.AddConfiguration(configuration));
builder.ConfigureServices(services =>
{
});
});
_httpClient = app.CreateClient();
I have inspected the configuration variable and can see the properties loaded from my integrartiontestsettings.json file. However, the host is still running using the appsettings.json from the server project.
Previously, in .Net5, I was using WebHostBuilder and the settings were overridden by test settings.
WebHostBuilder webHostBuilder = new();
webHostBuilder.UseStartup<Startup>();
webHostBuilder.ConfigureAppConfiguration(cfg => cfg.AddConfiguration(_configuration));
But cannot get the test settings to apply using the WebApplicationFactory.
It seems the method has changed.
Changing:
builder.ConfigureAppConfiguration(cfg => cfg.AddConfiguration(configuration));
To:
builder.UseConfiguraton(configuration);
has done the trick.
builder.ConfigureAppConfiguration, now it's configuring the app (after your WebApplicationBuilder.Build() is called) and your WebApplication is created.
You need to "inject" your configurations before the .Build() is done. This is why you need to call UseConfiguraton instead of ConfigureAppConfiguration.
I've got a project that uses SignalR and a RedisBackplane, we've moved from StackExchange.Redis to ServiceStack.Redis due to Redis Sentinel compatibility issues (Not movable)
However, it now looks like the support for SignalR Redis Backplane seems to be tied into StackExchange?
Have I completely missed something, or is there support for ServiceStack on a SignalR Redis Backplane?
Current code looks like:
var redisConnection = ConnectionMultiplexer.Connect(this.Configuration.GetValue<string>("Redis"));
services.AddSignalR(o => { o.EnableDetailedErrors = true; })
.AddStackExchangeRedis(options =>
{
options.Configuration.ChannelPrefix = "Audit";
options.ConnectionFactory =
writer => Task.FromResult(redisConnection as IConnectionMultiplexer);
});
I don't believe anyone has implemented a SignalR Redis backplane using ServiceStack.Redis.
ServiceStack does have it's own real-time events solution using SSE which includes a Redis Server Events implementation that uses ServiceStack.Redis (akin to SignalR Redis backplane).
I prefer to use username/password in the configuration
//StackExchange.Redis for configuration options
var redisConfiguration = new ConfigurationOptions
{
EndPoints = { "serverinfo:portinfo" },
User = username,
Password = password
//,Ssl = true
};
signalRBuilder.AddStackExchangeRedis(options => { options.Configuration = redisConfiguration; });
After updating MassTransit packages to the latest version (4.1.0.1426-develop) I experience problems with registering more then 26 queues. For example, code below crushes with error
[20:51:06 ERR] RabbitMQ Connect Failed: Broker unreachable:
guest#localhost:5672/test
static void Main(string[] args)
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", true, true);
var configuration = builder.Build();
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.ReadFrom.Configuration(configuration)
.CreateLogger();
Log.Information("Starting Receiver...");
var services = new ServiceCollection();
services.AddSingleton(context => Bus.Factory.CreateUsingRabbitMq(x =>
{
IRabbitMqHost host = x.Host(new Uri("rabbitmq://guest:guest#localhost:5672/test"), h => { });
for (var i = 0; i < 27; i++)
{
x.ReceiveEndpoint(host, $"receiver_queue{i}", e =>
{
e.Consumer<TestHandler>();
});
}
x.UseSerilog();
}));
var container = services.BuildServiceProvider();
var busControl = container.GetRequiredService<IBusControl>();
busControl.Start();
Log.Information("Receiver started...");
}
So, it can't register 27 queues. However it works if I decrease the number to 26 :)
If I downgrade MT NuGet packages to the latest stable 4.0.1 version it perfectly works and I can register up to 50 queues.
Also, another observation - with 4.1.0.1426-develop versions it takes much longer to start this very tiny app. However when I test it with latest stable 4.0.1 and try to create 50 queues it starts almost immediately.
Any ideas where this limitation came from and how to avoid it?
Thank you for opening the issue, that helps track it.
Also, it seems to be fixed now. There was an issue with how the netcoreapp2.0 program stack (and possibly the TaskScheduler) causing it to delay for a long period of time the Connect method in RabbitMQ.Client. I'm thinking this is a TPL/thread issue where the connection wasn't being scheduled for a good 15+ seconds, after which it completed immediately.
Moving it into a Task.Factory.StartNew() (deep inside the MT code) appears to have fixed the issue to where it doesn't fail, and it executes immediately.
I know this has been marked as resolved but I ran into a similar issue.
fail: MassTransit[0] partners.moneytransfer | RabbitMQ Connect Failed:
serviceUser#rabbitmq:5672/
The only way I was able to resolve is, is by adding the user to the rabbitmq database with its username and password as specified in the Bus configuration.
I am trying to configure swagger for my .Netcore App (1.1) and couldnt generate the docs.
Here is my configuration
public void ConfigureServices(IServiceCollection services) {
services.AddMvcCore().AddVersionedApiExplorer(o => o.GroupNameFormat = "1.0");
services.AddMvc();
services.AddApiVersioning(opt =>
{
opt.ApiVersionReader = new HeaderApiVersionReader("api-version");
opt.DefaultApiVersion = new ApiVersion(1, 0);
opt.ReportApiVersions = true;
opt.AssumeDefaultVersionWhenUnspecified = true;
});
services.AddSwaggerGen(
options =>
{
options.SwaggerDoc("1.0",new Info {Contact = new Contact() {Name="Admin" } });
// add a custom operation filter which sets default values
options.OperationFilter<SwaggerDefaultValues>();
});
}
In the Configure Method
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=User}/{action=Get}/{requestString?}");
});
app.UseSwagger(o=>
{
o.RouteTemplate = "docs/{documentName}/swagger.json";
});
app.UseSwaggerUI(
options =>
{
options.SwaggerEndpoint("/docs/1.0/swagger.json", "1.0");
});
When I run the application,
http://localhost:5000/docs/1.0/swagger.json
I am getting the below methods, None of my API's are discovered.
{"swagger":"2.0","info":{"contact":{"name":"Admin"}},"basePath":"/","paths":{},"definitions":{},"securityDefinitions":{}}
OK, I have reproduced your problem and found that the reason is the value in GroupNameFormat option.
If quickly, instead of const version string you should specify version format. As you want to have version in url as 1.0 you may use:
services.AddMvcCore().AddVersionedApiExplorer( o => o.GroupNameFormat = "VVVV" );
From Version Format section in Documentation:
Format Specifier: VVVV
Description: Major, minor version, and status
Examples: 1-RC -> 1.0-RC, 1.1 -> 1.1, 1 -> 1.0
Regarding AddMvcCore() vs AddMvc():
From the swagger docs at https://github.com/domaindrivendev/Swashbuckle.AspNetCore
Swashbuckle relies heavily on ApiExplorer, the API metadata layer that ships with ASP.NET Core. If you're using the AddMvc helper to bootstrap the MVC stack, then ApiExplorer will be automatically registered and SB will work without issue. However, if you're using AddMvcCore for a more paired-down MVC stack, you'll need to explicitly add the Api Explorer service:
services.AddMvcCore().AddApiExplorer();
If you also want AddVersionedApiExplorer(), chain that after AddApiExplorer()
In NSB 5, how do I correctly configure NSB with autofac container with one IDocumentStore for NSB data and a separate IDocumentStore for application data? I've pasted the relevant part of EndpointConfig below:
// Raven DataStore for Freight system
var appDataStore = new DocumentStore {
ConnectionStringName = "RavenDB",
DefaultDatabase = "ApplicationData"
};
appDataStore .Initialize();
// Raven DataStore for NServiceBus
var nsbDataStore = new DocumentStore
{
ConnectionStringName = "NServiceBus.Persistence",
DefaultDatabase = "BookingProcessing"
};
nsbDataStore.Initialize();
// Set up and build AutoFac container
var builder = new ContainerBuilder();
builder.RegisterInstance<DocumentStore>(appDataStore ).As<IDocumentStore>().SingleInstance();
var container = builder.Build();
// Set up NServiceBus
configuration.UseContainer<AutofacBuilder>(customizations => customizations.ExistingLifetimeScope(container));
configuration.UsePersistence<RavenDBPersistence>().SetDefaultDocumentStore(nsbDataStore);
I know this isn't working since I had problems storing sagas in another question. The SagaPersister tried to persist saga in appDataStore, but the Timeout Messages was persisted in nsbDataStore.
This issue is now fixed in NServiceBus.RavenDB v2.0.1
This is a sample for 4.x using unit of work,
If you use
Look here to see how you can implement IManageUnitsOfWork
The Init is here
Look here for the usage
will this help?