タイトルが長過ぎてなんのこっちゃワカランと思います。僕も良いタイトルが浮かびません...(
今回は下記の Issue の内容と公式回答についてザックリ解説します。僕の理解が正確かは分からないので、Issue も読んでもらえると助かりますw
Issue の内容
System.Interactive.Async
v4.1.1 を NuGet 参照してる Azure Functions プロジェクトがある- この NuGet パッケージは C# 8.0 以降で言語サポートされた
IAsyncEnumerable<T>
を利用するときに高頻度で利用する
- この NuGet パッケージは C# 8.0 以降で言語サポートされた
- Azure Functions v3 にデプロイしたら「dll がないぜ!」って例外飛んで動かない!
- どうやら
RemoveRuntimeDependencies
のせいでSystem.Interactive.Async.dll
が削除されちゃってるっぽい Microsoft.NET.Sdk.Functions
を更新したのが問題ぽい- v3.0.3 までは動いてた
背景
Azure Functions は起動高速化などを目的として Functions Host が利用している dll と重複している dll をビルド時に削除するようになっています。これは .csproj ビルド時に RemoveRuntimeDependencies
タスクが動くことで実現されていて、既定で有効です。削除対象となる dll は runtimeassemblies.json にリストされているのですが、ここに System.Interactive.Async.dll
が入っています。Microsoft.NET.Sdk.Functions
v3.0.4 以降で System.Interactive.Async.dll
が追加されたようで、「Functions SDK を更新 (v3.0.4+) したら突然動かなくなった!」という感じです。実際僕も業務で同じ問題にブチ当たってしばらくハマりました。
ここで問題だったのが RemoveRuntimeDependencies
で削除する際に dll のバージョンを見てくれていなかったことです *1。Azure Functions v3 Host は System.Interactive.Async.dll
v3.x.x を参照しているのですが、プロジェクト側で NuGet 参照して利用している v4.x.x を問答無用で削除してしまうことで問題が発生していました。C# 8.0 以降を利用するときに大変相性が悪い事案でツラぽよでした。
これまでの回避策
アセンブリ自動削除が行われなければ問題が起こらないので、RemoveRuntimeDependencies
タスクを Opt-out します。_FunctionsSkipCleanOutput = true
を .csproj に記述すれば OK です。
<PropertyGroup> <TargetFramework>netcoreapp3.1</TargetFramework> <AzureFunctionsVersion>v3</AzureFunctionsVersion> <!-- ↓↓ コレを追加 ↓↓ --> <_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput> </PropertyGroup>
という workaround を知っていたのでコメントしておきました。それが 2020 年 7 月の話です。
新しい回避策
それから半年以上経過した 2021 年 3 月。つい最近です。オフィシャルな回答として以下が提示されました。簡単に言うと除外する dll を除外リストに入れられるようになったという感じです。
Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator
1.2.1 以降を参照<FunctionsPreservedDependencies Include="xxx.dll" />
で除外リストに追加
<ItemGroup> <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.11" /> <!-- ↓↓ コレを追加 ↓↓ --> <PackageReference Include="Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator" Version="1.2.1" /> <FunctionsPreservedDependencies Include="System.Interactive.Async.dll" /> </ItemGroup>
削除されると困る dll を適宜羅列することで、RemoveRuntimeDependencies
による出力アセンブリの最適化の恩恵も得られる形になりました。大変ハッピー!
*1:今はバージョンも見て削除しているような気がしなくないですが、まだ未確認なのであまり信じないでください