今回はいつも以上にまとまりがありませんぞ。
Azure Functionsは様々な起動タイミングを設定することができます。
HTTPリクエストが来た、定期実行、ファイルがアップロードされた、データベースにデータが保存された、などのイベントで起動できるのでたいへん便利です。
それはいいんだけど、Azure Functionsはドキュメントが無駄にたくさんあるわりに中身が不親切なんですよね。
今回C#でBLOBに保存したタイミングのトリガーを実装したかったのですが、このドキュメントをそのままコピペすると『型または名前空間の名前 'BlobTrigger' が見つかりませんでした』とか言われて動きませんでした。
これの解決にやたら苦戦したので記録しておきます。
ていうかAzureのドキュメント、全体的に何言ってるのかわからないテキストが多い。
xxxxxx.csproj
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="5.2.1" />
を追加する。
Versionはnugetをコピペしただけなので、コピペするタイミングによって異なる場合があります。
xxxxxx.cs
using Microsoft.Azure.WebJobs;
を追加する。
これで[BlobTrigger("test-samples-trigger/{name}")] string myTriggerItem
が動くようになります。
PackageReferenceと全然違うやん。
どうしてusing Microsoft.Azure.WebJobs.Extensions.Storage;
とかでないのかはわかりません。
これドキュメントのどこにも書かれてないんですが、どうやって辿り着けばいいんだ?
そもそもドキュメントにはusing
が全く書かれていないので、だいたいいつもクラスがないって引っかかるんですよね。
パッケージ名クラス名でググれば概ね解決することが多いのですが、今回のBlobTriggerは何故か全然ひっかからなくて、どのパッケージにあるのか見つけるのにやたら苦労しました。
本当にMicrosoft.Azure.WebJobs.Extensions.Storageでいいの?
似たような別のドキュメントにはMicrosoft.Azure.Functions.Worker.Extensions.Storage.Blobsとかいうまた違うパッケージが出てきています。
さらに謎のマイグレーションガイドに出てくるのはMicrosoft.Azure.Storage.BlobとAzure.Storage.Blobsです。
なにがどう違うんだこれ。
BLOBトリガーのサンプルが意味不明
ドキュメント記載のサンプルがこちらです。
public static class BlobFunction
{
[Function(nameof(BlobFunction))]
[BlobOutput("test-samples-output/{name}-output.txt")]
public static string Run(
[BlobTrigger("test-samples-trigger/{name}")] string myTriggerItem,
[BlobInput("test-samples-input/sample1.txt")] string myBlob,
FunctionContext context)
{
var logger = context.GetLogger("BlobFunction");
logger.LogInformation("Triggered Item = {myTriggerItem}", myTriggerItem);
logger.LogInformation("Input Item = {myBlob}", myBlob);
// Blob Output
return "blob-output content";
}
}
"test-samples-trigger/{name}"
にBLOBが保存されたことをトリガーにして、"test-samples-input/sample1.txt"
を読み込んで"test-samples-output/{name}-output.txt"
に出力します。
なんで?
普通"test-samples-trigger/{name}"
をどうこうしたいだろ。
というか一番欲しい情報は{name}
だと思うのだけど、それを取り出す方法が何故かここには書かれていません。
わざわざ別ページまで辿る必要があります。
public static class BlobFunction
{
[Function(nameof(BlobFunction))]
[BlobOutput("test-samples-output/{name}-output.txt")]
public static string Run(
[BlobTrigger("test-samples-trigger/{name}")] string myTriggerItem,
[BlobInput("test-samples-input/sample1.txt")] string myBlob,
string name,
FunctionContext context)
{
// 引数nameに入る
return name;
}
}
トリガーに"test-samples-trigger/{name}"
とあった場合、引数にstring name
を増やすとどういうわけかそこに値が入ってきます。
この取り出し方を真っ先に書いてほしいのだが。
public static class BlobFunction
{
[Function(nameof(BlobFunction))]
public static string Run(
[BlobTrigger("{foo}/{bar}/{name}")] string myTriggerItem,
string foo,
string bar,
string baz,
ILogger logger,
IBinder binder)
{
return $"foo:{foo} bar:{bar} baz:{baz}";
}
}
取り出したい値が複数ある場合は、単に引数を増やせばいいです。
またBlobInputやBlobOutputなどは、いらない場合は引数から消すだけで使わないようになります。
さらに引数にILoggerやらIBinderを指定すると、なんか勝手にそれらがバインドされてきます。
引数がアバウトすぎてやべえ。
この引数に使える値の一覧どこにあるんだ?
BlobOutputに動的値を使えない
public static class BlobFunction
{
[Function(nameof(BlobFunction))]
[BlobOutput("test-samples-output/{name.padLeft(10,'0')}-output.txt")]
public static string Run(
[BlobTrigger("test-samples-trigger/{name}")] string myTriggerItem,
[BlobInput("test-samples-input/sample1.txt")] string myBlob,
string name)
{
return name;
}
}
動きません。
BlobOutput
の"test-samples-output/{name.padLeft(10,'0')}-output.txt"
は文字列補間としては正しい形式であるにも関わらず、ここではエラーになります。
BlobOutput
にはBlobInput
でバインドした値をそのまま使うことはできますが、計算式などを使うことはできません。
なんで。
このあたり有効な書式とかAzure Functions における Azure Blob Storage のバインドの概要にもAzure Functions における Azure Blob Storage の出力バインドにも一切記載がありませんでした。
どうしても動的値を使いたい場合は、BlobOutput
等を使わず自力で接続しに行くか、IBinderを使うくらいしかなさそうでした。
あとリクエストによってはBlobOutputを出力したくない場合もあると思うんだけど、BlobOutput
を書いた上でBlobOutput
に対して何もしなかったときは空のファイルが出力されてしまいました。
あるときはファイルを出力したい、また他のあるときは出力したくない、といった場合はどうすればいいんだろう。