Yavor is a PM at Snowflake working on developer experience. Previously at Docker, Auth0, Hulu, and Microsoft Azure.
21 December 2012
Update: Corrected the server script code snippet.
Update 2:The example below will unfortunately no longer work due to Twitter API changes… I need to update it. In the mean time, our official documentation shows a very similar scenario, so check that out.
As Scott announced earlier today, Mobile Services is celebrating the holiday season by bringing you some cool new features, including the ability to execute scheduled jobs (or “cron jobs”).
"Windows Azure Mobile Services now supports the ability to easily schedule background jobs (aka CRON jobs) that execute on a pre-set timer interval, and which can run independently of a device accessing the service (ensuring that you don’t block or slow-down any requests from your users). This job scheduler functionality allows you to perform a variety of useful scenarios without having to create or manage a separate VM."
Some of the scenarios you can enable with it include:
Here I want to give a more detailed demonstration of the feature and celebrate another winter tradition: skiing. Let’s walk through a simple scenario where we will use a scheduled job to aggregate and analyze tweets related to ski conditions near Seattle. The source code is available here.
Let’s assume we already have a mobile service called skibuddy. We can navigate to the new Scheduler tab in the Windows Azure portal to create a scheduled job.
Let’s go ahead and create a job called getUpdates. We will use the default interval of 15 minutes that is already selected in the dialog.
Once the job is created we will now see it in the summary view. You will note that the job starts off as disabled, so let’s click the job name to add our script.
On the job details page, we see information about our job and also we also have an opportunity to change the schedule. For now let’s leave everything as-is and navigate over to the Script tab.
Here we see the script editor window that has been pre-populated with a default empty script.
Let’s replace the default script with the following one.
var updatesTable = tables.getTable('updates');
var request = require('request');
function getUpdates() {
// Check what is the last tweet we stored when the job last ran
// and ask Twitter to only give us more recent tweets
appendLastTweetId(
'http://search.twitter.com/search.json?q=ski%20weather&result_type=recent&geocode=47.593199,-122.14119,200mi&rpp=100',
function twitterUrlReady(url){
request(url, function tweetsLoaded (error, response, body) {
if (!error && response.statusCode == 200) {
var results = JSON.parse(body).results;
if(results){
console.log('Fetched new results from Twitter');
results.forEach(function visitResult(tweet){
if(!filterOutTweet(tweet)){
var update = {
twitterId: tweet.id,
text: tweet.text,
author: tweet.from_user,
location: tweet.location || "Unknown location",
date: tweet.created_at
};
updatesTable.insert(update);
}
});
}
} else {
console.error('Could not contact Twitter');
}
});
});
}
// Find the largest (most recent) tweet ID we have already stored
// (if we have stored any) and ask Twitter to only return more
// recent ones
function appendLastTweetId(url, callback){
updatesTable
.orderByDescending('twitterId')
.read({success: function readUpdates(updates){
if(updates.length){
callback(url + '&since_id=' + (updates[0].twitterId + 1));
} else {
callback(url);
}
}});
}
function filterOutTweet(tweet){
// Remove retweets and replies
return (tweet.text.indexOf('RT') === 0 || tweet.to_user_id);
}
Here is what the script does:
Now that we’ve entered the script, we can press the Save button and then select Run once to execute a trial run. The Run once functionality lets you easily test out your job script before you enable the job for recurring execution.
Once you run the script, head over to the Data tab on the main page for your mobile service and select the updates table.
You should see it has now been populated with the tweet data we fetched in our job. Our mobile clients can now read the data from that table and display it to their users.
Next, open the Logs tab from the main portal page for your mobile service.
You should see an entry generated by our scheduled job script. Any calls to the console API from your job script and all errors generated by that script will be logged here. This makes the Logs table very useful while debugging and monitoring your scheduled job.
Now that we have made sure the job is working as expected, we are ready to enable it. We can go back to the Scheduler tab, select our job, and click Enable.
Once the job has run for a while, we can check the updates table and also the logs to ensure it is executing. If we return to the Scheduler tab, it conveniently provides last run and next run data for the job.
This was a quick overview of the new scheduled jobs feature in Mobile Services. I’ll skip the rest of the app implementation as it has been covered many times, you can find the source at the GitHub link above.
Here are some extra details on the feature that we didn’t get to cover: