Skip to content

chore: kickoff release #4006

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

Merged
merged 2 commits into from
Jun 12, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,13 @@ extension WebSocketClient: URLSessionWebSocketDelegate {

let nsError = error as NSError
switch (nsError.domain, nsError.code) {
case (NSURLErrorDomain.self, NSURLErrorNetworkConnectionLost), // connection lost
(NSPOSIXErrorDomain.self, Int(ECONNABORTED)): // background to foreground
case (NSURLErrorDomain.self, NSURLErrorNetworkConnectionLost),
(NSURLErrorDomain.self, NSURLErrorCannotConnectToHost),
(NSURLErrorDomain.self, NSURLErrorTimedOut),
(NSURLErrorDomain.self, NSURLErrorNotConnectedToInternet),
(NSURLErrorDomain.self, NSURLErrorDataNotAllowed),
(NSPOSIXErrorDomain.self, Int(ECONNABORTED)),
(NSPOSIXErrorDomain.self, 57):
self.subject.send(.error(WebSocketClient.Error.connectionLost))
Task { [weak self] in
await self?.networkMonitor.updateState(.offline)
Expand Down Expand Up @@ -283,11 +288,11 @@ extension WebSocketClient {
}

switch stateChange {
case (.online, .offline):
log.debug("[WebSocketClient] NetworkMonitor - Device went offline")
case (.online, .offline), (.none, .offline), (.online, .none):
log.debug("[WebSocketClient] NetworkMonitor - Device went offline or network status became unknown")
self.connection?.cancel(with: .invalid, reason: nil)
self.subject.send(.disconnected(.invalid, nil))
case (.offline, .online):
case (.offline, .online), (.none, .online):
log.debug("[WebSocketClient] NetworkMonitor - Device back online")
await self.createConnectionAndRead()
default:
Expand Down Expand Up @@ -335,13 +340,19 @@ extension WebSocketClient {
}

switch closeCode {
case .internalServerError:
case .internalServerError,
.abnormalClosure,
.invalid,
.policyViolation:
log.debug("[WebSocketClient] Retrying on closeCode: \(closeCode)")
let delayInMs = await retryWithJitter.next()
Task { [weak self] in
try await Task.sleep(nanoseconds: UInt64(delayInMs) * 1_000_000)
await self?.createConnectionAndRead()
}
default: break
default:
log.debug("[WebSocketClient] Not retrying for closeCode: \(closeCode)")
break
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,14 +229,14 @@ enum StorageMultipartUpload {
case .parts(let uploadId, let uploadFile, let partSize, let parts):
self = .paused(uploadId: uploadId, uploadFile: uploadFile, partSize: partSize, parts: parts)
default:
throw Failure.invalidStateTransition(reason: "Cannot pause from current state: \(self)")
throw Failure.invalidStateTransition(reason: "Cannot pause upload: upload must be in progress")
}
case .resuming:
switch self {
case .paused(let uploadId, let uploadFile, let partSize, let parts):
self = .parts(uploadId: uploadId, uploadFile: uploadFile, partSize: partSize, parts: parts)
default:
throw Failure.invalidStateTransition(reason: "Cannot resume from current state: \(self)")
throw Failure.invalidStateTransition(reason: "Cannot resume upload: upload must be paused")
}
break
case .completing(let taskIdentifier):
Expand All @@ -246,20 +246,20 @@ enum StorageMultipartUpload {
case .parts:
self = .completed(uploadId: uploadId)
default:
throw Failure.invalidStateTransition(reason: "Cannot complete from current state: \(self)")
throw Failure.invalidStateTransition(reason: "Cannot complete upload: upload must be in progress")
}
case .aborting(let error):
if let uploadId = uploadId {
self = .aborting(uploadId: uploadId, error: error)
} else {
throw Failure.invalidStateTransition(reason: "Cannot abort from current state: \(self)")
throw Failure.invalidStateTransition(reason: "Cannot abort upload: no upload ID available")
}
case .aborted(let uploadId, let error):
switch self {
case .created, .parts, .aborting:
self = .aborted(uploadId: uploadId, error: error)
default:
throw Failure.invalidStateTransition(reason: "Cannot abort from current state: \(self)")
throw Failure.invalidStateTransition(reason: "Cannot abort upload: upload must be in progress or created")
}
case .failed(let uploadId, let error):
switch self {
Expand All @@ -268,7 +268,7 @@ enum StorageMultipartUpload {
case .parts(_, _, _, let parts):
self = .failed(uploadId: uploadId, parts: parts, error: error)
default:
throw Failure.invalidStateTransition(reason: "Cannot fail from current state: \(self)")
throw Failure.invalidStateTransition(reason: "Cannot fail upload: invalid state for failure")
}
}
}
Expand All @@ -277,7 +277,7 @@ enum StorageMultipartUpload {
mutating func transition(uploadPartEvent: StorageUploadPartEvent) throws {
guard !isAborting, !isAborted else { return }
guard case .parts(let uploadId, let uploadFile, let partSize, var parts) = self else {
throw Failure.invalidStateTransition(reason: "Parts are required for this transition: \(uploadPartEvent)")
throw Failure.invalidStateTransition(reason: "Cannot process part event: upload must be in progress")
}

let partNumber = uploadPartEvent.number
Expand All @@ -297,12 +297,12 @@ enum StorageMultipartUpload {
parts[index] = .inProgress(bytes: part.bytes, bytesTransferred: 0, taskIdentifier: taskIdentifier)
case .progressUpdated(_, let bytesTransferred, _):
guard case .inProgress(let bytes, _, let taskIdentifier) = part else {
throw Failure.invalidStateTransition(reason: "Part cannot update progress in current state: \(self)")
throw Failure.invalidStateTransition(reason: "Cannot update progress: part must be in progress")
}
parts[index] = .inProgress(bytes: bytes, bytesTransferred: bytesTransferred, taskIdentifier: taskIdentifier)
case .completed(_, let eTag, _):
guard case .inProgress(let bytes, _, _) = part else {
throw Failure.invalidStateTransition(reason: "Part cannot be completed in current state: \(self)")
throw Failure.invalidStateTransition(reason: "Cannot complete part: part must be in progress")
}
parts[index] = StorageUploadPart.completed(bytes: bytes, eTag: eTag)
case .failed:
Expand Down
Loading