| Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 |
| Prepare 5.12.0 (#4035) ### Goals :soccer: This PR prepares the 5.12.0 release. | 4 个月前 |
| Fix watchOS Memory Leaks (#3110) * Add watchOS sample project for testing. * Always disassociate on watchOS. * Add information comment about watchOS workaround. * Clean up the watchOS example. * Add bug and workarounds to README and documentation. * Add proper licensing headers. * Delay completion of request for test stability. | 6 年前 |
| Lazy Requests, per-Request Features (#3996) ### Issue Link :link: Closes #3992, other feature requests. ### Goals :soccer: This PR includes four major new features: 1. By default, all `Request` set up is now fully lazy and does not start until the instance is resumed, whether automatically or manually. Virtually all users should be unimpacted by this change, aside from seeing fewer race conditions. For those that do see issues, the previous behavior can be restored by passing `requestSetup: .eager` to the `Session.init`. 2. Speaking of `resume()`, automatic resume is now controllable on a per-`Request` basis using the `shouldAutomaticallyResumeParameter`. By default this is `nil` an obeys the `Session` setting. 3. You can now add a `RequestAdapter`, `RequestRetrier`, or `RequestInterceptor` after `Request.init`, like any other chained Alamofire API. This is what necessitated the lazy start change, as adapters added in this manner are racy with eager `Request`s and may miss the appropriate lifetime events. 4. In addition to the interceptors, you can now add a per-`Request` `EventMonitor` that is composed after the `Session`'s event monitor. ```swift // shouldAutomaticallyResume defaults to nil, obeying the Session's setting, which // defaults to true. let request = <session>.request(<urlRequest>, shouldAutomaticallyResume: true) .adapt(using: <adapter>) .retry(using: <retrier>) .interceptor(<interceptor>) .eventMonitor(<monitor>) // request is inert until resumed or a response handler (when automatic resume is enabled) // is added. let response = await request.serializingDecoding(<Type>.self).response ``` ### Implementation Details :construction: Actual changes were rather minimal for the impact these features have. 1. Simple stored interceptor and monitor are now stored in the mutable state and new instance methods have been added to provide those values. 2. Internally, the previous `perform` method has been split between eager and lazy variants, and a new `RequestDelegate` method has been added to start the request when needed (upon resume). 3. Interceptors and EventMonitors are now composed `Session`-first, to guarantee that `Request`s can override `Session` interceptor behavior. ### Testing Details :mag: Tests against very specific `Request` lifetime timing were updated to use an `eager` `Session`, to replicate the previous behavior. However, these tests are almost always inherently racy, which made them flaky in CI, so this sort of breaking behavioral change is more of a bug fix. Users could never really rely on these event orderings before, as `Request` start and the events themselves would race. Additional tests added to cover the new APIs, and some tests have been converted to Swift Testing for performance and ergonomics. Additionally, the test target deployment targets have been bumped again, as the testing frameworks technically only deploy back to macOS 14, etc. | 8 个月前 |
| Lazy Requests, per-Request Features (#3996) ### Issue Link :link: Closes #3992, other feature requests. ### Goals :soccer: This PR includes four major new features: 1. By default, all `Request` set up is now fully lazy and does not start until the instance is resumed, whether automatically or manually. Virtually all users should be unimpacted by this change, aside from seeing fewer race conditions. For those that do see issues, the previous behavior can be restored by passing `requestSetup: .eager` to the `Session.init`. 2. Speaking of `resume()`, automatic resume is now controllable on a per-`Request` basis using the `shouldAutomaticallyResumeParameter`. By default this is `nil` an obeys the `Session` setting. 3. You can now add a `RequestAdapter`, `RequestRetrier`, or `RequestInterceptor` after `Request.init`, like any other chained Alamofire API. This is what necessitated the lazy start change, as adapters added in this manner are racy with eager `Request`s and may miss the appropriate lifetime events. 4. In addition to the interceptors, you can now add a per-`Request` `EventMonitor` that is composed after the `Session`'s event monitor. ```swift // shouldAutomaticallyResume defaults to nil, obeying the Session's setting, which // defaults to true. let request = <session>.request(<urlRequest>, shouldAutomaticallyResume: true) .adapt(using: <adapter>) .retry(using: <retrier>) .interceptor(<interceptor>) .eventMonitor(<monitor>) // request is inert until resumed or a response handler (when automatic resume is enabled) // is added. let response = await request.serializingDecoding(<Type>.self).response ``` ### Implementation Details :construction: Actual changes were rather minimal for the impact these features have. 1. Simple stored interceptor and monitor are now stored in the mutable state and new instance methods have been added to provide those values. 2. Internally, the previous `perform` method has been split between eager and lazy variants, and a new `RequestDelegate` method has been added to start the request when needed (upon resume). 3. Interceptors and EventMonitors are now composed `Session`-first, to guarantee that `Request`s can override `Session` interceptor behavior. ### Testing Details :mag: Tests against very specific `Request` lifetime timing were updated to use an `eager` `Session`, to replicate the previous behavior. However, these tests are almost always inherently racy, which made them flaky in CI, so this sort of breaking behavioral change is more of a bug fix. Users could never really rely on these event orderings before, as `Request` start and the events themselves would race. Additional tests added to cover the new APIs, and some tests have been converted to Swift Testing for performance and ergonomics. Additionally, the test target deployment targets have been bumped again, as the testing frameworks technically only deploy back to macOS 14, etc. | 8 个月前 |
| Add watchOS Testing (#3449) * Add watchOS tests, fix them, add action. * Return to timeout. * Fix YML. * Actually test on watchOS 7.4. * Turn off Metal validation for test scheme. * Enable retry tests by using different basic auth users. * Move logos, add MacStadium logo. | 5 年前 |
| Prepare 5.12.0 (#4035) ### Goals :soccer: This PR prepares the 5.12.0 release. | 4 个月前 |
| Stabilize CI And Fix Bugs (#4030) ### Goals :soccer: Alamofire has long had many tests which pass 100% of the time locally, but occasionally fail in CI. This PR fixes those tests, and the underlying issues uncovered, through a combination of manual and tool-assisted analysis over many, many CI runs. ### Implementation Details :construction: Some of these fixes are actually adoptions of existing testing patterns but most address timing issues in Alamofire itself. - `AuthenticationInterceptor` has been refactored to track more state and ensure requests are only retried once. - 🔥 There is a bit of a behavior change here. `AuthenticationInterceptor` will allow more requests to fail and wait for retry rather than holding them at the request adaptation step. This ensures they fully rerun their request pipeline to pick up the latest adaptations. Unfortunately, it wasn't possible to do this when held for adaptation. - `Request.suspend()` and `Request.cancel()` could be ineffective if called at narrow points within the `Request` lifecycle. These updates are now more atomic. - `Request.cancel()` (and overrides) could call `Request.finish()` when the request was already completed, leading to duplicate lifecycle events. - `Request.resume()` could create extra `URLSessionTask`s if called at narrow points in the lifecycle. - Similarly, rapid `Request.resume()` to `Request.suspend()` and back calls could lead a request performing multiple times. - `Request` could create multiple tasks during narrow points in its lifetime. - `Session.deinit` is now thread-safe. Unfortunately this required yet another lock, but should ensure it operates safely from any thread. - `Session.deinit` was internally racy, which could lead to duplicate `Request.finish()` calls. It now allows the `Session` to shut down while it finishes the requests separately in the `SessionDelegate`. - `Request` task updates were moved to the `Request` itself, to ensure they're always atomic relative to external state updates like `cancel()` or `resume()`. - `Request.onHTTPResponse`'s `.cancel` disposition didn't call the full `Request.cancel()`, which could lead to different behavior, like `EventMonitor` callbacks. - Most `unowned self` usage has been removed. - `DataStreamRequest`'s `outputStream` could have `write` called after `close()`, this is now properly checked. - `MIMEType` checking would improperly match invalid types like `text` to `text/plain`, this has been addressed and this parsing and matching are now specifically tested. - `DownloadRequest` now properly checks `!isCancelled` before attempting retry. - `DataTask` and `DownloadTask` didn't properly handle `cancel()` before creating their task. `Task.isCancelled` is now checked immediately after creation to ensure cancellation. Many test implementations have been updated: - All tests now use a unique `stored(Session())`, where possible. This ensures they never share state. - More data is used for upload and download requests tracking progress, but it may not be enough. Tests are so fast, and progress reporting isn't guaranteed, so the test may never be 100% reliable. - Separate stream setup from `async let`. Since `async let` can make sync work async, which means the stream setup races with the request itself. - Fixed the `URLProtocol` tests with correct event ordering. - Various tests were changed structurally to eliminate races. ### Testing Details :mag: Many tests updated and added. | 4 个月前 |
| Prepare 5.12.0 (#4035) ### Goals :soccer: This PR prepares the 5.12.0 release. | 4 个月前 |
| Lazy Requests, per-Request Features (#3996) ### Issue Link :link: Closes #3992, other feature requests. ### Goals :soccer: This PR includes four major new features: 1. By default, all `Request` set up is now fully lazy and does not start until the instance is resumed, whether automatically or manually. Virtually all users should be unimpacted by this change, aside from seeing fewer race conditions. For those that do see issues, the previous behavior can be restored by passing `requestSetup: .eager` to the `Session.init`. 2. Speaking of `resume()`, automatic resume is now controllable on a per-`Request` basis using the `shouldAutomaticallyResumeParameter`. By default this is `nil` an obeys the `Session` setting. 3. You can now add a `RequestAdapter`, `RequestRetrier`, or `RequestInterceptor` after `Request.init`, like any other chained Alamofire API. This is what necessitated the lazy start change, as adapters added in this manner are racy with eager `Request`s and may miss the appropriate lifetime events. 4. In addition to the interceptors, you can now add a per-`Request` `EventMonitor` that is composed after the `Session`'s event monitor. ```swift // shouldAutomaticallyResume defaults to nil, obeying the Session's setting, which // defaults to true. let request = <session>.request(<urlRequest>, shouldAutomaticallyResume: true) .adapt(using: <adapter>) .retry(using: <retrier>) .interceptor(<interceptor>) .eventMonitor(<monitor>) // request is inert until resumed or a response handler (when automatic resume is enabled) // is added. let response = await request.serializingDecoding(<Type>.self).response ``` ### Implementation Details :construction: Actual changes were rather minimal for the impact these features have. 1. Simple stored interceptor and monitor are now stored in the mutable state and new instance methods have been added to provide those values. 2. Internally, the previous `perform` method has been split between eager and lazy variants, and a new `RequestDelegate` method has been added to start the request when needed (upon resume). 3. Interceptors and EventMonitors are now composed `Session`-first, to guarantee that `Request`s can override `Session` interceptor behavior. ### Testing Details :mag: Tests against very specific `Request` lifetime timing were updated to use an `eager` `Session`, to replicate the previous behavior. However, these tests are almost always inherently racy, which made them flaky in CI, so this sort of breaking behavioral change is more of a bug fix. Users could never really rely on these event orderings before, as `Request` start and the events themselves would race. Additional tests added to cover the new APIs, and some tests have been converted to Swift Testing for performance and ergonomics. Additionally, the test target deployment targets have been bumped again, as the testing frameworks technically only deploy back to macOS 14, etc. | 8 个月前 |
| Linux and Windows Support (#3446) * Initial Linux build. * Add CI support. * Fix YML. * Use correct image. * Initial Windows Support (#3462) * Correct example (#3453) * Exclude NetworkReachabilityManager from Windows Fixes #3459. Windows does not have SystemConfiguration, so we have to exclude it * Initial windows support * Fix lock issues * Add Windows tests * Fix Windows mutex error * Remove enable test discovery * Combine Windows and Linux mutex lock with one common NSLock based class * Remove locked variable check * Simplify locking extension * Attempt to fix Windows build. * Reenable all platform tests. * Formatting. * Update README for new platforms. * Fix shields. * Another color. * Fix table. * Update issues. * Remove fixed issue. * Add SPM badge. * Spell it out. * Update to 5.4.1 on Linux, add Nightly. * Naming update. * Use concurrency group to cancel previous runs. * Use correct nightly image. * Use Firebreak for most builds. * Build with correct archs. * Fix Catalyst, tvOS builds. * Run Catalyst on GitHub. * 12.4 for Catalyst. * Try hardened runtime on Firebreak. * Get tests building on Linux. * Update Linux CI to build tests as well. * Add unsupported status for Linux and Windows. * Fix actions. * Run Catalyst on GitHub. * Build tests on Windows too. * Remove hardened runtime. * Run jobs when workflows change too. * Add timeouts to all jobs. * Enable CI on changes inside workflows. * Check changes in Package too. Co-authored-by: Alex Taffe <alex.taffe@gmail.com> | 5 年前 |
| Deprecate `NetworkReachabilityManager` (#3947) ### Issue Link :link: Fixes #3943 ### Goals :soccer: Apple's `SCNetworkReachability` types were deprecated in iOS 17.4 related OS versions. This PR deprecates `NetworkReachabilityManager` in favor of `NWPathMonitor` from Network.framework, which has been the better solution for many years now. This PR also updates various infrastructure bits, and deletes the `.swiftpm` directory to prevent Xcode from generating schemes when integrating the package. ### Implementation Details :construction: Class deprecated. ### Testing Details :mag: Tests deprecated. | 10 个月前 |
| Fix dash download (#2258x2) * Update docs with root_url to properly allow Dash downloads. * Commit missing logo image and regenerate. * Add trailing slash to fix Dash again. | 8 年前 |
| [PR #2250] Added Jazzy docs for the release to work with GitHub Pages. * Add Jazzy for documentation - Adds Jazzy as a developer dependency using Bundler - Configures Jazzy for Alamofire Jazzy repo: https://github.com/realm/jazzy * Generate initial Jazzy docs * Update readme to use Jazzy docs Update the readme to point to GitHub Pages (when it is configured in repo's settings) for locally generated Jazzy docs instead of CocoaDocs as it is now deprecated. * Update and lint configurations Responding to PR feedback on https://github.com/Alamofire/Alamofire/pull/2250 - Adds spacing in array in `.jazzy.yaml` file - Adds `.ruby-gemset` and `.ruby-version` files for Ruby version managers - Adds `cocoapods` as an explicit Ruby dev dependency - Updates Bundler lock to latest version of Bundler - Updates Readme to use lower-case `ttps://alamofire.github.io` | 8 年前 |
| Prepare 5.12.0 (#4035) ### Goals :soccer: This PR prepares the 5.12.0 release. | 4 个月前 |
| Refactor Project Structure, Break Request Types Out Into Separate Files (#3819) ### Goals :soccer: Alamofire's project structure has grown from its original single-file origin into many files on disk. Unfortunately, as the project has grown, the `Request.swift` file has grown rather gigantic, topping 2600 lines after the recent addition of `WebSocketRequest`. This PR breaks up `Request.swift` into separate files for each request type. It also moves all the previous serialization extensions from `ResponseSerialization.swift` to their associated type's files. This PR also restructures some of the project's layout on disk to make some Xcode groups proper folders. This PR also creates the `AFInfo` namespace and moves the previously internal `version` value into it to make it public. This PR also adds primary associated types to the serialization protocols. | 2 年前 |
| Update Infrastructure (#4017) ### Goals :soccer: This PR updates actions and dependencies. This PR also fixes two issues: - A rare duplicate metrics crash seen when using `usesClassicLoadingMode = false`. - An extremely rare logic race between the creation of a `StreamOf` and the start of iteration, where values could be lost. | 4 个月前 |
| Prepare 5.12.0 (#4035) ### Goals :soccer: This PR prepares the 5.12.0 release. | 4 个月前 |
| Prepare 5.12.0 (#4035) ### Goals :soccer: This PR prepares the 5.12.0 release. | 4 个月前 |
| Prepare 5.12.0 (#4035) ### Goals :soccer: This PR prepares the 5.12.0 release. | 4 个月前 |
| Prepare 5.10.2 Release (#3921) ### Goals :soccer: This PR prepares the 5.10.2 release. | 1 年前 |
| Prepare 5.12.0 (#4035) ### Goals :soccer: This PR prepares the 5.12.0 release. | 4 个月前 |
| Update Sponsorship to GitHub Sponsors (#3543) | 4 年前 |
| Update Infrastructure (#4017) ### Goals :soccer: This PR updates actions and dependencies. This PR also fixes two issues: - A rare duplicate metrics crash seen when using `usesClassicLoadingMode = false`. - An extremely rare logic race between the creation of a `StreamOf` and the start of iteration, where values could be lost. | 4 个月前 |
| Lazy Requests, per-Request Features (#3996) ### Issue Link :link: Closes #3992, other feature requests. ### Goals :soccer: This PR includes four major new features: 1. By default, all `Request` set up is now fully lazy and does not start until the instance is resumed, whether automatically or manually. Virtually all users should be unimpacted by this change, aside from seeing fewer race conditions. For those that do see issues, the previous behavior can be restored by passing `requestSetup: .eager` to the `Session.init`. 2. Speaking of `resume()`, automatic resume is now controllable on a per-`Request` basis using the `shouldAutomaticallyResumeParameter`. By default this is `nil` an obeys the `Session` setting. 3. You can now add a `RequestAdapter`, `RequestRetrier`, or `RequestInterceptor` after `Request.init`, like any other chained Alamofire API. This is what necessitated the lazy start change, as adapters added in this manner are racy with eager `Request`s and may miss the appropriate lifetime events. 4. In addition to the interceptors, you can now add a per-`Request` `EventMonitor` that is composed after the `Session`'s event monitor. ```swift // shouldAutomaticallyResume defaults to nil, obeying the Session's setting, which // defaults to true. let request = <session>.request(<urlRequest>, shouldAutomaticallyResume: true) .adapt(using: <adapter>) .retry(using: <retrier>) .interceptor(<interceptor>) .eventMonitor(<monitor>) // request is inert until resumed or a response handler (when automatic resume is enabled) // is added. let response = await request.serializingDecoding(<Type>.self).response ``` ### Implementation Details :construction: Actual changes were rather minimal for the impact these features have. 1. Simple stored interceptor and monitor are now stored in the mutable state and new instance methods have been added to provide those values. 2. Internally, the previous `perform` method has been split between eager and lazy variants, and a new `RequestDelegate` method has been added to start the request when needed (upon resume). 3. Interceptors and EventMonitors are now composed `Session`-first, to guarantee that `Request`s can override `Session` interceptor behavior. ### Testing Details :mag: Tests against very specific `Request` lifetime timing were updated to use an `eager` `Session`, to replicate the previous behavior. However, these tests are almost always inherently racy, which made them flaky in CI, so this sort of breaking behavioral change is more of a bug fix. Users could never really rely on these event orderings before, as `Request` start and the events themselves would race. Additional tests added to cover the new APIs, and some tests have been converted to Swift Testing for performance and ergonomics. Additionally, the test target deployment targets have been bumped again, as the testing frameworks technically only deploy back to macOS 14, etc. | 8 个月前 |
| Lazy Requests, per-Request Features (#3996) ### Issue Link :link: Closes #3992, other feature requests. ### Goals :soccer: This PR includes four major new features: 1. By default, all `Request` set up is now fully lazy and does not start until the instance is resumed, whether automatically or manually. Virtually all users should be unimpacted by this change, aside from seeing fewer race conditions. For those that do see issues, the previous behavior can be restored by passing `requestSetup: .eager` to the `Session.init`. 2. Speaking of `resume()`, automatic resume is now controllable on a per-`Request` basis using the `shouldAutomaticallyResumeParameter`. By default this is `nil` an obeys the `Session` setting. 3. You can now add a `RequestAdapter`, `RequestRetrier`, or `RequestInterceptor` after `Request.init`, like any other chained Alamofire API. This is what necessitated the lazy start change, as adapters added in this manner are racy with eager `Request`s and may miss the appropriate lifetime events. 4. In addition to the interceptors, you can now add a per-`Request` `EventMonitor` that is composed after the `Session`'s event monitor. ```swift // shouldAutomaticallyResume defaults to nil, obeying the Session's setting, which // defaults to true. let request = <session>.request(<urlRequest>, shouldAutomaticallyResume: true) .adapt(using: <adapter>) .retry(using: <retrier>) .interceptor(<interceptor>) .eventMonitor(<monitor>) // request is inert until resumed or a response handler (when automatic resume is enabled) // is added. let response = await request.serializingDecoding(<Type>.self).response ``` ### Implementation Details :construction: Actual changes were rather minimal for the impact these features have. 1. Simple stored interceptor and monitor are now stored in the mutable state and new instance methods have been added to provide those values. 2. Internally, the previous `perform` method has been split between eager and lazy variants, and a new `RequestDelegate` method has been added to start the request when needed (upon resume). 3. Interceptors and EventMonitors are now composed `Session`-first, to guarantee that `Request`s can override `Session` interceptor behavior. ### Testing Details :mag: Tests against very specific `Request` lifetime timing were updated to use an `eager` `Session`, to replicate the previous behavior. However, these tests are almost always inherently racy, which made them flaky in CI, so this sort of breaking behavioral change is more of a bug fix. Users could never really rely on these event orderings before, as `Request` start and the events themselves would race. Additional tests added to cover the new APIs, and some tests have been converted to Swift Testing for performance and ergonomics. Additionally, the test target deployment targets have been bumped again, as the testing frameworks technically only deploy back to macOS 14, etc. | 8 个月前 |
| Update Infrastructure (#4017) ### Goals :soccer: This PR updates actions and dependencies. This PR also fixes two issues: - A rare duplicate metrics crash seen when using `usesClassicLoadingMode = false`. - An extremely rare logic race between the creation of a `StreamOf` and the start of iteration, where values could be lost. | 4 个月前 |
| Prepare 5.11 (#3997) This PR prepares the 5.11 release. | 8 个月前 |