Search code examples
c#.netazureazure-web-rolesazure-worker-roles

Worker Role process - Configuration value polling


I have a Worker Role which processes items off a queue. It is basically an infinite loop which pops items off of the queue and asynchronously processes them.

I have two configuration settings (PollingInterval and MessageGetLimit) which I want the worker role to pick up when changed (so with no restart required).

private TimeSpan PollingInterval 
{
    get
    {
        return TimeSpan.FromSeconds(Convert.ToInt32(RoleEnvironment.GetConfigurationSettingValue("PollingIntervalSeconds")));
    }
}

private int MessageGetLimit 
{ 
    get 
    {
        return Convert.ToInt32(RoleEnvironment.GetConfigurationSettingValue("MessageGetLimit"));
    } 
}

public override void Run()
{
    while (true)
    {
        var messages = queue.GetMessages(MessageGetLimit);

        if (messages.Count() > 0)
        {
            ProcessQueueMessages(messages);
        }
        else
        {
            Task.Delay(PollingInterval);
        }
    }
}

Problem:

During peak hours, the while loop could be running a couple of times per second. This means that it would be querying the config items up to 100,000 times per day.

Is this detrimental or inefficient?


Solution

  • Upfront disclaimer, I haven't used RoleEnvironments.

    The MDSN documentation for GetConfigurationSettingValue states that the configuration is read from disk. http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.serviceruntime.roleenvironment.getconfigurationsettingvalue.aspx. So it is sure to be slow when called often.

    The MSDN documentation also shows that there is an event fired when a setting changes. http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.serviceruntime.roleenvironment.changed.aspx. You can use this event to only reload the settings when they have actually changed.

    Here is one (untested, not compiled) approach.

    private TimeSpan mPollingInterval;
    private int mMessageGetLimit;
    
    public override void Run()
    {
        // Refresh the configuration members only when they change.
        RoleEnvironment.Changed += RoleEnvironmentChanged;
    
        // Initialize them for the first time
        RefreshRoleEnvironmentSettings();
    
        while (true)
        {
            var messages = queue.GetMessages(mMessageGetLimit);
    
            if (messages.Count() > 0)
            {
                ProcessQueueMessages(messages);
            }
            else
            {
                Task.Delay(mPollingInterval);
            }
        }
    }
    
    private void RoleEnvironmentChanged(object sender, RoleEnvironmentChangedEventArgs e)
    {
        RefreshRoleEnvironmentSettings();    
    }
    
    private void RefreshRoleEnvironmentSettings()
    {
        mPollingInterval = TimeSpan.FromSeconds(Convert.ToInt32(RoleEnvironment.GetConfigurationSettingValue("PollingIntervalSeconds")));
        mMessageGetLimit = Convert.ToInt32(RoleEnvironment.GetConfigurationSettingValue("MessageGetLimit"));
    }