Reputation: 329
I'm trying to create a client that can receive events from a server using SSE (server-sent events) and I'm using OkHttp3 to do that, combined with the OkHttp3-sse library (com.squareup.okhttp3:okhttp:4.1.0 & com.squareup.okhttp3:okhttp-sse:4.1.0).
I am able to connect to the server and receive the events just fine, but at some point in time, I want to disconnect the client and shutdown my application. That is were the problem is. The connection gets closed, but the application is not shutting down, probably due to the ConnectionPool
not closing.
As there is hardly any documentation on the use of the OkHttp3-sse library, I have tried to reverse engineer from the code what to do. I have tried to:
RealEventSource.cancel()
which is disconnecting, but is hanging on a threadOkHttpClient.dispatcher().cancelAll()
which is also disconnecting, but remains hanging on a threadResponse.close()
which is passed to EventSourceListener.onOpen()
As an alternative, I have looked at https://github.com/heremaps/oksse which has the RealServerSentEvent.close()
call which is doing what I expect. It closes the connection and stops all threads allowing the application to shutdown completely.
I have looked at the implementation of the RealServerSentEvent
class to see how the implementation differs from RealEventSource
. I think the difference is in the conditions of the read loop:
RealEventSource
line https://github.com/square/okhttp/blob/master/okhttp-sse/src/main/java/okhttp3/internal/sse/RealEventSource.kt#L75:
try {
listener.onOpen(this, response)
while (reader.processNextEvent()) {
}
} catch (e: Exception) {
listener.onFailure(this, e, response)
return
}
compares to
RealServerSentEvent
line https://github.com/heremaps/oksse/blob/master/src/main/java/com/here/oksse/RealServerSentEvent.java#L94:
listener.onOpen(this, response);
//noinspection StatementWithEmptyBody
while (call != null && !call.isCanceled() && sseReader.read()) {
}
The OkSSE
implementation includes the condition if the call.isCanceled()
in the loop, where as the OkHttp3-sse
does not. I suspect this is causing OkHttp3-sse
not to exit, but I might be mistaken.
Or, am I overseeing the intended way of disconnecting?
Upvotes: 8
Views: 3983
Reputation: 329
Eventually I found the connection can be gracefully shut down by calling:
eventSource.cancel();
client.dispatcher().executorService().shutdown();
As this does not require any changes to the library, I closed the bug report.
Upvotes: 7
Reputation: 40623
You're using the API correctly and OkHttp should be causing the read to fail with an IOException when the call is canceled. Obviously this isn't happening which I read as a bug in OkHttp.
Next steps: report the bug to OkHttp. If you can do so with an executable test case I'll make sure this gets fixed real soon.
Upvotes: 3