在本地运行一次计时器触发的 Azure 函数最简单的方法是什么?

我有一些 C # Azure 函数使用 计时器触发器按时间表运行。我把它们设置成这样,其中 %TimerSchedule%引用了应用程序设置中的 cron 表达式:

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

在开发过程中,我经常想使用 Azure 函数工具 for Visual Studio + Azure 函数核心工具在本地运行函数。但是当我按 F5在本地调试函数时,它(通常)不会立即运行。相反,它开始按照计时器计划等待下一次发生。例如,如果我的 cron 表达式说每天晚上8点运行,那么我必须等到晚上8点才能在我的机器上实际运行该函数。

所以我的问题是: 使函数在本地运行一次的最简单和最好的方法是什么?

我试过或考虑过的事情:

  1. 只为本地开发使用更频繁的计时器计划
    • 这是可以的,但并不完美-您仍然需要等待一点点,除非它非常频繁,如果它非常频繁,那么函数可能会运行多次。这就是我现在在做的。
  2. 编写一个控制台应用程序或单元测试,直接调用函数的 Run()方法
    • 这并不是100% 简单的,因为您必须为 Run()提供 TimerInfoTraceWriter参数-我发现这方面的文档非常少。

微软的 在 Azure 函数中测试代码的策略页面在这个主题上没有很大帮助——它只提到定时器触发器作为测试 其他触发器类型的一种方法。

在一个完美的世界里,当我点击 F5键时,这个函数会立即运行一次——就像开发一个“正常”函数一样。NET 应用程序。

49303 次浏览

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

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;
}

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)
{

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.

From https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=windows%2Ccsharp%2Cbash#non-http-triggered-functions

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>"
}

If you are using VS Code, use the Azure Functions extension:

  1. Hit F5 to enter debug mode, this starts the function app.
  2. Go to the Azure icon in the Activity bar.
  3. Under Local Project, find the function you want to run, right click, and select "Execute Function Now".

Check out this MS quickstart guide.

Using postman should do the trick. Follow the below steps to Run or debug you Timer Trigger Locally.

1 . RUN your Project.

  1. Open Postman and past this url http://localhost:{port}/admin/functions/{function_name}

  2. Make sure to use a POST Method with Json body of { "input": "" }

  3. Press SEND.

You Should receive a response of 202.

Start your function with this curl command

curl --request POST -H "Content-Type:application/json" --data '{"input":""}'  http://localhost:7071/admin/functions/{function_name}

The input data is required, without it the function won't be triggered.

Another approach is to trigger manually the function from Postman:
Manually run a non HTTP-triggered function.

POST /admin/functions/<function name> HTTP/1.1
Host: localhost:<port>
Content-Type: application/json


{}

For me, it looks like that on postman for a timerTrigger function called Function1: enter image description here