Как мне отключить соединение OkHttp3 sse? - PullRequest
3 голосов
/ 08 октября 2019

Проблема:

Я пытаюсь создать клиент, который может получать события от сервера, используя SSE (события, отправленные сервером), и я использую OkHttp3 для этого в сочетании с OkHttp3-sse. библиотека (com.squareup.okhttp3: okhttp: 4.1.0 и com.squareup.okhttp3: okhttp-sse: 4.1.0). Я могу подключиться к серверу и получать события нормально, но в какой-то момент я хочу отключить клиент и закрыть свое приложение. Вот в чем проблема. Соединение закрывается, но приложение не закрывается, возможно, из-за того, что ConnectionPool не закрывается.

Попытка:

Поскольку вряд ли есть какая-либо документация по использованию OkHttp3-Библиотека SSE, я попытался восстановить код из кода, что делать. Я попытался:

  • вызов RealEventSource.cancel(), который отключается, но висит на потоке
  • вызов OkHttpClient.dispatcher().cancelAll(), который также отключается, но остается висеть на потоке
  • вызов Response.close(), который передается EventSourceListener.onOpen()

Нахождение:

В качестве альтернативы я рассмотрел https://github.com/heremaps/oksse, который имеетRealServerSentEvent.close() вызов, который делает то, что я ожидаю. Он закрывает соединение и останавливает все потоки, позволяя приложению полностью завершиться. Я посмотрел на реализацию класса RealServerSentEvent, чтобы увидеть, как реализация отличается от RealEventSource. Я думаю, что разница в условиях цикла чтения:

RealEventSource строка 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
      }

сравнивается с RealServerSentEvent строка 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()) {
            }

Реализация OkSSE включает условие, если call.isCanceled() в цикле, а как OkHttp3-sse - нет. Я подозреваю, что из-за этого OkHttp3-sse не выходит, но я могу ошибаться.

Или я наблюдаю за намеченным способом отключения?

Ответы [ 2 ]

3 голосов
/ 09 октября 2019

Вы используете API правильно, и OkHttp должен вызывать сбой чтения с IOException, когда вызов отменен. Очевидно, этого не происходит, что я прочитал как ошибку в OkHttp.

Следующие шаги: сообщить об ошибке в OkHttp. Если вы сможете сделать это с помощью исполняемого тестового примера, я позабочусь, чтобы это было исправлено очень скоро.

2 голосов
/ 16 октября 2019

В конце концов я обнаружил, что соединение можно корректно отключить, вызвав:

eventSource.cancel();
client.dispatcher().executorService().shutdown();

Поскольку это не требует каких-либо изменений в библиотеке, я закрыл отчет об ошибке.

...