What is lost from the stack when a service handles async messages in ServiceStack? - servicestack

I'm using the messaging feature of ServiceStack for back end transactions I expect to involve database locks where consistency is very important.
I've registered handlers as explained in the documentation:
mqHost.RegisterHandler<Hello>(m => {
return this.ServiceController.ExecuteMessage(m);
});
I've noticed the Filters don't get called. Presumably, they're really "Http" filters similar to MVC. So it makes sense they're ignored.
How does Authorization work with message handlers, is it ignored too?
And as I want to keep my async services internal, and always async, is there any benefit in making them inherit from ServiceBase at all?
As I'm thinking of creating another envelop layer between IMessage and Body for some Identity data that can be passed from my public services out of AuthSession and to the Async service.

Related

NodeJS Service Layer asynchronous communication

If I have to invoke ServiceB.action as a result of ServiceA.action being invoked, should I call ServiceB.action from ServiceA.action at the appropriate time, or should I emit an event from ServiceA and let ServiceB react to that event?
I can use an EventEmitter, but it works synchronously, in a sense that the callbacks are invoked sequentially without waiting the previous to resolve, which is ok for me. What isn't, though, is that the $emit will not wait until all of the listeners have resolved.
For a more real world scenario, lets assume that I have a Subscription service, and when a new subscription is created, the Email service needs to know about it so that it can notify somebody by email.
const SubscriptionService = {
async create(user) {
await Subscription.create(user)
// Notify email service
}
}
const EmailService = {
async notify(user) {...}
}
One way I could do it, is call the EmailService.notify(user) from SubscriptionService.create and pass in the user.
Another way I could do it is with an event emitter
async create(user) {
await Subscription.create(user)
Emitter.$emit('subscription', user)
}
The second approach seems clean, because I'm not mixing things together, the notifications happen as a result of the subscription being created and the create method is not polluted with extra logic. Also, adding more side-effects like the notification one would be simpler.
The subscription service's create method, however, will not wait until all of the listeners have resolved, which is an issue. What if the Notification fails? The user will not get the email, in this scenario. What about error handling? In the first scenario I can handle the errors on spot when I invoke the EmailService.notify, but not with the emitter.
Is not meant for similar use-cases or am I looking at the problem in a wrong way?
The event pattern is the most appropriate for the scenario you described. Rather than using std event emitters you could use promise-events which should let you do error handling as it seems you described.
Hope this helps.
Since the create method returns a Promise, you can just do something like:
SubscriptionService.create(user).then((user) => EmailService.notify(user));
Note: The above depends on where and how you're calling these methods.
Both of the approaches are appliable and correct for specific scenarios.
Pub/Sub is great for the applications where there are few subscribers and does various jobs in the background. Publishers(SubscriptionService.create) are loosely coupled to the subscribers-(EmailService.notify)
Service layer exists for applying business logics, and nothing wrong with using function composition for more than one methods which serves for a single operation. If it should notify user after subscription has been created, yes those two methods can work together. Also, if you want to use EmailService.notify method in somewhere else, you have to publish a new event, and create a new subscriber for that too, because you can't just use the previously created subscriber.
Personally, I would prefer, calling ServiceB.action inside ServiceA.action on your scenario. Publishing an event and creating a subscriber in the ServiceB is looks a bit much.

DDD / CQRS - Does a request handler (or controller) can throw exceptions defined at the domain level?

