Skip to content

Using multiple DbCommandInterceptor doesn't play nice in AsyncLocal #22766

@ajcvickers

Description

@ajcvickers

Moved from discussion #22749

Question

From @srprash

Hi,
I have a sample ASPNetCore webapp which uses EFCore to add or retrieve users to a postgres db. In addition to this, I'm using AWS X-Ray .Net SDK to trace these operations by adding the EFInterceptor along with a custom empty MyDbCommandInterceptor. I'm using the empty interceptor for simplicity. The issue happens with any interceptor used with the EFInterceptor.
The AWS X-Ray SDK uses AsyncLocal to store the trace context of the app. When I use just use one of the interceptors, everything works fine. However, when both the interceptors are used together, the trace context gets messed up and becomes inconsistent across threads for async calls involving ExecuteReaderAsync. The interceptors work fine together for any synchronous operation to the db.

I've opened a related issue on X-Ray SDK's repo with more details pertaining to the error on the SDK but while digging into the cause of the problem, I established that the issue is with AsyncLocal not being consistent for threads invoking ReaderExecutingAsync and ReaderExecutedAsync methods before and after an async call to my postgres db.
I wonder if using multiple DbCommandInterceptors has an impact on separate threads and their thread local storage. Also, ReaderExecutingAsync and ReaderExecutedAsync methods seem to execute on different threads. Is there a way to ensure they run on same thread or to propagate a context between these methods?

I'm hoping to get some direction from this discussion to investigate the problem further and resolve it. Any help is greatly appreciated :)

Replies

From @roji

@srprash can you please submit a minimal console app which demonstrates to inconsistency with? AFAIK the interceptors shouldn't be interfering with AsyncLocal in any way.

(Note that this isn't about thread-local storage, which does not persist across asynchronous operations since those don't necessarily continue on the same thread where they began. This is why AsyncLocal is needed).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions