Closed acodrington closed 1 year ago
This pull request has been linked to Shortcut Story #53211: 🎉 🎉 🎉 Make Halibut Support Async RPC Calls 🎉 🎉 🎉.
The description I think should give an example of the behaviour that this PR adds e.g. an example around how an async service can be supplied and called as well as some details around how it has to be done/what the methods need to look like etc.
Description
This PR adds a
InvokeAsync
method toIServiceInvoker
andServiceInvoker
, as part of [sc-53211]. This allows the ServiceInvoker to invoke async implementations of services with sync interfaces.Upon succesfully acquiring a lease from the
IServiceFactory
,InvokeAsync
will search for an async method on the registered service which matches the name of requested method, but also follows these conventions:Async
CancellationToken
as its last argumentTask
orTask<T>
, depending on whether the originally requested method returnsvoid
or a result.This feature is dependant on the implementation of
IServiceFactory
being used (Octopus Server and Tentacle use their own implementations), but we can now register async implementations of sync services in theDelegateServiceFactory
:In the above example, there is no formal relationship between
IMySyncService
andIMyAsyncService
, but the async interface must replicate the sync interface whilst adhering to the conventions listed above.The
DelegateServiceFactory
will throw an exception upon registration if the async interface does not follow the conventions, via the newAsyncServiceVerifier
helper class.Main changes:
IServiceInvoker
AsyncServiceVerifier
for verifying the mapping between sync and async service interfaces.null
rather than emptyDelegateServiceFactory
to allow registering async implementations against a sync service interface, and verify that mapping conforms to conventions.DelegateServiceFactory
for purposefully registering non-comforming sync/async service interfaces (used in testing)Related to https://github.com/OctopusDeploy/Issues/issues/8266