Rebus 4.0 - How to specify order of handlers , tried with "SpecifyOrderOfHandlers" method but gives compile time error - rebus

Hellooo Rebus Fans, We have been using Rebus 0.84 aka 1.0 for many years and now moving to 4.0 version & it seems its improved a lot in terms of implementation & performance but facing some problems while implementing orders for handlers.
Example in previous version , we used to do
public class RebusInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
Configure.With(new WindsorContainerAdapter(container))
.Logging(l => l.Log4Net())
.Transport(t => t.UseMsmqAndGetInputQueueNameFromAppConfig())
.SpecifyOrderOfHandlers(t => t.First<AuthenticationHandler>())
.Serialization(x => x.UseJsonSerializer())
.MessageOwnership(m => m.FromRebusConfigurationSection())
.Sagas(m => m.StoreInNDb())
.Subscriptions(m => m.StoreInNDb())
.Timeouts(m => m.StoreInMemory())
.Events(e =>
{
e.MessageSent += (advancedbus, destination, message) =>
{
var timeToBeReceived = ConfigurationManager.AppSettings["TimeToBeReceived"];
if (string.IsNullOrEmpty(timeToBeReceived))
timeToBeReceived = "00:00:30";
if (timeToBeReceived != "-1")
{
advancedbus.AttachHeader(message, Headers.TimeToBeReceived, timeToBeReceived);
advancedbus.AttachHeader(message, Headers.Express, "rebus-express");
}
};
})
.CreateBus()
.Start();
}
}
and now if i am implementing the same with rebus 4.0 then somehow , while trying "SpecifyOrderOfHandlers" it gives compile time error that it does not accept any argument then how can we implement ordering of handlers, below is the implementation with rebus 4.0
using Rebus.Config;
using Rebus.Persistence.InMem;
using Rebus.Handlers;
using Rebus.Messages;
public void Install(IWindsorContainer container, IConfigurationStore store)
{
Configure.With(new CastleWindsorContainerAdapter(container))
.Options(o =>
{
o.SpecifyOrderOfHandlers(o => o.First<AuthenticationHandler>());
})
.Logging(l => l.Log4Net())
.Transport(t => t.UseMsmq(ConfigurationManager.AppSettings["InputQueue"]))
.Routing(r => r.TypeBasedRoutingFromAppConfig())
.Sagas(m => m.StoreInNDb())
.Subscriptions(m => m.StoreInNDb())
.Timeouts(m => m.StoreInMemory())
.Events(e =>
{
e.BeforeMessageSent += (bus, headers, message, context) =>
{
var timeToBeReceived = ConfigurationManager.AppSettings["TimeToBeReceived"];
if (string.IsNullOrEmpty(timeToBeReceived))
timeToBeReceived = "00:00:30";
if (timeToBeReceived != "-1")
{
headers.Add(Headers.TimeToBeReceived, timeToBeReceived);
headers.Add(Headers.Express, "rebus-express");
}
};
})
.Start();
}
Please suggest how to implement handler ordering with rebus 4.0 and also let me know if above approach of implementing rebus 4.0 is correct or needs improvement.

You've simply made the call to SpecifyOrderOfHandlers a little bit too complicated – this should do the trick:
Configure.With(activator)
(...)
.Options(o =>
{
o.SpecifyOrderOfHandlers()
.First<AuthenticationHandler>();
})
.(...)
.Start();
If it wasn't readily obvious, then it's probably because the SpecifyOrderOfHandlers is in another namespace, so if you add
using Rebus.Handlers.Reordering;
in the top of your file somewhere, then I bet IntelliSense will guide you :)

Related

Mock IConfiguration or IValueResolver

