Probably a common pattern, but I haven't been able to find any help.
I have an ASP.NET web application hosting Quartz, and I have job that fires on schedule. The job calls a remote WCF service:
public class SimpleJob : IJob {
public SimpleJob() {
}
public void Execute(IJobExecutionContext context) {
// call some remote service at
// http://someserver.com/someservice.svc/StartSomething
// that could take hours to complete
}
}
The StartSomething endpoint will run for a long time, so I cannot just wait for an http response 200. But, when it's done, I want the remote process to tell Quartz that it's done, thereby activating my IJobListener, and also do it's regular Quartz stuff. So, it's a fire-and-forget job, with a callback.
How can I accomplish this?
Idea 1
I could create an endpoint in my own application, like this:
http://myserver.com/Quartz/JobComplete?jobId=1234
The remote service would call this endpoint. But, what's the Quartz API to tell Quartz that a job has completed?
Idea 2
After posting this question, and reading some more, I found a different solution. It would work, but seems like it would really mess with Quartz's thread pool. Here's the link: http://www.interworks.com/blogs/banderton/2009/10/30/long-running-tasks-aspnet. In short, my IJob implementation would go into a loop, polling the remote service until it's done.
public void Execute(IJobExecutionContext context) {
var jobComplete = false;
// call remote service
while(jobComplete == false){
var currentJobStatus = // ge tstatus from remote service
if(status == complete) {
jobComplete = true;
}
}
}
Idea 3
Another route would be some kind of WCF Pub/Sub. Perhaps a WCF duplex callback. But, I read that it's flaky and I should avoid it: Best practice for WCF Duplex client. But, if that's wrong, I'm willing to try it. I've also read that this pattern can be accomplished with MSMQ over WCF. But, it sounds like (without Azure Queue) that's a trail of tears.
Still, with any Pub/Sub I've got the issue of telling Quartz that the job has ended. How would I do that?
I hope I understand your question, I would suggest going with Idea 1 with some modifications.
You could define two jobs with the following flow (a sort of a two-step job):
I would recommend that in step 2 you create a job with a later trigger to act as a timeout in case the remote service never calls your endpoint back.