.NET 8 インプロセスの Azure Functions を 分離ワーカーに移行する検証をしてみた

.NET 6 インプロセスの Azure Functions は、.NET 8 のインプロセスに移行しました。

https://qiita.com/mnrst/items/d9ded8ed93c74da8a403

次は、.NET 8 インプロセスから .NET 8 分離ワーカーに移行して、次の LTS バージョンとなる .NET 10 分離ワーカーの移行に備えておきたいと思います。

## 移行元となる検証用の .NET 8 インプロセスを作成

```bash:bash
func init mnrdn8in --target-framework net8.0 --worker-runtime dotnet

cd mnrdn8in

func new --name Sample --template HttpTrigger

func start

curl http://localhost:7071/api/Sample
```

## .NET 8 インプロセスの検証用アプリ

```cs:Sample.cs
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace mnrdn8in
{
    public static class Sample
    {
        [FunctionName("Sample")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            string responseMessage = string.IsNullOrEmpty(name)
                ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
                : $"Hello, {name}. This HTTP triggered function executed successfully.";

            return new OkObjectResult(responseMessage);
        }
    }
}
```

## 移行先となる .NET 8 分離ワーカーを作成

```bash:bash
cd ..

func init mnrdn8iso --target-framework net8.0 --worker-runtime dotnet-isolated

cd mnrdn8iso

func new --name Sample --template HttpTrigger

func start

curl http://localhost:7071/api/Sample
```

## Sample.cs を分離ワーカー用に最低限の修正

```cs:Sample.cs
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;

namespace mnrdn8iso
{
    public class Sample
    {
        private readonly ILogger<Sample> log;

        public Sample(ILogger<Sample> logger)
        {
            log = logger;
        }

        [Function("Sample")]
        public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string? name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic? data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            string responseMessage = string.IsNullOrEmpty(name)
                ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
                : $"Hello, {name}. This HTTP triggered function executed successfully.";

            return new OkObjectResult(responseMessage);
        }
    }
}
```

## 動作確認

```bash:bash
$ func start
  復元対象のプロジェクトを決定しています...
  復元対象のすべてのプロジェクトは最新です。
  復元対象のプロジェクトを決定しています...
  復元対象のすべてのプロジェクトは最新です。
  WorkerExtensions -> /Users/mnr/work/test/mnrdn8iso/obj/Debug/net8.0/WorkerExtensions/buildout/Microsoft.Azure.Functions.Worker.Extensions.dll
  mnrdn8iso -> /Users/mnr/work/test/mnrdn8iso/bin/output/mnrdn8iso.dll

ビルドに成功しました。
    0 個の警告
    0 エラー

経過時間 00:00:01.96



Azure Functions Core Tools
Core Tools Version:       4.0.6610 Commit hash: N/A +0d55b5d7efe83d85d2b5c6e0b0a9c1b213e96256 (64-bit)
Function Runtime Version: 4.1036.1.23224

[2024-12-14T08:39:47.285Z] Found /Users/mnr/work/test/mnrdn8iso/mnrdn8iso.csproj. Using for user secrets file configuration.
[2024-12-14T08:39:48.271Z] Worker process started and initialized.

Functions:

        Sample: [GET,POST] http://localhost:7071/api/Sample

For detailed output, run func with --verbose flag.
[2024-12-14T08:39:51.310Z] Executing 'Functions.Sample' (Reason='This function was programmatically called via the host APIs.', Id=7417f498-fb8d-4ecd-88b7-81d6c4111ac5)
[2024-12-14T08:39:51.392Z] C# HTTP trigger function processed a request.
[2024-12-14T08:39:51.410Z] Executing OkObjectResult, writing value of type 'System.String'.
[2024-12-14T08:39:51.432Z] Executed 'Functions.Sample' (Succeeded, Id=7417f498-fb8d-4ecd-88b7-81d6c4111ac5, Duration=133ms)
```

## 参考

https://learn.microsoft.com/ja-jp/azure/azure-functions/migrate-dotnet-to-isolated-model?tabs=net8