Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fire and forget with ServiceStack's AsyncServiceBase

Tags:

servicestack

I have following service

public class AppService : AsyncServiceBase<EvaluateStock>
{
    public IBus Bus { get; set; }

    public override object ExecuteAsync(EvaluateStock request)
    {
        // this will block the incoming http request 
        // unitl task is completed

        // long computation
        // Bus.Publish(result)
    }
}

which gets called by different consumers following way

POST
http://srv1/app/json/asynconeway/EvaluateStock

Using asynconeway I was assuming that it will allow me to achieve fire and forget as WCF does with IsOneWay. But seems is not the case.

Do I miss something ?

like image 709
ruslander Avatar asked Jun 20 '12 16:06

ruslander


1 Answers

AsyncServiceBase has been deprecated as ExecuteAsync is now in ServiceBase which is what gets called when a request is made to /asynconeway/XXX pre-defined endpoint.

Rather than overriding ExecuteAsync the recommended approach is to implement IMessageFactory which is what gets called if an IMessageFactory has been registered in the AppHost IOC. If an IMessageFactory wasn't registered than it just gets executed Sync - at which point if you still wanted it non-blocking you would override it. The impl for ExecuteAsync is at:

// Persists the request into the registered message queue if configured, 
// otherwise calls Execute() to handle the request immediately.
// 
// IAsyncService.ExecuteAsync() will be used instead of IService.Execute() for 
// EndpointAttributes.AsyncOneWay requests
public virtual object ExecuteAsync(TRequest request)
{
    if (MessageFactory == null)
    {
        return Execute(request);
    }

    BeforeEachRequest(request);

    //Capture and persist this async request on this Services 'In Queue' 
    //for execution after this request has been completed
    using (var producer = MessageFactory.CreateMessageProducer()) {
        producer.Publish(request);
    }

    return ServiceUtils.CreateResponseDto(request);
}

IMessageFactory (client)/IMessageService (server) is apart of ServiceStack's Messaging API which allows you to publish messages for deferred execution later. See the Redis and Messaging wiki for an example of an end-to-end solution that uses the built-in Redis IMessageService. There are also InMemory and RCon IMesssageService's available and it should be easy to create your own as well.

Future Async support

There is also an async branch that has ServiceStack running on IHttpAsyncHandler and already has a functional alpha build available for you to try at: ServiceStack-v4.00-alpha.zip

With this change ServiceStack supports Task<> as a return type on services. You only need to register the Task<> plugin. To see a full example look at this integration test.

like image 138
mythz Avatar answered Nov 17 '22 14:11

mythz