nats-io / nats.swift

Swift client for NATS, the cloud native messaging system.
Apache License 2.0
22 stars 4 forks source link

Task Continuation Misuse in NATS Swift Client During Background Authentication Timeout #84

Open dmaulikr opened 1 month ago

dmaulikr commented 1 month ago

Observed behavior

We are encountering a crash in the NATS Swift client, specifically when the app is in the background for extended periods or idle without activity. The crash log shows the following error: Fatal error: SWIFT TASK CONTINUATION MISUSE: sendClientConnectInit() tried to resume its continuation more than once, throwing NatsServerError(description: 'Authentication Timeout')

It appears that the continuation in the sendClientConnectInit() method is being resumed more than once, possibly due to background disconnections or authentication timeouts.

Screenshot 2024-09-20 at 2 09 46 PM

This happens after leaving the app idle for extended periods or when it is in the background. The crash is not consistently reproducible but occurs intermittently, sometimes while the app is still in the background and sometimes when it’s brought back to the foreground.

Here's the code:

public class NatsManager {
    static let shared = NatsManager()
    let serverURL = "nats://dev-events-aub.mintoak.com:4222"
    private var client: NatsClient?

    func connect() {
        let client = NatsClientOptions()
            .url(URL(string: serverURL)!)
            .nkey("SUAHCEFNHKYV7DDFH4XHBPJUWNRSLB6I5QEXZUIXEQNSS3BJSMR5DFU2MI")
            .build()

        client.on(.connected) { event in
            print("NATS connection established")
        }

        let task = Task.init {
            do {
                try await client.connect()
                self.client = client
                print("Successfully connected to NATS server")
            } catch {
                print("Failed to connect to NATS server: \(error)")
            }
        }
    }

Expected behavior

Server and client version

Host environment

No response

Steps to reproduce

While the crash is not consistently reproducible, the following general conditions have been observed:

1.  Use the NATS Swift client to establish a connection with NatsClientOptions().
2.  Publish events as needed (client is connected and publishing works fine initially).
3.  Move the app to the background or leave it idle for an extended period (e.g., a few hours).
4.  After some time (while the app is still in the background or just when it is brought back to the foreground), the app crashes with the error related to task continuation misuse.

Note: The crash seems to occur more frequently when the app is left idle or in the background for long periods but without a specific pattern that consistently reproduces it.