Adding a Azure worker role

Posted on 12/27/2011 @ 2:47 AM in #Azure by | Feedback | 5421 views

This blogpost is part of a series on “Writing an Azure application and integrating it with SharePoint Securely”.

Table of Contents -

  1. Writing a simple MVC app
  2. Porting our MVC app to Azure – adding table storage.
  3. Adding a worker role <—You are here!
  4. Deploying the application to Azure
  5. Integrating this Azure application with SharePoint


In my previous articles, I talked about writing an MVC app that had nothing to do with Azure. Then with not a lot of effort, I was able to move it into Azure. In the process we also leveraged Azure Table storage, and I described some of the basic concepts around that.

In this article, I will add a worker role that processes the data collected by the web role.

The first thing we are going to do is enhance the controller so it also stores the message on the queue.

  1:         [HttpPost]
  2:         public ViewResult Index(Complaint complaint)
  3:         {
  4:             CloudStorageAccount storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
  5:             CloudTableClient.CreateTablesFromModel(
  6:                 typeof(ComplaintContext),
  7:                 storageAccount.TableEndpoint.AbsoluteUri,
  8:                 storageAccount.Credentials);
  9: 
 10:             ComplaintContext context = new ComplaintContext(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials);
 11:             context.RetryPolicy = RetryPolicies.Retry(3, TimeSpan.FromSeconds(1));
 12: 
 13:             context.AddObject("ComplaintEntry", complaint);
 14:             context.SaveChanges();
 15: 
 16:             CloudQueueClient queueStorage = storageAccount.CreateCloudQueueClient();
 17:             CloudQueue queue = queueStorage.GetQueueReference("complaints");
 18:             queue.CreateIfNotExist();
 19:             
 20:             var message = new CloudQueueMessage(String.Format("{0},{1},{2}", complaint.RowKey, complaint.PartitionKey, complaint.Title));
 21:             queue.AddMessage(message);
 22: 
 23:             return View("Thanks", complaint);
 24:         }

Next, in the Azure project, right click on the “Roles” node, and choose to add a new WorkerRole project. Call it “ProcessComplaint”.

The ProcessComplaint project will have a worker role in it, with two methods –OnStart and Run. OnStart is a perfect place for us to initialize the queue.

Start by adding a references in ProcessComplaint to the following,

- ComplaintBox project

- System.Data.Services.Client

This can be done using the following code,

  1:         public override bool OnStart()
  2:         {
  3:             // Set the maximum number of concurrent connections 
  4:             ServicePointManager.DefaultConnectionLimit = 12;
  5: 
  6:             // For information on handling configuration changes
  7:             // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
  8: 
  9:             CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
 10:             {
 11:                 configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
 12:             });
 13:             var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
 14:             CloudQueueClient queueStorage = storageAccount.CreateCloudQueueClient();
 15:             queue = queueStorage.GetQueueReference("complaints");
 16:             queue.CreateIfNotExist();
 17: 
 18:             return base.OnStart();
 19:         }

Processing on the message is equally easy.

In order to process the message, we continuously run inside the “Run” method until a message becomes available. Soon as a message is available, we process it

This is done using the following code in the Run method.

  1: public override void Run()
  2:         {
  3:             // This is a sample worker implementation. Replace with your logic.
  4:             Trace.WriteLine("$projectname$ entry point called", "Information");
  5: 
  6:             while (true)
  7:             {
  8:                 CloudQueueMessage msg = queue.GetMessage();
  9:                 if (msg != null)
 10:                 {
 11:                     var messageParts = msg.AsString.Split(new char[] { ',' });
 12:                     var rowKey = messageParts[0];
 13:                     var partitionKey = messageParts[1];
 14:                     var title = messageParts[2];
 15: 
 16:                     CloudStorageAccount storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
 17:                     CloudTableClient.CreateTablesFromModel(
 18:                         typeof(ComplaintContext),
 19:                         storageAccount.TableEndpoint.AbsoluteUri,
 20:                         storageAccount.Credentials);
 21: 
 22:                     ComplaintContext context = new ComplaintContext(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials);
 23:                     context.RetryPolicy = RetryPolicies.Retry(3, TimeSpan.FromSeconds(1));
 24: 
 25:                     var results = from complaint in context.ComplaintEntry
 26:                                   where complaint.PartitionKey == partitionKey && complaint.RowKey == rowKey
 27:                                   select complaint;
 28: 
 29:                     var entry = results.FirstOrDefault<Complaint>();
 30:                     entry.IsProcessed = true;
 31:                     context.UpdateObject(entry);
 32:                     context.SaveChanges();
 33: 
 34:                     queue.DeleteMessage(msg);
 35:                 }
 36:             }
 37:         }

You would note that the code is quite familiar and similar to what you have already seen. Perhaps there is an extra linq query here. For fun, try doing a .ToString() in debug mode on the var results linq query. What do you see? You should see a REST API URL.

There is one thing missing however! If you right click/properties on the two roles in the ComplaintBox.Azure project, under the “Settings” part, you will need to add a connection string in either as shown below,

Now, go ahead and run the application. Enter a few complaints, and you would note that the worker role picks them up via the queue, and marks their “IsProcessed” to true. This can be seen as shown below,

Awesome! Our application is now complete and running very well locally! It’s time to move this into Azure! The real Azure!

Sound off but keep it civil:

Older comments..