Good morning,
Let's say, we've a domain defining an exception such as ObjectNotFoundException which expect an identifier (VO), defined at the domain model.
Question
Can we throw domain exceptions from the request handlers directly, for instance:
class ObjectRequestHandler implements RequestHandler
{
...
public function __invoke(Request $request, Response $response)
{
// Will self-validate and throw an exception if not a valid UUID
$objectId = ObjectId::fromString(strval($request->param('object_id'])));
$object = $this->repository->find((string)$objectId);
if (NULL === $object) {
// Exception defined at the domain level...
throw new ObjectNotFoundException($objectId);
}
...
}
}
Doing this also lead to usage of the identifier VO in the request handler... It MUST be also noted that the throwed exception will be catched by the default exception handler which in turn, will prepare and send a JSON response.
Finally, note that the request handler here, is an implementation detail, not part of the question. Please don't comment about it.
Thank you.
Your example shows the correct usage of the repository to fetch an object from the data store based on an identifier.
Let's unpack and expand the workflow a little more to fit the paradigms of DDD, to help answer the question:
API Controller (or Request Handler) would invoke an Application Service with request params sent by the callee.
Request params forwarded to the Application Service can be simple data (like JSON) or can be objects (like DTOs)
Application Service has access to the correct repository associated with the object.
Repositories are outside the domain layer
Application Service would load the objects into memory using these repositories before handing over the control to (or invoking a method in) the domain layer.
The ObjectNotFound error is thrown typically from the repository if no object is found for the given identifier
The domain layer typically receives all objects it needs to work on from the Application Service or builds objects using factory methods.
The actual process is all about assigning or transforming attribute values according to business rules while ensuring invariant rules are satisfied. So the kind of errors that Domain Layer throws is Business Rule Errors (or Validation Errors).
So,
ObjectNotFoundException is not a Domain Exception
You are not at the domain level yet, so calling the identifier as a ValueObject is incorrect
Ignoring Application Services for a moment, you are spot on in your usage of the concept. The code example is correct in structure. It's just the terms that need to be clarified.

Using HttpContext.Current in WebApi is dangerous because of async

