What is the simplest way to run a timer-triggered Azure Function locally once?

限于喜欢 提交于 2020-03-17 06:30:08

问题


I have a few C# Azure Functions that run on a schedule using timer triggers. I've set them up like so, where %TimerSchedule% refers to a cron expression in the app settings:

public static void Run([TimerTrigger("%TimerSchedule%")]TimerInfo myTimer, TraceWriter log)

During development, I often want to run the functions locally using Azure Functions Tools for Visual Studio + Azure Functions Core Tools. But when I hit F5 to debug the function locally it (usually) doesn't run immediately. Instead, it starts waiting for the next occurrence as per the timer schedule. So for example, if my cron expression says to run daily at 8PM, I'd have to wait until 8PM for the function to actually run on my machine.

So my question is: What is the simplest and best way to make a function run once locally?

Things I have tried or considered:

  1. Use a more frequent timer schedule just for local development
    • This is OK but not perfect – you still have to wait a little bit unless it's very frequent, and if it's very frequent then the function might run multiple times. This is what I'm doing now.
  2. Write a console app or unit test that directly calls the function's Run() method
    • This isn't 100% straightforward because you have to provide TimerInfo and TraceWriter arguments to Run() – and I've found surprisingly little documentation for that.

Microsoft's Strategies for testing your code in Azure Functions page is not very helpful on this topic – it only mentions timer triggers as a way to test other trigger types.

In a perfect world, I'd hit F5 and the function would immediately run once – just like developing a "normal" .NET app.


回答1:


You could perhaps use the RunOnStartup flag as documented here. It doesn't quite meet your brief regarding it only running once, but it should at least execute it locally once the app has started.

/// Gets or sets a value indicating whether the function should be invoked
/// immediately on startup. After the initial startup run, the function will
/// be run on schedule thereafter.

Example using attribute binding:

[TimerTrigger("%TimerSchedule%", RunOnStartup = true)]TimerInfo myTimer




回答2:


I had the same question, and used the DEBUG-flag to have the RunOnStartup only while debugging:

        public static void Run(
            [TimerTrigger("* 0 7 * * 1-5"
#if DEBUG
            , RunOnStartup=true
#endif
            )]TimerInfo myTimer, TraceWriter log)
        {



回答3:


I had the same question. I fixed it with a Unittest. Indeed you need to stub out the TraceWriter and the TimerInfo.

Here some code how I did this.

TimerInfo:

public class ScheduleStub : TimerInfo
{
    public ScheduleStub(TimerSchedule schedule, ScheduleStatus status, bool isPastDue = false) : base(schedule, status, isPastDue)
    {
    }
}

And the TraceWriter:

 public class TraceWriterStub : TraceWriter
{
    protected TraceLevel _level;
    protected List<TraceEvent> _traces;

    public TraceWriterStub(TraceLevel level) : base(level)
    {
        _level = level;
        _traces = new List<TraceEvent>();
    }

    public override void Trace(TraceEvent traceEvent)
    {
        _traces.Add(traceEvent);
    }

    public List<TraceEvent> Traces => _traces;
}



回答4:


From https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local#local-settings-file

Non-HTTP triggered functions

For all kinds of functions other than HTTP triggers and webhooks, you can test your functions locally by calling an administration endpoint. Calling this endpoint with an HTTP POST request on the local server triggers the function. You can optionally pass test data to the execution in the body of the POST request. This functionality is similar to the Test tab in the Azure portal.

You call the following administrator endpoint to trigger non-HTTP functions:

http://localhost:{port}/admin/functions/{function_name}

To pass test data to the administrator endpoint of a function, you must supply the data in the body of a POST request message. The message body is required to have the following JSON format:

{
    "input": "<trigger_input>"
}



回答5:


Just add another function with HTTP trigger type within the same class, add your code, or call your Run method from that function and invoke it from your browser.

Be sure to comment/remove that function when deployed to prod, or you will have the ability to trigger the function via HTTP calls in prod.



来源:https://stackoverflow.com/questions/46556621/what-is-the-simplest-way-to-run-a-timer-triggered-azure-function-locally-once

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!