Conversation
* feat(storage): add progress stall timeout for S3 uploads - Add progressStallTimeoutInterval to StorageConfiguration and AWSS3StoragePluginConfiguration - Single upload: stall timer in StorageServiceSessionDelegate, resets on didSendBodyData - Multipart upload: stall timer in StorageMultipartUploadSession - New error: AWSS3TransferUtilityErrorDomain, code 10 (makeProgressStallTimeoutError) - Dispatch .failed events on main thread for faster UI feedback - Unit tests: StorageErrorConstants, StorageConfiguration, PluginConfiguration, StorageServiceSessionDelegate, StorageMultipartUploadSession - Default: 0 (disabled), opt-in via configuration Made-with: Cursor * docs: add progress stall timeout documentation - Storage plugin README with configuration and error handling - Enhanced doc comments for AWSS3StoragePluginConfiguration - StorageErrorConstants documentation for stall timeout error - CHANGELOG entry - .gitignore for local changelog Made-with: Cursor * refactor(storage): ProgressStallTimeout type and per-operation override Introduce ProgressStallTimeout (.disabled, .interval) to replace raw TimeInterval naming. Plugin configuration uses progressStallTimeout; upload options can override per operation. Update tests, README, and CHANGELOG. Made-with: Cursor * test(storage): serialize Amplify reset/configure in operation unit tests Route reset and configure through a shared actor so concurrent test setUp/tearDown cannot leave Hub in pendingConfiguration when operations use Amplify.Hub. Update UploadFileOperationTests2 for async setUp. * fix(storage): address stall timeout review (errors, tests, Hub lifecycle) - Use StorageError.unknown for stall timeouts; remove NSError helper constants - Resolve stall interval on StorageTransferTask (-1 defers to StorageConfiguration) - Stall path: fail, unregister, then cancel; reset timer on multipart part progress - Restore upload operation failure dispatch threading; rename tests per review - Add integration tests for progressStallTimeout on small and multipart uploads - Fix OperationTestBase vs XCTest async ordering (Hub pendingConfiguration) - Reset Amplify in BaseConfigTests setUp when add() requires clean framework Made-with: Cursor * test(storage): rename progress stall timeout config test to camelCase Made-with: Cursor * Revert Storage README and .gitignore per review Made-with: Cursor * chore: revert Unreleased CHANGELOG entry; rename multipart stall test Made-with: Cursor * test(storage): add integration test for multipart stall timeout failure Made-with: Cursor * test(storage): stabilize stall timeout test on slow simulators Increase the stall interval and fulfillment timeout so the GCD timer has enough slack to fire reliably on watchOS/tvOS/iOS simulators in CI. Made-with: Cursor * refactor(storage): remove redundant StorageConfiguration init Drop the single-arg init(forBucket:) overload; the init(forBucket:progressStallTimeout:) variant already provides the same behavior via the default progressStallTimeout value. Made-with: Cursor * test(storage): rename stall tests to camelCase and stabilize mock session - Rename progress stall unit and integration tests from snake_case to camelCase to match review feedback and the rest of the suite. - Retain ARC ownership of the mock service/delegate in the async stall test so the delegate's weak reference to the service survives until the stall timer fires on slow simulators. - Configure the storage service mock with URLSessionConfiguration.default so the underlying URLSession initializes cleanly on iOS/watchOS/tvOS simulators that lack the application-identifier entitlement required for background sessions. Made-with: Cursor * refactor(storage): use optional TimeInterval for stall timeout sentinel Replace the -1 sentinel in StorageTransferTask.progressStallTimeoutSeconds with an optional TimeInterval. `nil` now signals "resolve from StorageConfiguration" (used for tasks restored from persistence), and resolvedProgressStallTimeoutSeconds falls back to the configuration value via nil-coalescing. Made-with: Cursor * style(storage): apply swiftformat to StorageMultipartUploadSession Drop redundant self. references inside the stall-timer closure to satisfy SwiftFormat 0.60.1 rules used by CI. Made-with: Cursor * test(storage): remove flaky multipart stall timeout failure test The sub-second interval used to force a stall during multipart uploads is too timing-sensitive for CI. Per reviewer feedback, drop the test and its associated error-chain helper; the unit-level coverage in StorageServiceSessionDelegateTests is sufficient to exercise the stall path without relying on network timing. Made-with: Cursor --------- Co-authored-by: Harsh <6162866+harsh62@users.noreply.github.com> Co-authored-by: Abhash Kumar Singh <thisisabhash@gmail.com>
…th change (#4202) * fix(api): recycle WebSocket and resubscribe on same-online network path change Resolve zombie subscription state after iOS recycles the TCP route while NWPathMonitor continues reporting path.status == .satisfied (e.g. during a scenePhase inactive -> active transition on the same Wi-Fi network). Two layered bugs were addressed: 1. WebSocketClient.onNetworkStateChange dropped (.online, .online) transitions through `default: break`. NWPathMonitor's pathUpdateHandler only fires on real path changes, so a second .satisfied emission while already online means the underlying path was swapped and the existing URLSessionWebSocketTask is bound to a stale route. The task's state stays .running but reads/writes silently fail, leaving the cached client zombied. Added an explicit (.online, .online) case that cancels the stale task and re-establishes the connection. Guarded by connection?.state == .running so we don't recycle a torn-down connection. 2. AppSyncRealTimeSubscription.subscribe() early-returned when local state was already .subscribed, so after the WebSocket recycled and resumeExistingSubscriptions() fired, no .start request was resent to the server. The server had already forgotten the subscription, so the subscription was silently broken. Added prepareForResubscribe() which resets local state to .none, and call it from resumeExistingSubscriptions() before re-invoking subscribe(). Fixes #3976 * test(websocket): tolerate spontaneous NWPathMonitor fires in integration test `testWebSocketClient_withRealNetworkMonitor_whenPathChangesWhileOnline_shouldRecycle` was failing deterministically on watchOS CI (watchOS 26.x on Apple Watch Series 10). Reproduced locally on watchOS 26.1 with the same 5-second timeout signature. Root cause: the test used `verifyConnected()` which XCTFails on any event other than `.connected`. On watchOS, the real `NWPathMonitor` inside `AmplifyNetworkMonitor` fires `pathUpdateHandler` spontaneously during startup — often multiple times — which either (a) delivers an `.online` before the WebSocketClient's Combine sink attaches, causing the scan to miss the priming event and never reach `(.online, .online)`, or (b) fires an extra `.satisfied` after the client is connected, triggering a recycle that `verifyConnected` sees as an unexpected `.disconnected`. Rewrote the test to: - Subscribe to the WebSocket publisher before calling `connect()`, so no events can be missed during sink-attach. - Count `.connected` events with a thread-safe counter and expect two (initial connect + post-recycle reconnect) rather than asserting exact event sequences. - Tolerate `.disconnected`/`.error`/`.string`/`.data` events so NWPathMonitor-driven noise doesn't fail the test. Verified on watchOS 26.1 (Apple Watch Series 11 simulator) — passes 8/8 WebSocketClientTests, 1325/1325 AWSPluginsCoreTests. iOS 26.1 still passes 8/8. * docs(tests): apply Given/When/Then doc comments to new regression tests The four regression tests added for issue #3976 were written with plain comment blocks instead of the project-standard Given/When/Then doc comments. Retrofit them to match the convention documented in AGENTS.md. Also strengthen the testing-conventions section in AGENTS.md to mark Given/When/Then doc comments as mandatory for all new or modified tests, so future contributors and automated agents follow the rule. Tests updated: - testWebSocketClient_whenNetworkPathChangesWhileOnline_shouldRecycleConnection - testWebSocketClient_withRealNetworkMonitor_whenPathChangesWhileOnline_shouldRecycle - testAmplifyNetworkMonitor_whenOnlineEmittedTwice_publishesOnlineOnlineTuple - testSubscribe_afterOnlineToOnlinePathChange_shouldRecycleAndResubscribe No behavioral change — doc comments only. All 8 WebSocketClientTests pass on iOS 26.1 and watchOS 26.1. * test(api): address PR #4202 review nits on E2E regression test - Drop the obsolete config-location note from the doc comment; every test in the file has the same requirement, enforced in setUp. - Replace the plain `var subscribedCount = 0` with an AtomicInt helper matching the unit-test pattern. The counter is mutated from a Combine sink closure, which can fire on any scheduler — theoretical data race that AtomicInt closes cleanly.
…refresh (#4208) * fix(auth): Use inputUsername for device metadata lookup during token refresh * fix(auth): Use inputUsername for device metadata lookup during token refresh
harsh62
approved these changes
May 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
kickoff release