My question is a bit related to this: WebApi equivalent for HttpContext.Items with Dependency Injection.
We want to inject a class using HttpContext.Current in WebApi area using Ninject.
My concern is, this could be very dangerous, as in WebApi (everything?) is async.
Please correct me if I am wrong in these points, this is what I investigated so far:
HttpContext.Current gets the current context by Thread (I looked into the implementation directly).
Using HttpContext.Current inside of async Task is not possible, because it can run on another Thread.
WebApi uses IHttpController with method Task<HttpResponseMessage> ExecuteAsync => every request is async => you cannot use HttpContext.Current inside of action method. It could even happen, more Request are executed on the same thread by coicidence.
For creating controllers with injected stuff into constructors IHttpControllerActivator is used with sync method IHttpController Create. This is, where ninject creates Controller with all its dependencies.
If I am correct in all of these 4 points, using of HttpContext.Current inside of an action method or any layer below is very dangerous and can have unexpected results. I saw on StackOverflow lot of accepted answers suggesting exactly this. In my opinion this can work for a while, but will fail under load.
But when using DI to create a Controller and its dependencies, it is Ok, because this runs on one separated thread. I could get a value from the HttpContext in the constructor and it would be safe?. I wonder if each Controller is created on single thread for every request, as this could cause problem under heavy loads, where all threads from IIS could be consumed.
Just to explain why I want to inject HttpContext stuff:
one solution would be to get the request in controller action method and pass the needed value all the layers as param until its used somewhere deep in the code.
our wanted solution: all the layers between are not affected by this, and we can use the injected request somewhere deep in code (e.g. in some ConfigurationProvider which is dependent on URL)
Please give me your opinion if I am totally wrong or my suggestions are correct, as this theme seems to be very complicated.
HttpContext.Current gets the current context by Thread (I looked into the implementation directly).
It would be more correct to say that HttpContext is applied to a thread; or a thread "enters" the HttpContext.
Using HttpContext.Current inside of async Task is not possible, because it can run on another Thread.
Not at all; the default behavior of async/await will resume on an arbitrary thread, but that thread will enter the request context before resuming your async method.
The key to this is the SynchronizationContext. I have an MSDN article on the subject if you're not familiar with it. A SynchronizationContext defines a "context" for a platform, with the common ones being UI contexts (WPF, WinPhone, WinForms, etc), the thread pool context, and the ASP.NET request context.
The ASP.NET request context manages HttpContext.Current as well as a few other things such as culture and security. The UI contexts are all tightly associated with a single thread (the UI thread), but the ASP.NET request context is not tied to a specific thread. It will, however, only allow one thread in the request context at a time.
The other part of the solution is how async and await work. I have an async intro on my blog that describes their behavior. In summary, await by default will capture the current context (which is SynchronizationContext.Current unless it is null), and use that context to resume the async method. So, await is automatically capturing the ASP.NET SynchronizationContext and will resume the async method within that request context (thus preserving culture, security, and HttpContext.Current).
If you await ConfigureAwait(false), then you're explicitly telling await to not capture the context.
Note that ASP.NET did have to change its SynchronizationContext to work cleanly with async/await. You have to ensure that the application is compiled against .NET 4.5 and also explicitly targets 4.5 in its web.config; this is the default for new ASP.NET 4.5 projects but must be explicitly set if you upgraded an existing project from ASP.NET 4.0 or earlier.
You can ensure these settings are correct by executing your application against .NET 4.5 and observing SynchronizationContext.Current. If it is AspNetSynchronizationContext, then you're good; if it's LegacyAspNetSynchronizationContext, then the settings are wrong.
As long as the settings are correct (and you are using the ASP.NET 4.5 AspNetSynchronizationContext), then you can safely use HttpContext.Current after an await without worrying about it.
I am using a web api, which is using async/await methodology.
also using
1) HttpContext.Current.Server.MapPath
2) System.Web.HttpContext.Current.Request.ServerVariables
This was working fine for a good amount of time which broke suddenly for no code change.
Spending a lot of time by reverting back to previous old versions, found the missing key causes the issue.
< httpRuntime targetFramework="4.5.2" /> under system.web
I am not an expert technically. But I suggest to add the key to your web config and give it a GO.
I found very good article describing exactly this problem: http://byterot.blogspot.cz/2012/04/aspnet-web-api-series-part-3-async-deep.html?m=1
author investigated deeply, how the ExecuteAsync method is called in the WebApi framework and came to this conclusion:
ASP.NET Web API actions (and all the pipeline methods) will be called asynchronously only if you return a Task or Task<T>. This might sound obvious but none of the pipeline methods with Async suffix will run in their own threads. Using blanket Async could be a misnomer. [UPDATE: ASP.NET team indeed have confirmed that the Async is used to denote methods that return Task and can run asynchronously but do not have to]
What I understood from the article is, that the Action methods are called synchronously, but it is the caller decision.
I created a small test app for this purpose, something like this:
public class ValuesController : ApiController
{
public object Get(string clientId, string specialValue)
{
HttpRequest staticContext = HttpContext.Current.Request;
string staticUrl = staticContext.Url.ToString();
HttpRequestMessage dynamicContext = Request;
string dynamicUrl = dynamicContext.RequestUri.ToString();
return new {one = staticUrl, two = dynamicUrl};
}
}
and one Async version returning async Task<object>
I tried to do a little DOS attack on it with jquery and could not determine any issue until I used await Task.Delay(1).ConfigureAwait(false);, which is obvious it would fail.
What I took from the article is, that the problem is very complicated and Thread switch can happen when using async action method, so it is definetly NOT a good idea to use HttpContext.Current anywhere in the code called from the action methods. But as the controller is created synchronously, using HttpContext.Current in the constructor and as well in dependency injection is OK.
When somebody has another explanation to this problem please correct me as this problem is very complicated an I am still not 100% convinced.
diclaimer:
I ignore for now the problem of self-hosted Web-Api withoud IIS, where HttpContext.Current would not work probably anyway. We now rely on IIS.

ServiceStack message queue handling and Profiler

