launchdarkly / swift-eventsource

Server-sent events (SSE) client implementation in Swift for iOS, macOS, tvOS, and watchOS
https://launchdarkly.github.io/swift-eventsource/
Other
187 stars 34 forks source link

Why does the delegate reconnect even if there is no error? #81

Closed shaotaoliu closed 2 months ago

shaotaoliu commented 3 months ago

The open method is called and the response is returned successfully, but then the following function is called (and so the onMessage is not reached)

public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)

The error is nil, so it reconnects and keeps re-calling the API even if the API is successful. Is it a bug?

tanderson-ld commented 3 months ago

Hi @shaotaoliu , thanks for reporting this.

  1. Are you using this library standalone or as part of the LaunchDarkly iOS SDK?
  2. Do you have any logs that go along with the behavior you are seeing?
  3. Do you have examples of messages that were received when this behavior occurs?
shaotaoliu commented 3 months ago

Hi @tanderson-ld, thank you for your reply.

  1. I'm using the package LDSwiftEventSource.

  2. Yes, see the logs below:

Starting EventSource client initial reply received State: raw -> open Opened Connection unexpectedly closed. State: open -> closed Waiting 1.7817 seconds before reconnecting... Closed Starting EventSource client initial reply received State: closed -> open Opened Connection unexpectedly closed. State: open -> closed Closed Waiting 3.4727 seconds before reconnecting... Starting EventSource client initial reply received State: closed -> open Opened Connection unexpectedly closed. State: open -> closed Closed Waiting 7.2460 seconds before reconnecting... ......

  1. Yes, I have an example of the message.

data: {"chatId":"550e8400-e29b-41d4-a716-446655440000","gid":"123e4567-e89b-12d3-a456-426614174000","seq":1,"type":"text","value":{"text":"Your credit file is locked.","metadata":{}},"last":false}

shaotaoliu commented 3 months ago

Hi @tanderson-ld What happens if the server closes the connection after finishing sending the events? Will the above urlSession function be called?

tanderson-ld commented 3 months ago

Hi @tanderson-ld What happens if the server closes the connection after finishing sending the events? Will the above urlSession function be called?

It does appear so.

If the data is being transmitted in full, but onMessage is not triggering, perhaps the data is not properly terminated. Is this a custom SSE server implementation? If so, I recommend reviewing this specification.

Lines must be separated by either a U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF) character pair, a single U+000A LINE FEED (LF) character, or a single U+000D CARRIAGE RETURN (CR) character.

Since connections established to remote servers for such resources are expected to be long-lived, UAs should ensure that appropriate buffering is used. In particular, while line buffering with lines are defined to end with a single U+000A LINE FEED (LF) character is safe, block buffering or line buffering with different expected line endings can cause delays in event dispatch.

shaotaoliu commented 3 months ago

@tanderson-ld Actually the onMessage function is called, sorry for the mistake. It seems that LDSwiftEventSource expects the client closes the connection, so what should I do in the following two scenarios?

  1. If the client forgot to close the connection and opens a new connection, it will fail with a timeout error.
  2. If the server closes the connection after finishing the events, the above urlSession function will be called and the client tries to reconnect to the server, which is not expected. How to avoid it? Thank you!

My second question looks like the pooling or long-pooling described here: https://eclipse-ee4j.github.io/jersey.github.io/documentation/3.0.0/sse.html#:~:text=If%20the%20server%20has%20no,a%20request%20to%20a%20server.

tanderson-ld commented 3 months ago
  1. That sounds like the server is not willing to have multiple connections.
  2. This is as designed and is expected. This library was created for use in our feature flagging SDK. It makes best effort to maintain a connection to our flag delivery network.

You may need to fork this repo and make modifications to meet your needs.