One more `wire` + `grpc` question. If I have a ser...
# squarelibraries
d
One more
wire
+
grpc
question. If I have a service like this
Copy code
rpc getItemsStream(ItemRequest) returns (stream ItemResponse) {}
How do I send the initial request? Wire generates the implementation of GrpcStreamingCall which has 2 channels. Do I understand correctly that I must send initial request using a
sendChannel
? My issue posted above seems to be caused by no request body being sent. Sending it to the channel doesn't help, maybe I must do it otherwise? Stub implementation generated by
grpc-kotlin
library has this explicitly:
fun getItemsStream(request: ItemsRequest): Flow<Response>
, but
wire
generates function with no params in this case.
OK. I started doing this:
Copy code
sendChannel.send(ItemsRequest())
sendChannel.close()
And now things went alive! I can see in server logs that events are being sent from server to client. If this is the right way to do this, you really should document this, wasted a lot of time of this "obvious" stuff 🙂
1
But now I have another issue: client does not receive those streaming messages. I can see this event from OkHttp
Copy code
okhttp.OkHttpClient  I  [53 ms] responseBodyStart
and then silence. Am I again not consuming them right? I call
receiveChannel.receive()
on the client.
b
If you close the
sendChannel
it closes the whole connection. You wanna send request on one thread, and read the responses on another. If you close any of them, the connection dies.
d
Hmm. Without closing, server doesn't receive request body at all. Wait, does this mean that if I'm doing this:
Copy code
GlobalScope.launch(<http://Dispatchers.IO|Dispatchers.IO>) {
  val (send, receive) = service.someStreamingCall().execute()
  send.send(MyRequest())
  for (resp in receive) { println(resp) }
}
...then I'm effectively blocking a thread? Because I do it like above and a) either send doesn't work, no request body goes out, times out b) adding 'close()' after send actually causes server to receive the request, but then connection is closed This would explain things, but then... if I remove this
for
it still doesn't send the body. Eeeh. I hope I'll figure this out,
wire
is soooo much simpler than "native" grpc stuff.
j
you should close the send channel
@Benoit Quenaudon we should confirm that closing the send channel doesn’t close the whole connection! That’s valid for unidirectional streaming
b
I'm sorry, ok. Hmm I'll check
d
It actually looks 👌: it doesn't close the connection: after doing
close()
I can see that server keeps sending me outbound data requests in the stream. But for some reason I dont receive them in the receive channel, okhttp's event listener reports
readResponseBody
and nothing after that, I guess no body is being read. wire's sample has only bi-directional streaming example, so I'm not sure if i'm doing everything right, but I do it like in the snippet I posted above.
Also maybe related: after I
close()
, while connection is not closed, but logging interceptor prints
<--- 200 OK
, so does this mean that the streaming response is considered to be done/finished? Maybe that's why I don't receive anything in the receive channel? (streaming responses still continue to 'tick' in the server logs)
b
I'll try to write a test
d
Yep, I saw them too, forgot to mention. Still, I don't get anything in the receive channel for some reason. Server does send the stream, every 2 seconds, see it in server logs, but receive channel is empty on my side. Do you use unidirectional streaming in cash app (or wherever?). Maybe this issue manifests only on "live" connections, in non-test environment.
b
We have duplex working in cash app
But we don't close the request until the end
d
I'd try to reproduce my problem on wire's "whiteboard" sample, to come up with the minimal example, but there's that issue with MainActivity not available in the apk (which I still didn't wrap my head around 🙂 )
b
Yeah the sample is broken right now. Maybe try to write a test in grpc client tests with the same schema that you have and see if the test passes
d
ok! I'll report if I'll find anything simply-reproducable.
r
Curiously, I see something similar, receive() is successful once, but upon second call it never returns. When I try stepping into the receive call android studio misbehaves and I usually crash straight up. So I'm guessing I'm passing bad data in or something else isn't setup correctly, which is what I'm investigating.
Also, that test in GrpcClientTest can't be being called (or can it?). It's using
receiveOrNull
which is error deprecated for
receiveCatching().getOrNull()
. Maybe I'm missing something?
Oh, and I forgot to mention, if I use
receiveCatching
in my loop to get data, I don't have to
close()
the sendChannel in order to receive that one message. But if I try to use the
for (update in receiveUpdateChannel)
stuff, it only receives that one message if I do
close
the channel.
d
I suspect there's something weird with concurrency going on.