AsyncClientStreamingCall <TRequest, TResponse>(Method <TRequest, TResponse> method, string host, CallOptions options) { // No channel affinity feature for client streaming call. ChannelRef channelRef = GetChannelRef(); var callDetails = new CallInvocationDetails <TRequest, TResponse>(channelRef.Channel, method, host, options); var originalCall = Calls.AsyncClientStreamingCall(callDetails); // Decrease the active streams count once async response finishes. var gcpResponseAsync = DecrementCountAndPropagateResult(originalCall.ResponseAsync); // Create a wrapper of the original AsyncClientStreamingCall. return(new AsyncClientStreamingCall <TRequest, TResponse>( originalCall.RequestStream, gcpResponseAsync, originalCall.ResponseHeadersAsync, () => originalCall.GetStatus(), () => originalCall.GetTrailers(), () => originalCall.Dispose())); async Task <TResponse> DecrementCountAndPropagateResult(Task <TResponse> task) { try { return(await task.ConfigureAwait(false)); } finally { channelRef.ActiveStreamCountDecr(); } } }
// Note: response may be default(TResponse) in the case of a failure. We only expect to be called from // protobuf-based calls anyway, so it will always be a class type, and will never be null for success cases. // We can therefore check for nullity rather than having a separate "success" parameter. private void PostProcess <TResponse>(AffinityConfig affinityConfig, ChannelRef channelRef, string boundKey, TResponse response) { channelRef.ActiveStreamCountDecr(); // Process BIND or UNBIND if the method has affinity feature enabled, but only for successful calls. if (affinityConfig != null && response != null) { if (affinityConfig.Command == AffinityConfig.Types.Command.Bind) { Bind(channelRef, GetAffinityKeyFromProto(affinityConfig.AffinityKey, (IMessage)response)); } else if (affinityConfig.Command == AffinityConfig.Types.Command.Unbind) { Unbind(boundKey); } } }
AsyncDuplexStreamingCall <TRequest, TResponse>(Method <TRequest, TResponse> method, string host, CallOptions options) { // No channel affinity feature for duplex streaming call. ChannelRef channelRef = GetChannelRef(); var callDetails = new CallInvocationDetails <TRequest, TResponse>(channelRef.Channel, method, host, options); var originalCall = Calls.AsyncDuplexStreamingCall(callDetails); // Decrease the active streams count once the streaming response finishes its final batch. var gcpResponseStream = new GcpClientResponseStream <TRequest, TResponse>( originalCall.ResponseStream, (resp) => channelRef.ActiveStreamCountDecr()); // Create a wrapper of the original AsyncDuplexStreamingCall. return(new AsyncDuplexStreamingCall <TRequest, TResponse>( originalCall.RequestStream, gcpResponseStream, originalCall.ResponseHeadersAsync, () => originalCall.GetStatus(), () => originalCall.GetTrailers(), () => originalCall.Dispose())); }