Azure Blob storage got a new addition recently, that is Append Blob. Based on the Microsoft documentations this is an ideal blob storage service for frequently modified data, which makes it a suitable candidate for the logging.
It is a natural tendency that we see AppendText method and we go for it for simple text based logging and you end up with this exception – The remote server returned an error : (412) The append position condition specified was not met.
This blogger has addressed the issue and provided a workaround in his post.
If you’re looking for a solution, then above link has it. If you want to read about the reason for this issue continue reading.
I started the investigation directly by digging into the source code of the Azure Storage SDK in GitHub
In the documentation it is mentioned that AppendText method can be used only in the single write scenarios.
See this section CloudAppendBlob Methods
It is very explicit that in the SDK it has been mentioned that AppendText should be used only in the single writer scenarios, check that in line number 1739 of this file
CloudAppendBlob methods that cannot be used in concurrent access scenarios
Also the Async counter parts of the above methods also cannot be used in concurrent access.
The only method that can be used in concurrent scenarios is AppendBlock / AppendBlockAsync
So Why AppendBlock is special ?
Investigating the source in GitHub it is clear that the call chain goes like this.
AppendText calls AppendFromByteArray, AppendFromByteArray calls AppendFromStream, AppendFromStream calls the internal method UploadFromStreamHelper
UploadFromStreamHelper cannot handle concurrent scenarios.
Continuing the investigation…..
Still we need to investigate how AppendBlock can handle the concurrent requests. We pass a System.IO.Stream object to AppendBlock method and the AppendBlock method calls WriteToSync on the passed Stream object.
Do we have a WriteToSync method in the System.IO.Stream ? No.
The Storage SDK has a implementation of WriteToSync as an extenstion method. See this file – line number 65
It is clear that WriteToAsync has a synchronized call to the blob using the ManualResetEvent, so that is why AppendBlock could handle the concurrent access, but remember this is a blocking call.