Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I disconnect a OkHttp3 sse connection?

Tags:

okhttp

Problem:

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.

Attempted:

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:

  • call RealEventSource.cancel() which is disconnecting, but is hanging on a thread
  • call OkHttpClient.dispatcher().cancelAll() which is also disconnecting, but remains hanging on a thread
  • call Response.close() which is passed to EventSourceListener.onOpen()

Finding:

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?

like image 547
Hoppie Avatar asked Oct 08 '19 18:10

Hoppie


People also ask

Should OkHttp client be a singleton?

OkHttp performs best when you create a single OkHttpClient instance and reuse it for all of your HTTP calls. This is because each client holds its own connection pool and thread pools. Reusing connections and threads reduces latency and saves memory.

What is OkHttp client?

OkHttp is an efficient HTTP & HTTP/2 client for Android and Java applications. It comes with advanced features, such as connection pooling (if HTTP/2 isn't available), transparent GZIP compression, and response caching, to avoid the network completely for repeated requests.

What is OkHttp connection pool?

OkHttp is an HTTP client from Square for Java and Android applications. It's designed to load resources faster and save bandwidth. OkHttp is widely used in open-source projects and is the backbone of libraries like Retrofit, Picasso, and many others.


2 Answers

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.

like image 117
Jesse Wilson Avatar answered Sep 23 '22 13:09

Jesse Wilson


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.

like image 34
Hoppie Avatar answered Sep 22 '22 13:09

Hoppie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!