Scheduling a background thread to run exactly once

Not applicable

OK, so the setTimeout()/setInterval() trick works great, and the background job starts up as expected and runs without any obvious timeouts.

But when I look at the logs, there's two servers working on our backend, and the background job starts up on both at once, which is bad because this job has to update the BaaS.

What I really want is a way to schedule a job to run on exactly one backend server at a time. I could do this by adding in an HTTP handler and triggering that from one of the many third-party "web cron" services, but I'd rather avoid third parties if possible.

Is there any way to do this from within Apigee?

Solved Solved
1 6 780
1 ACCEPTED SOLUTION

Not applicable

HI @Nick Moore,

Each servers running in own Message Processor independently, and no way to define MP inside your app. However application cache is common storage for all MPs.

So i can suggest you next approach.

- Start first server,

- Clear cache, then generate id based on timestamp and push this id into cache.

- Set timer

- On callback you check if your id is active, if yes - continue....

Second server clear cache on init so only last restarted MP will have active id. First server would not escalate duplicated flow.

Here is my Git https://github.com/vatsenko/APIGEE-Scheduler

For some reason this approach not works with express ... however this depends on version i think.

Hope this helps

View solution in original post

6 REPLIES 6

Yes @Nick Moore any node.js process runs in each of Apigee's MPs so this is expected.

If it is purely a timestamp triggered action Apigee is not the right place. If the trigger is related to an incoming API request, the setTimeout call can be made in the scope of the request to do the action once. This would make it work only the on the MP that processes the incoming request.

I can think of some other options, can you add more details on the usecase please.

Not applicable

Yep, I'd seen that one and the approach will work, but I'm trying to avoid third-party "web cron" services for company policy reasons. Cheers, -----Nick

Not applicable

HI @Nick Moore,

Each servers running in own Message Processor independently, and no way to define MP inside your app. However application cache is common storage for all MPs.

So i can suggest you next approach.

- Start first server,

- Clear cache, then generate id based on timestamp and push this id into cache.

- Set timer

- On callback you check if your id is active, if yes - continue....

Second server clear cache on init so only last restarted MP will have active id. First server would not escalate duplicated flow.

Here is my Git https://github.com/vatsenko/APIGEE-Scheduler

For some reason this approach not works with express ... however this depends on version i think.

Hope this helps

Thanks @i.vatsenko , yeah I think that'd work and its an interesting take on breaking a race condition. If N servers all try to update the record, we elect the winner as the node which came in last! For a job which only runs on a schedule every few hours I think this would be workable.

I ended up implementing a similar thing using the cache for IPC and it seems to be working great. Each process setTimeout()s to the same point in time, then writes a random nonce into a single cache entry and then checks back a couple of seconds later to see if it is still there. Since all processes use the same cache entry, only one will succeed ... the others wait for the next cycle. This should generalize pretty well to a larger number of servers. Thanks for your help!