I've created an Azure Function that is triggered by a timer, which connects to a storage queue and grabs the next few messages, it runs every minute:
using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.WindowsAzure.Storage;
using Newtonsoft.Json;
using VS.Core.JobRunner;
namespace VS.JobRunner {
public static class JobRunner {
[FunctionName("JobRunner")]
public static void Run([TimerTrigger("0 */1 * * * *")]TimerInfo myTimer, TraceWriter log) {
var storageAccount = CloudStorageAccount.Parse(
"DefaultEndpointsProtocol=https;AccountName=xxxxxxxxx;AccountKey=xxxxxxxxxxxxxxxxxxxxxxxx;EndpointSuffix=core.windows.net");
var queueClient = storageAccount.CreateCloudQueueClient();
var queueWait = queueClient.GetQueueReference("jobs-waiting-uat");
var queueProcessing = queueClient.GetQueueReference("jobs-processing-uat");
var messages = queueWait.GetMessages(10, TimeSpan.FromSeconds(55));
foreach (var message in messages) {
log.Info($"Processing {message.AsString}");
queueWait.DeleteMessage(message);
try {
var jobMessage = JsonConvert.DeserializeObject<JobMessage>(message.AsString);
if (jobMessage.ExecuteTime <= DateTime.Now) {
log.Info($"Send message to processing queue.");
queueProcessing.AddMessage(message);
} else {
log.Info($"Requeue message.");
queueWait.AddMessage(message);
}
} catch (Exception ex) {
log.Error(ex.Message);
}
}
}
}
}
It deploys to Azure with no issues, and happily runs and does its thing. But when I try to run it locally to do some testing, it fails with the following:
[07/03/2018 18:09:01] Reading host configuration file 'C:\github\vs\VS.Jobs\VS.JobRunner\bin\UAT\net462\host.json'
[07/03/2018 18:09:01] Host configuration file read:
[07/03/2018 18:09:01] {}
[07/03/2018 18:09:01] Generating 1 job function(s)
[07/03/2018 18:09:01] Starting Host (HostId=vslaptopbg2-470926380, Version=2.0.11415.0, ProcessId=26736, Debug=False, ConsecutiveErrors=0, StartupCount=1, FunctionsExtensionVersion=~1)
[07/03/2018 18:09:01] Found the following functions:
[07/03/2018 18:09:01] VS.JobRunner.JobRunner.Run
[07/03/2018 18:09:01]
Listening on http://localhost:7071/
Hit CTRL-C to exit...
[07/03/2018 18:09:02] Host lock lease acquired by instance ID '0000000000000000000000009A12D146'.
[07/03/2018 18:09:02] Function started (Id=00f03472-4bee-4fe9-a8af-29e0ea4a1e8b)
[07/03/2018 18:09:02] Executing 'JobRunner' (Reason='Timer fired at 2018-03-07T18:09:02.4920152+00:00', Id=00f03472-4bfe-4fe9-a8af-29e0ea4a1e8b)
[07/03/2018 18:09:02] A ScriptHost error has occurred
[07/03/2018 18:09:02] Exception while executing function: JobRunner. VS.JobRunner: Method not found: 'System.Collections.Generic.IEnumerable`1<Microsoft.WindowsAzure.Storage.Queue.CloudQueueMessage> Microsoft.WindowsAzure.Storage.Queue.CloudQueue.GetMessages(Int32, System.Nullable`1<System.TimeSpan>, Microsoft.WindowsAzure.Storage.Queue.QueueRequestOptions, Microsoft.WindowsAzure.Storage.OperationContext)'.
[07/03/2018 18:09:02] Exception while executing function: JobRunner
[07/03/2018 18:09:02] Exception while executing function: JobRunner. VS.JobRunner: Method not found: 'System.Collections.Generic.IEnumerable`1<Microsoft.WindowsAzure.Storage.Queue.CloudQueueMessage> Microsoft.WindowsAzure.Storage.Queue.CloudQueue.GetMessages(Int32, System.Nullable`1<System.TimeSpan>, Microsoft.WindowsAzure.Storage.Queue.QueueRequestOptions, Microsoft.WindowsAzure.Storage.OperationContext)'.
[07/03/2018 18:09:02] Function completed (Failure, Id=00f03472-4bfe-4fe9-a8af-29e0ea4a1e8b, Duration=158ms)
[07/03/2018 18:09:02]
[07/03/2018 18:09:02] Executed 'JobRunner' (Failed, Id=00f03472-4bfe-4fe9-a8af-29e0ea4a1e8b)
[07/03/2018 18:09:02] System.Private.CoreLib: Exception while executing function: JobRunner. VS.JobRunner: Method not found: 'System.Collections.Generic.IEnumerable`1<Microsoft.WindowsAzure.Storage.Queue.CloudQueueMessage> Microsoft.WindowsAzure.Storage.Queue.CloudQueue.GetMessages(Int32, System.Nullable`1<System.TimeSpan>, Microsoft.WindowsAzure.Storage.Queue.QueueRequestOptions, Microsoft.WindowsAzure.Storage.OperationContext)'.
[07/03/2018 18:09:02] Function had errors. See Azure WebJobs SDK dashboard for details. Instance ID is '00f03472-4bfe-4fe9-a8af-29e0ea4a1e8b'
[07/03/2018 18:09:02] System.Private.CoreLib: Exception while executing function: JobRunner. VS.JobRunner: Method not found: 'System.Collections.Generic.IEnumerable`1<Microsoft.WindowsAzure.Storage.Queue.CloudQueueMessage> Microsoft.WindowsAzure.Storage.Queue.CloudQueue.GetMessages(Int32, System.Nullable`1<System.TimeSpan>, Microsoft.WindowsAzure.Storage.Queue.QueueRequestOptions, Microsoft.WindowsAzure.Storage.OperationContext)'.
[07/03/2018 18:09:02] The next 5 occurrences of the schedule will be:
[07/03/2018 18:09:02] 07/03/2018 18:10:00
[07/03/2018 18:09:02] 07/03/2018 18:11:00
[07/03/2018 18:09:02] 07/03/2018 18:12:00
[07/03/2018 18:09:02] 07/03/2018 18:13:00
[07/03/2018 18:09:02] 07/03/2018 18:14:00
[07/03/2018 18:09:02]
[07/03/2018 18:09:02] Job host started
^CTerminate batch job (Y/N)? y
I'm guessing its missing a reference to Microsoft.WindowsAzure.Storage somewhere, but where do I add this reference? I've tried adding WindowsAzure.Storage nuget package, but it still errors.
References
Microsoft.NET.Sdk.Functions v1.0.6
Newtonsoft.Json v11.0.1
UPDATE
I tried adding WindowsAzure.Storage v9.0.1 to the project, but that results in a different error:
[08/03/2018 09:47:55] A ScriptHost error has occurred
[08/03/2018 09:47:55] Exception while executing function: JobRunner. VS.JobRunner: Could not load file or assembly 'Microsoft.WindowsAzure.Storage, Version=9.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Could not find or load a specific file. (Exception from HRESULT: 0x80131621). System.Private.CoreLib: Could not load file or assembly 'Microsoft.WindowsAzure.Storage, Version=9.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
visibilityTimeout
has made me think about this some more, and looking at it you can set a timeout of up to 7 days... so using this as a delay rather than a temporary block while processing would actually work perfectly... so again sorry, and I take my previous comment back! – BG100