odata.net icon indicating copy to clipboard operation
odata.net copied to clipboard

Provide async API for CsdlWriter

Open habbes opened this issue 1 year ago • 2 comments

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 and CsdlWriter.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.

habbes avatar Jun 12 '23 04:06 habbes