1
votes

I have an Azure Function that is triggered by some blob creation, is doing some transforms (OCR mostly) and writes the result again to Blob:

[FunctionName("Ocr")]
public static async Task Run([BlobTrigger("input/{name}")]CloudBlockBlob myBlob,[Blob("output/{name}_{DateTime}.txt", FileAccess.Write)] TextWriter resultTextFile, string name,ILogger log)
{
    try
    {
        var ocrResult = await DoOcr(name);
        // This only happens if no exception was thrown
        await resultTextFile.WriteAsync(ocrResult.Text);
    }
    catch (Exception e)
    {
        log.LogError(e, $"Exception during processing. Cannot process document {name}");
    }
}

This works all fine and well. However, if something goes wrong inside the "DoOcr()" function, an exception is thrown - and caught it inside my catch block - the Function ends and an empty new blob was created at "output/{name}_{DateTime}.txt".

"WriteAsync()" gets never called but why is the file still created? It does not happen if I use "CloudBlockBlob" instead of "TextWriter" in the binding.

1
I guess I don't understand the confusion - the Blob decorator means it's a StreamWriter constructor which creates the file path provided if it doesn't exist. See docs.microsoft.com/en-us/dotnet/api/… And this is different than creating just a CloudBlockBlob which is basically an in-memory stream that then gets dumped to the file. - Kyle Hale
Ok, maybe it didn't put it clearly enough, sorry. My point is that the file on the Blob gets created, even if the WriteAsync() operation gets never called. You can see that in the case of an Exception, the file gets created only after the Function actually ends. This is not the case (i.e. the file does not created) when I use the CloudBlockBlob decorator. - silent
Thanks. Yeah I think I understand the logic behind it now. Not saying that it makes total sense to me :) - silent
The thing you're missing is that that Blob decorator instantiates an instance of your variable class and passes that in to your Run method. When you choose TextWriter as that class, instantiation automatically creates the file. So the file is already created before your Run method even kicks off. When you choose CloudBlockBlob as that class, instantiation creates a stream but not a file. So the file is only created when you use one of the Write* methods. - Kyle Hale
Stepping through in the debugger I actually do not see the file on the blob storage before the Run() methods exists - no matter if I call write() or not. - silent

1 Answers

1
votes

As Kyle said, TextWriter writer = new StreamWriter(stream);. So when you use TextWriter as blob output, it will initializes a new instance of the StreamWriter class for the specified file on the specified path. If the file exists, it can be either overwritten or appended to. If the file does not exist, this constructor creates a new file.

While you use CloudBlockBlob as blob output, it will initializes a new instance of the CloudBlockBlob class using an absolute URI to the blob which read as an in-memory stream and then get dumped to the file. So, if the stream is interrupt, it will not create a output new file.