Synchronizing Asynchronous Events in Salesforce.com

So the title is slightly dubious as you really can't synchronize asynchronous events in salesforce.com. However, here's a strategy to make asynchronous events more manageable.

Don't get me wrong, asynchronous events (Apex methods with the @future annotation) are awesome. You get higher limits, they fire when the platform has spare cycles and users don't have to wait for processing to finish. However, if you use them liberally in your application, orchestrating them may become difficult.

So here's the situation we ran into at CloudSpokes and how I finally solved the issue. I may be a bit slow but it took a few iterations.

So if you haven't been to CloudSpokes (shame on you if you haven't!!) we run development challenges for cash, prizes, badges and bragging right. A good majority of our challenges are Force.com related. So we run a challenge like Multiple Campaign Picker and a number of developers submit solutions for the challenge. After the challenge closes for submissions, multiple judges score each developer's submission. Here's the problem: all of our scoring is done asynchronously. So when a judge submits a scorecard for a developer it is scored asynchronously. When all of the judges have submitted all of their scorecards for a developer, the developer is given a final score, again asynchronously. Then when all of the developers have been scored by all of the judges, the entire challenge is scored.... you guessed it, asynchronously.

The issue we were running into was that because of the asynchronous nature of the event processing the final scoring for the challenge was being done (occasionally) before that last developer was scored. At first I thought a simple sleep() would work at the beginning of the final challenging scoring. This would give the platform some time to score that final developer. However, as you know, there is no sleep() on Force.com as it would tie up valuable shared resources.

I then wrote batch job that I kicked off when the final developer was scored. The job was schedule to run in two minutes. That quickly hit the limit of scheduled tasks available and I didn't really like the solution anyway.

Note: a queue in Force.com would be awesome in this circumstance and Taggart Matthiesen mentioned in a recent webinar that it is on the roadmap. (Be still my beating heart.)

So here's the solution that I can up with. I went back to good 'ole workflow. Never do programmatically what you can do declaratively, I always say. So I wrote a workflow that fires on the challenge object when the number of scored developers equals the number of developers participating. The workflow runs a time-dependent action that fires "0 Hours After Rule Trigger Date" and changes a picklist value. My trigger catches this change and fires the Apex code to score the entire challenge. Viola! Problem solved with point-and-click programming!

There are some limitations with this workflow method but they are minor. Time-based triggers don't support minutes or seconds. I think the documentation states that they fire within an hour but I read on the developerforce boards once that it's generally 15 minutes or so. I've noticed that most of ours fire around 5 minutes or so.