I am using automapper in my Program.cs like this:
builder.Services.AddAutoMapper(typeof(MappingProfiles));
And in my MappingProfiles I have configured this profile:
CreateMap<Product, ProductToReturnDto>()
.ForMember(d => d.ProductBrand, o => o.MapFrom(s => s.ProductBrand.Name))
.ForMember(d => d.ProductType, o => o.MapFrom(s => s.ProductType.Name))
.ForMember(d => d.PictureUrl, o => o.MapFrom<ProductUrlResolver>());
Im my ProductUrlResolver I get IConfiguration injected in the constructor and that IConfiguration is used in the ProductUrlResolver to get some properties from appsettings.*.json
Now I would like to write a XUnit test for my controller where i use MOQ to mock out the services and also I do this to create my mapper that normally get injected into my controller:
var mapperConfiguration = new MapperConfiguration(cgf => cgf.AddProfile(new MappingProfiles()));
var mapper = new Mapper(mapperConfiguration);
But I get a error when the ProductUrlResolver is trying to get properties from the IConfiguration, and since I am not injecting the ProductUrlResolver into my MappingProfiles, but rather it is getting the ProductUrlResolver with the "o.MapFrom()" magic, then how do I trick the ProductUrlResolver to be able to get some data from some mocked or real configuration?
Thank you
Søren
How about this:
public class MappingProfiles: Profile
{
public MappingProfiles(IProductUrlResolver urlRes)
{
CreateMap<Product, ProductToReturnDto>()
.ForMember(d => d.ProductBrand, o => o.MapFrom(s => s.ProductBrand.Name))
.ForMember(d => d.ProductType, o => o.MapFrom(s => s.ProductType.Name))
.ForMember(d => d.PictureUrl, o => o.ConvertUsing(new MyConverter(urlRes));
}
private class MyConverter: IValueConverter<string, string> { ... }
}
Now you can pass to the MappingProfiles either a normal or a mocked instance of your URL converter.
If you want a normal instance, don't use the whole configuration in it, use Options pattern:
public class ProductUrlResolver : IProductUrlResolver {
void ProductUrlResolver(IOptions<MySettings> settings) { ... }
}
Than in your test you can instantiate it like this:
new ProductUrlResolver(Options.Create(new MySettings())

Rebus Singleton Connection with RabbitMQ

I am using Rebus and have seen some strange behavior.
I do expect that my application (Endpoint) would open only one Connection to the RabbitMQ Server and this connection will be used as a Singleton.
However I have seen that the number of connections from my end point to the server increases over time a thing that leads to RabbitMQ server to crash.
I would like to know if there is any way to limit the number of connections that the rebus endpoint can open to RabbitMQ server.
In the method public void ConfigureServices(IServiceCollection services) we have
services.AutoRegisterHandlersFromAssemblyOf<RegisterMemberEventHandler>();
services.AddRebus(configure => configure
.Logging(l => l.Serilog())
.Transport(t => t.UseRabbitMq($"amqp://{UserName}:{Password}#{HostName}:{PortNo}", $"{EndPointQueue}")
.ClientConnectionName("OMRSAPI")
)
.Options(o =>
{
o.SetNumberOfWorkers(NumberOfWorkers);//10
o.SetMaxParallelism(MaxParallelism);//20
o.HandleMessagesInsideTransactionScope();
o.Decorate<IErrorHandler>(c => {
var errorHandler = c.Get<IErrorHandler>();
var loggerFactory = c.Get<IRebusLoggerFactory>();
var bus = c.Get<IBus>();
var transport = c.Get<ITransport>();
return new ErrorMessageHandler(errorHandler, loggerFactory,settings,bus,transport);
});
o.SimpleRetryStrategy(maxDeliveryAttempts: 3, secondLevelRetriesEnabled: true);
})
.Timeouts(x => x.StoreInSqlServer(settings.ConnectionStrings.RebusContext, "Timeouts"))
.Routing(r => r.TypeBased()
.Map<VerifyNID>(EndPointQueue)
.Map<ErrorOccurred>(ErrorQueueName)
));
//Some Code was removed for the sake of clarity

How can I write use previous returned value of an observable with redux-observable?

I don't know my question title is suitable for this question.
I would like to use returned value of someAsync1 (same as v2) as argument of action1 inside of flatMap.
const anEpic = ($action: ActionsObservable<MyAction>, store: Store<MyRootStore>) => {
return $action.ofType(ActionTypes.AN_ASYNC_ACTION)
.switchMap((v1) => someAsync1(v1))
.switchMap((v2) => someAsync2(v2))
.map((v) => applyToUI(v))
.flatMap((v) => Observable.concat(Observable.of(action1(v)), Observable.of(action2(true)))) //
}
I guess I can use that value by injecting v2 to returned value of someAsync2. But that code looks disgusting.
What is clever way to do this with redux-observable?
switchMap technically means, well, switch to another Observable stream. That means there is no way for you to retain the value because your observer is now observing a different source.
There are a few ways to do the so called "retaining" the values from one stream to another, depending on which one you prefer.
1. Behaviour Subject
This is the most preferred way, because the purpose of BehaviourSubject is to retain a value of an Observable:
//initialize a BehaviourSubject
let v2BSubject = new BehaviourSubject<any>(null);
const anEpic = ($action: ActionsObservable<MyAction>, store: Store<MyRootStore>) => {
return $action.ofType(ActionTypes.AN_ASYNC_ACTION)
.switchMap((v1) => someAsync1(v1))
.switchMap((v2) => {
//store your v2 value here!
v2BSubject.next(v2);
return someAsync2(v2)
})
.map((v) => applyToUI(v))
.flatMap((v) => {
//get your v2 values here
let v2Value = v2BSubject.value;
return Observable.concat(Observable.of(action1(v)), Observable.of(action2(true)))
}) //
}
or you can use it as an Observable. That way you can treat it as an observable and use whatever rxjs operator can provide:
.flatMap((v) => {
return Observable.concat(Observable.of(action1(v)), v2BSubject.asObservable())
})
2. Use .map to propagate the value.
This is rather hacky, but gets the job done. However do note it's modifying the stream source. If you have many operations along the pipe, it may blow up quickly and hard to manage:
const anEpic = ($action: ActionsObservable<MyAction>, store: Store<MyRootStore>) => {
return $action.ofType(ActionTypes.AN_ASYNC_ACTION)
.switchMap((v1) => someAsync1(v1))
.switchMap((v2) => {
someAsync2(v2)
.map(afterSomeAsync2 => {
return {
v1Value: v2,
v2Value: afterSomeAsync2
}
})
})
.map(({v1Value, v2Value}) => {
return applyToUI(v1Value).map(v1 => {
return {
v1Value: v1,
v2Value: v2Value
}
})
})
.flatMap(({v1Value, v2Value}) => {
return Observable.concat(Observable.of(action1(v1Value)), Observable.of(v2Value))
})
The easiest solution is to apply your operators directly on the returned inner Observables instead of on the collapsed outer chain. You can then access the values emitted because they're part of the closures.
That's probably confusing, but hopefully this code makes it clear:
const anEpic = ($action: ActionsObservable<MyAction>, store: Store<MyRootStore>) => {
return $action.ofType(ActionTypes.AN_ASYNC_ACTION)
.switchMap((v1) =>
someAsync1(v1)
.switchMap((v2) =>
someAsync2(v2)
.map((v) => applyToUI(v))
.flatMap((v) => Observable.of(action1(v, v1, v2), action2(true))
)
)
}
This pattern is also what you would have to use if you wanted to catch any errors by someAsync1 or someAsync2 because if you let the error propagate to the top-level chain the epic will have stopped listening for future actions.
e.g. if your epic looks like this:
const somethingEpic = (action$, store) => {
return action$.ofType(SOMETHING)
.switchMap(action => someAsync1(v1))
.map(() => ({ type: SOMETHING_FULFILLED }))
.catch(error => Observable.of({
type: SOMETHING_REJECTED,
error
}));
}
When the error reaches the catch operator it's too late, your epic is no longer listening for future actions. You could "restart" it, but this can have unexpected consequences so its best to avoid this pattern.
Instead, catch the error before it propagates out
const somethingEpic = (action$, store) => {
return action$.ofType(SOMETHING)
.switchMap(action =>
someAsync1(v1)
.map(() => ({ type: SOMETHING_FULFILLED }))
.catch(error => Observable.of({
type: SOMETHING_REJECTED,
error
}))
);
}
Some people refer to this as "isolating your observer chains".
Also notice how I didn't need to use concat with multiple of because of supports any number of arguments.

Angular 2 loads HTTP request 5 times even though i am calling only once

For example:
ngOnInit()
{
this.user = new User();
this.result = new Result();
this.route.params
.switchMap((params: Params) => this.user.id = params['id'])
.subscribe((user: User) => this.getUser());
}
getUser()
{
this.result.updateInfo("getting records...")
this.user.id = this.user.id.toLowerCase();
this._serivce.getUser(this.user.id).subscribe(userobj =>
{
this.user = userobj;
console.log(userobj);//five times
},error => this.result.updateError(error));
}
the useronj gets printed five times in console.
Service:
getUser(id: string) {
return this.http.get(<url>, { headers: this.headers })
.map(this.extractData)
.catch(this.handleError);
}
Update: Only the ngOnInit calls getUser, that too only once!
Is there a reason why you are using switchMap? You are also doing a lot of subscribing there, which could cause the issue. What you are trying to achieve, which seems to be getting a user by the id parameter, so this should do the trick:
ngOnInit() {
this.route.params
.subscribe(params => {
let id = params['id'];
this._service.getUser(id.toLowerCase())
.subscribe(userobj => {
console.log(userObj);
});
});
}
EDIT: As a sidenote, per comment from OP (since comments tend to go unnoticed) Turned out that switchMap was the sole issue in this case. So my suspicion that all the subscribing could be an additional cause for this issue, turned out to not be true :)

How to return an observable from a http service in angular2

Unfortunately as I was storing many results on the service, I'm now stuck with many {{myservice.somevalue}} (and myservice.someother) etc. sprinkled over my other components.
I believe it would be nicer to return from the service to a component.
This is the code that I have on the service:
getIssue(issueName: string) {
return this.http.post(this.URL + 'issue/all', JSON.stringify({'issueName': issueName}))
.subscribe(data => this.somevalue = data.json(),
err => console.log(err));
}
So then on several other components I call functions like this.myservice.getIssue(issueName).
In the HTML I'd prefer to use {{somevalue}}.
What can I do to return a http observable from the http service?
class SomeService {
someValue = new BehaviorSubject();
getIssue(issueName: string) {
return this.http.post(this.URL + 'issue/all', JSON.stringify({'issueName': issueName}))
.subscribe(data => this.somevalue.next(data.json()),
err => console.log(err));
}
}
In your component
class MyComponent {
constructor(someService:SomeService) {
someService.someValue.subscribe(val => {
this.someValue = val;
});
}
}
For an alternative approach see also https://stackoverflow.com/a/36291681/217408

Resources