Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Start long-running action from Web API Controller

I'm porting existing, self-hosted WCF service to IIS-hosted Web API.

Service is intended to execute long running action, and client (desktop applications) could initiate action, and either wait for result, or disconnect from service (even turn off), and come back for result later.

At the moment, WCF service have such contact (sessions are not allowed):

public interface IMyServiceContract
{
    // this initiates the action and returns the action id
    int StartAction(ActionParams actionParams);

    // this allows client to query action status (running, completed, faulted)
    ActionStatus GetActionStatus(int actionId);

    // this allows client to download action result, if action was completed
    ActionResult GetActionResult(int actionId);
}

ActionParams and ActionResult are some data contracts, which contain input parameters and resulting values (it doesn't matter, what is inside in the context of the question).

StartAction method creates an action id, starts a task via Task.Factory.StartNew, and returns. Client periodically polls the service, calling GetActionStatus method, and, if it was completed, client downloads the result, using GetActionResult.

Note, that user can initiate action, and shut down computer, running client application, but later he can download action result.

The question. What is approach to do such things using Web API?

I've read some questions at SO, and tutorials at asp.net, but the samples are built very similar: they implement an awaitable method and call async API (e.g., from EF 6). As far, as I understand, this doesn't allows scenario "disconnect and download result later".

Moreover, this post from Stephen Cleary tells:

That’s why one of the principles of ASP.NET is to avoid using thread pool threads (except for the request thread that ASP.NET gives you, of course). More to the point, this means that ASP.NET applications should avoid Task.Run.

Am I missing something?

like image 263
Dennis Avatar asked Jul 24 '26 13:07

Dennis


1 Answers

I'm using Hangfire.io for long running tasks. Hangfire uses a database and makes sure that a task is executed, even if the website (or the application pool) is restarted.

It offers a pretty simple API:

BackgroundJob.Enqueue(() => LongRunningTask());

And it allows you to schedule tasks for executing later or for recurring Tasks:

BackgroundJob.Schedule(
    () => LongRunningTask(), 
    TimeSpan.FromDays(7));

RecurringJob.AddOrUpdate(
    () => LongRunningTask(), 
    Cron.Daily);

Statement from their Website:

Background jobs are being deleted from the storage only on successful execution. Abruptly aborted jobs will be requeued after application restart.
Once a job was created, it will be performed at least once, even if the host process was terminated.

like image 64
MichaelS Avatar answered Jul 26 '26 04:07

MichaelS