Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix connection not resuming after guest user goes to background #3483

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

# Upcoming

### 🔄 Changed
## StreamChat
### 🐞 Fixed
- Fix connection not resuming after guest user goes to background [#3483](https://github.com/GetStream/stream-chat-swift/pull/3483)

# [4.66.0](https://github.com/GetStream/stream-chat-swift/releases/tag/4.66.0)
_November 05, 2024_
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,10 @@ struct DemoAppConfig {
/// The app secret from the dashboard.
let appSecret: String
/// The duration in seconds until the token is expired.
let duration: TimeInterval
let expirationDuration: TimeInterval
/// In order to test token refresh fails, we can set a value of how
/// many token refresh will succeed before it starts failing.
/// By default it is 0. Which means it will always succeed.
let numberOfSuccessfulRefreshesBeforeFailing: Int
/// many token refresh will fail before a successful one.
let numberOfFailures: Int
}
}

Expand Down Expand Up @@ -317,8 +316,8 @@ class AppConfigViewController: UITableViewController {
self?.demoAppConfig.isLocationAttachmentsEnabled = newValue
}
case .tokenRefreshDetails:
if let tokenRefreshDuration = demoAppConfig.tokenRefreshDetails?.duration {
cell.detailTextLabel?.text = "Duration: \(tokenRefreshDuration)s"
if let tokenRefreshDuration = demoAppConfig.tokenRefreshDetails?.expirationDuration {
cell.detailTextLabel?.text = "Duration before expired: \(tokenRefreshDuration)s"
} else {
cell.detailTextLabel?.text = "Disabled"
}
Expand Down Expand Up @@ -626,28 +625,28 @@ class AppConfigViewController: UITableViewController {
}
}
alert.addTextField { textField in
textField.placeholder = "Duration (Seconds)"
textField.placeholder = "Expiration duration (Seconds)"
textField.keyboardType = .numberPad
if let duration = self.demoAppConfig.tokenRefreshDetails?.duration {
if let duration = self.demoAppConfig.tokenRefreshDetails?.expirationDuration {
textField.text = "\(duration)"
}
}
alert.addTextField { textField in
textField.placeholder = "Number of Refreshes Before Failing"
textField.placeholder = "Number of refresh fails"
textField.keyboardType = .numberPad
if let numberOfRefreshes = self.demoAppConfig.tokenRefreshDetails?.numberOfSuccessfulRefreshesBeforeFailing {
if let numberOfRefreshes = self.demoAppConfig.tokenRefreshDetails?.numberOfFailures {
textField.text = "\(numberOfRefreshes)"
}
}

alert.addAction(.init(title: "Enable", style: .default, handler: { _ in
guard let appSecret = alert.textFields?[0].text else { return }
guard let duration = alert.textFields?[1].text else { return }
guard let successfulRetries = alert.textFields?[2].text else { return }
guard let numberOfFailures = alert.textFields?[2].text else { return }
self.demoAppConfig.tokenRefreshDetails = .init(
appSecret: appSecret,
duration: TimeInterval(duration) ?? 60,
numberOfSuccessfulRefreshesBeforeFailing: Int(successfulRetries) ?? 0
expirationDuration: TimeInterval(duration) ?? 60,
numberOfFailures: Int(numberOfFailures) ?? 0
)
}))

Expand Down
7 changes: 3 additions & 4 deletions DemoApp/Shared/Token+Development.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,15 @@ extension StreamChatWrapper {
let generatedToken: Token? = _generateUserToken(
secret: refreshDetails.appSecret,
userID: initialToken.userId,
expirationDate: Date().addingTimeInterval(refreshDetails.duration)
expirationDate: Date().addingTimeInterval(refreshDetails.expirationDuration)
)

if generatedToken == nil {
log.error("Demo App Token Refreshing: Unable to generate token. Using initialToken instead.")
}

let numberOfSuccessfulRefreshes = refreshDetails.numberOfSuccessfulRefreshesBeforeFailing
let shouldNotFail = numberOfSuccessfulRefreshes == 0
if shouldNotFail || self.numberOfRefreshTokens >= numberOfSuccessfulRefreshes {
let shouldNotFail = refreshDetails.numberOfFailures == 0
if shouldNotFail || self.numberOfRefreshTokens >= refreshDetails.numberOfFailures {
print("Demo App Token Refreshing: New token generated successfully.")
let newToken = generatedToken ?? initialToken
completion(.success(newToken))
Expand Down
1 change: 0 additions & 1 deletion Sources/StreamChat/ChatClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,6 @@ public class ChatClient {
/// Disconnects the chat client from the chat servers. No further updates from the servers
/// are received.
public func disconnect(completion: @escaping () -> Void) {
connectionRecoveryHandler?.stop()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to be safe because recovery handler checks for current connection state and does not attempt to reconnect if the state is disconnected with userInitiated. 🤔

var canReconnectFromOffline: Bool {
        …
        switch webSocketClient.connectionState {
        case .disconnected(let source) where source == .userInitiated:
            return false

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes exactly the reconnection handler although alive, it won't do nothing

connectionRepository.disconnect(source: .userInitiated) {
log.info("The `ChatClient` has been disconnected.", subsystems: .webSocket)
completion()
Expand Down
Loading