I'm currently trying out the persistent mini profiler feature of ServiceStack and I'm currently having trouble registering profile information for my Redis Message Queue handlers.
A bit more background:
I have some regular REST api handlers which takes in a request, defers some updates of account information and replies OK back to the caller. These messages are posted to a Redis server, using the ServiceStack Redis MQ pattern. Therefore, the Redis message handling is registered as:
var redisFactory = new PooledRedisClientManager(redisClients);
var mqHost = new RedisMqServer(redisFactory, retryCount: 2);
var defaultThreadCount = 4;
mqHost.RegisterHandler<SomeDto>(m => this.ServiceController.ExecuteMessage(m), noOfThreads:defaultThreadCount);
mqHost.RegisterHandler<SomeOtherDto>(m => this.ServiceController.ExecuteMessage(m), noOfThreads:defaultThreadCount);
mqHost.Start();
And my messages are being handled properly too.
In a custom ServiceRunner I've enabled profiling of all requests in the BeforeEachRequest and added a custom Profiler step like this:
public override void BeforeEachRequest(IRequest requestContext, T request)
{
Profiler.Start();
using (Profiler.StepStatic("Executing handler"))
{
base.BeforeEachRequest(requestContext, request);
}
}
All my HTTP REST requests are making it to the SQL tables, but none of the MQ handler calls are registered. And I'm 100% confident that the handlers are indeed being executed, since the result of that execution is stored in a MongoDB collection.
Anything I'm missing?
-- EDIT --
I forgot to mention that this project is indeed hosted via an ASP.NET application. The AppHost is initialized in Global.asax App_Start - I just found it more convenient to have "before request" handing in a custom service runner rather than the ASP.NET Begin_Request handler.
I have a similar problem with a self hosted server. The problem is that the profiler uses HttpContext.Current to store the profiling results. If there is no valid context it does not know which profiling 'session' to add the results to.
It is possible to implement your own ProfilingProvider by setting Profile.Settings.ProfilingProvider, but, unless I am missing something, it will be tricky (if not impossible) to implement this properly in an Async environment with the current IProfilerProvider interface.
I wrote a very simple and naive provider which you can use for profiling. This will not pick up any of the steps that ServiceStack already adds by default, but it might still be useful for your own debugging.
Example use:
Profiler.Settings.ProfilerProvider = RequestProfilerProvider.Instance;
PreRequestFilters.Add((req, res) => RequestProfiler.Start(req));
GlobalRequestFilters.Add((req, res, dto) => {
var profiler = RequestProfiler.GetProfiler(req);
using (profiler.Step("Very slow step")) {
Thread.Sleep(1000);
}
});
GlobalResponseFilters.Add((req, res, dto) => RequestProfiler.Stop(req));

Global request/response interceptor

What would be the easiest way to setup a request/response interceptor in ServiceStack that would execute for a particular service?
A request filter (IHasRequestFilter) works fine but a response filter (IHasResponseFilter) is not triggered if the service returns non 2xx status code. I need to retrieve the status code returned by the method as well as the response DTO (if any).
A custom ServiceRunner and overriding the OnBeforeExecute and OnAfterExecute methods seems to work fine but I find it pretty intrusive as the service runner need to be replaced for the entire application and I couldn't find a way clean way to isolate per functionality the tasks that need to be executed in those methods.
Is there some extension point in ServiceStack that I am missing that would allow me to execute some code before each service method and after each service method? A plugin would be ideal but how can I subscribe to some fictitious BeforeExecute and AfterExecute methods that would allow me to run some custom code?
UPDATE:
Just after posting the question I found out that global response filters are executed no matter what status code is returned by the service which is exactly what I needed. So one last question: Is it possible to retrieve the service type that will handle the request in a request filter? I need to check whether this service is decorated by some custom marker attribute.
I have found out a solution to my question about how to retrieve the service type in a custom request/response filter:
appHost.RequestFilters.Add((req, res, requestDto) =>
{
var metadata = EndpointHost.Metadata;
Type serviceType = metadata.GetServiceTypeByRequest(requestDto.GetType());
...
}
A custom ServiceRunner and overriding the OnBeforeExecute and OnAfterExecute methods seems to work fine but I find it pretty intrusive as the service runner need to be replaced for the entire application
Quick note, you can opt-in and choose only what requests should use a custom service runner, e.g:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(
ActionContext actionContext)
{
return useCustomRunner(actionContext.RequestType)
? new MyServiceRunner<TRequest>(this, actionContext)
: base.CreateServiceRunner<TRequest>(actionContext);
}
IHttpRequest has OperationName. I think thats what you are after.

Resources