-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement asynchronous interceptors #186
Conversation
Updates the documentation to reflect the changes in connectrpc/connect-swift#186.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few little insignificant comments around code style. The majority of the changes are quite straight forward, despite the unhelpful Git diff. ProtocolClient
and InterceptorChain
changes are a bit more dense; however, the 100% test coverage is amazing.
Libraries/Connect/Implementation/Interceptors/InterceptorChain.swift
Outdated
Show resolved
Hide resolved
Thank you for the review @eseay! |
Updates the documentation to reflect the changes in connectrpc/connect-swift#186. The copy matches `Interceptor.swift`'s inline documentation from that PR with the addition of an auth example here.
Thanks for implementing this! Are you going to tag a new version soon? |
Summary
This PR refactors the interceptor implementation offered by Connect-Swift to support asynchronous processing inside interceptors. This is useful when clients want to perform work prior to sending outbound requests or returning responses to callers, such as:
Resolves #104.
Docs are being updated in connectrpc/connectrpc.com#68.
Considerations
When implementing these, the following considerations were made:
return await finishProcessingRequest(request)
versusproceed(request)
), but it would place significant limitations on interceptors by disallowing them from doing any buffering on streams due to the fact that data cannot be passed to any interceptors while one is beingawait
ed. For this reason, we opted for exposing closures which allows interceptors toproceed()
the chain at any point, potentially after receiving additional invocations from the client with more information. Implementations can still wrap these calls with async/await if desired (example below, and inInterceptor.swift
)headers -> data -> data -> data -> trailers
Example of wrapping an interceptor with async/await:
Approach
Sendable
requirement on interceptor closures), as closures can be invoked from different threads during the span of a request or stream due to the asynchronous nature of other interceptors which may be present in the chain.Task
(as shown above).Notes
Sendable
requirements for interceptors #182 have been reverted as part of this PR due to the fact that interceptor closures must beSendable
/thread-safe per the discussion aboveswiftSettings: [.unsafeFlags(["-Xfrontend", "-strict-concurrency=complete"])]
to ensure that it doesn't introduce new strict concurrency warnings