vyshane/grpc-swift-combine

How do I finish a bidirectional stream?

Closed this issue · 4 comments

krjw commented

I have a Bidirectional stream and my server side waits for the client side to finish. When I cancel the cancelable call.sendEnd() is not triggered although I think it should be. My server side waits forever for the stream to finish. I can dispose the client which cancels all pending streams but I think cancelling or ending the stream separately should be the correct behaviour.

I will try to implement this, but I am very new to swift and combine. If this is already a feature please point me to it.

Greetings krjw

Ok so I have tested it with merging my @Published publisher and a `PassthroughSubject like so:

let stream = self.passthrough.merge(with: self.$published.setFailureType(to: Error.self).eraseToAnyPublisher())

where self.passthrough is defined as:

private let passthrough = PassthroughSubject<CustomMessage, Error>()

when I want to finish the stream I call self.passthrough.send(completion: .failure(Fail.none)) or self.passthrough.send(completion: .finished).

I checked but in BidirectionalStreamingCallPublisher the .sink() in receive() does not call the receiveCompletion, hence the call is neither sendEnd()ed , nor cancel()ed

  func receive<S>(subscriber: S)
    where S : Subscriber, BidirectionalStreamingCallPublisher.Failure == S.Failure,
    BidirectionalStreamingCallPublisher.Output == S.Input
  {
    _ = requests.sink(
      receiveCompletion: { switch $0 {
        case .finished:
          Swift.print("FINISHED CHECK NOT CALLED")
          _ = self.call.sendEnd()
        case .failure:
          Swift.print("FAILURE CHECK NOT CALLED")
          _ = self.call.cancel()
      }},
      receiveValue: {
        _ = self.call.sendMessage($0)
      }
    )
    bridge.messagePublisher.subscribe(subscriber)
    // Call status future always succeeds and signals call failure via gRPC status
    call.status.whenSuccess { sendCompletion(status: $0, toSubscriber: subscriber) }
  }

Do you have any idea why this is happening?

same guy, other profile

Greetings krjw

I found out that I had to call sendEnd() and cancel() separately. Note: On the same thread!!! Otherwise it didn't work. Could be an implementation mistake on the C# server side I have but I think it would be good to manually call these functions anyway to have more control over the behaviour since I have the feeling that this is different for every implementation out there and not prohibited by the design of the frameworks.

Thanks for looking into this!

I've just merged #11, which should fix this issue. @krjw-eyev are you able to update your dependency to master and see whether this has resolved the problem for you?

Since I was using this in a library that needed this quickly, I removed your library completely. I might try again in the future. Thanks for updating the library!