Search code examples
c#azureazure-webjobsazure-webjobs-continuousazure-webjobs-triggered

Can I query the Azure web job queue?


I have two Azure Web Jobs running within my Azure web app:

  • Job A - running continuously
  • Job B - triggered

Job A's purpose is to trigger Job B based on two things:

  1. Job B has not been run in the past hour for a specified account number (passed into Job B as a param from Job A.
  2. Some other business logic determined from the database

#2 is easy. It's #1 that I have a question about. Is it possible for Job A query the web job queue to see if Job B has been executed?

Here is Job B (triggered):

public class Functions
{
    public static void ProcessQueueMessage([QueueTrigger("triggeredqueue")] string message, TextWriter log)
    {
        var accountId = message;
        //DO STUFF WITH accountId HERE...
    }
 }

And here is Job A (running continuously). I've added code in comments to show what I would like to do:

class Program
{
    static void Main()
    {
        while (true)
        {
            var accounts = getAccounts();
            foreach (var account in accounts) {
                if (testOtherBusinessLogic(account)) {
                    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConnectionStringHelper.StorageConnectionString);
                    CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
                    CloudQueue queue = queueClient.GetQueueReference("triggeredqueue");
                    queue.CreateIfNotExists();
                    //THIS IS WHAT IT IS DOING NOW:
                    CloudQueueMessage message = new CloudQueueMessage(account.AccountId);
                    queue.AddMessage(message);
                    //THIS IS WHAT I WOULD LIKE IT TO DO:
                    /* 
                    if (!queue.Any(x => x.RunDate > (DateTime.Now.AddMinutes(-60)) && x.Message == account.AccountId.ToString()) {                          
                        CloudQueueMessage message = new CloudQueueMessage(account.AccountId);
                        queue.AddMessage(message);
                    }
                    */
                }
            }
            System.Threading.Thread.Sleep(7000);
        }
    }
}

Solution

  • Azure storage queue doesn't support query operations. And note that once your queuetrigger runs, the message triggered it will be no long in the queue. Besides, your JobB should also be running continuously to listen changes on the queue.

    I recommend you to use table storage to store the execution date. Have a try with code below.

    // Add table entity class in JobA Program class and JobB Functions class
    class MyEntity : TableEntity
    {
        public DateTime ExecutionTime { get; set; }
    }
    
    
    //In JobA, achieve what you would like to do 
     var accountId = account.AccountId;
     CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
     CloudTable table = tableClient.GetTableReference("execution");
     table.CreateIfNotExists();
    
     // table entity use combination of partionkey and rowkey as entity identifier, so I set both of them to accountId
     TableOperation retriveOperation = TableOperation.Retrieve<MyEntity>(accountId, accountId);
    
     MyEntity retriveEntity = (MyEntity)table.Execute(retriveOperation).Result;
    
     if (retriveEntity != null)
     {
         if (retriveEntity.ExecutionTime> DateTime.UtcNow.AddMinutes(-60))
         {
             CloudQueueMessage message = new CloudQueueMessage(accountId);
             queue.AddMessage(message);
         }
     }else
     {
         CloudQueueMessage message = new CloudQueueMessage(accountId);
         queue.AddMessage(message);
     }
    
    
     //In JobB, add operations to store execution time after business logic 
     //Connection operations omitted, please add by yourself.
     CloudTable table = tableClient.GetTableReference("execution");
     table.CreateIfNotExists();
     TableOperation retriveOperation = TableOperation.Retrieve<MyEntity>(accountId, accountId);
     MyEntity retriveEntity = (MyEntity)table.Execute(retriveOperation).Result;
    
     if (retriveEntity != null)
     {
          retriveEntity.ExecutionTime = DateTime.UtcNow;
          TableOperation updateOperation = TableOperation.Replace(retriveEntity);
          table.Execute(updateOperation);
     }
     else
     {
          retriveEntity = new MyEntity
          {
               ExecutionTime = DateTime.UtcNow,
               PartitionKey = accountId,
               RowKey = accountId
           };
          TableOperation insertOperation = TableOperation.Insert(retriveEntity);
          table.Execute(insertOperation);
     }
    

    Last suggestion, it seems not necessary to use queuetrigger, you can use only JobA to achieve your goal(DO STUFF WITH accountId directly in JobA).