odata.net
odata.net copied to clipboard
Provide async API for CsdlWriter
The CsdlWriter
only exposes synchronous APIs for writing CSDL (WriteCsdl
and TryWriteCsdl
). This means that any async API that relies on CsdlWriter
to serialize CSDLs (e.g. ODataMessageWriter.WriteMetadataAsync
) will have to perform synchronous I/O, which may lead to undesired effects (sync over async which may lead to thread starvation, exceptions in environments that don't allow synchronous I/O, etc.).
Assemblies affected
Micrososft.OData.Edm
7.x
Reproduce steps
The simplest set of steps to reproduce the issue. If possible, reference a commit that demonstrates the issue.
Expected result
- We should provide APIs like
CsdlWriter.WriteCsdlAsync
andCsdlWriter.TryWriteCsdlWriterAsync
. - Methods like
ODataMessageWriter.WriteMetadataAsync
should be purely asynchronous and not perform any synchronous I/O.
Actual result
-
CsdlWriter
does not expose async APIs -
ODataMessageWriter.WriteMetadataAsync
performs synchronous I/O
Additional detail
You may be wondering: If ODataMessageWriter.WriteMetadataAsync
performs synchronous I/O and ASP.NET Core disables synchronous I/O by default then how come /$metadata
request in ASP.NET Core OData do not throw exceptions? Well, ASP.NET Core OData 8 implements a hack to get around this issue. It has a StreamWrapper that implements synchronous I/O calls like Flush()
using blocking async calls calls like FlushAsync().Wait()
(which is also bad for perf). We should also address this when we make WriteMetadataAsync
truly async.
For customers who use ODataMessageWriter
directly and don't want to perform synchronous I/O, a workaround could be to write the CSDL in a memory stream and cache the byte array, then use the byte array as the input for async I/O.