{"payload":{"feedbackUrl":"https://github.com/orgs/community/discussions/53140","repo":{"id":630567597,"defaultBranch":"main","name":"swift-openapi-urlsession","ownerLogin":"apple","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2023-04-20T16:53:01.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/10639145?v=4","public":true,"private":false,"isOrgOwned":true},"refInfo":{"name":"","listCacheKey":"v0:1705411055.0","currentOid":""},"activityList":{"items":[{"before":"f81270ea80d9fba9d33f2ac147a79765302124c0","after":"6b915d82591735d890cbc94f9ac9e2784737f9de","ref":"refs/heads/main","pushedAt":"2024-04-16T14:38:10.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Remove unnecessary self keyword (#48)\n\n### Motivation\r\n\r\n- We want to avoid redundant code by removing unnecessary self keywords\r\n\r\n### Modifications\r\n\r\n- Removed unnecessary self keywords\r\n\r\n### Result\r\n\r\n- No errors, `./scripts/soundness.sh` also passed.\r\n- Follow [this\r\nreference](https://github.com/apple/swift-openapi-urlsession/blob/main/CONTRIBUTING.md#run-scriptssoundnesssh)","shortMessageHtmlLink":"Remove unnecessary self keyword (#48)"}},{"before":"6efbfda5276bbbc8b4fec5d744f0ecd8c784eb47","after":"f81270ea80d9fba9d33f2ac147a79765302124c0","ref":"refs/heads/main","pushedAt":"2024-03-11T13:39:20.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"czechboy0","name":"Honza Dvorsky","path":"/czechboy0","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/2182121?s=80&v=4"},"commit":{"message":"Update CI to use release 5.10 image (#47)","shortMessageHtmlLink":"Update CI to use release 5.10 image (#47)"}},{"before":"3d1f6e7b403fc9ae892fe5497809a7d3427e67b3","after":"6efbfda5276bbbc8b4fec5d744f0ecd8c784eb47","ref":"refs/heads/main","pushedAt":"2024-01-16T09:53:45.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Set OutputStream.delegate to nil in HTTPBodyOutputStreamBridge.deinit (#46)\n\n### Motivation\r\n\r\nWhen running the cancellation tests in a loop, very occasionally there\r\nwould be a crash with the following backtrace:\r\n\r\n```\r\n#0\t0x000000018aa008d4 in objc_opt_respondsToSelector ()\r\n#1\t0x000000018aea3410 in _outputStreamCallbackFunc ()\r\n#2\t0x000000018aea3310 in _signalEventSync ()\r\n#3\t0x000000018aeecdb0 in ___signalEventQueue_block_invoke ()\r\n#4\t0x000000018abe6cb8 in _dispatch_call_block_and_release ()\r\n#5\t0x000000018abe8910 in _dispatch_client_callout ()\r\n#6\t0x000000018abefea4 in _dispatch_lane_serial_drain ()\r\n#7\t0x000000018abf0a08 in _dispatch_lane_invoke ()\r\n#8\t0x000000018abfb61c in _dispatch_root_queue_drain_deferred_wlh ()\r\n#9\t0x000000018abfae90 in _dispatch_workloop_worker_thread ()\r\n#10\t0x000000018ad96114 in _pthread_wqthread ()\r\n```\r\n\r\nThis seems to indicate that the output stream is trying to access its\r\ndelegate. However, when running with debug logging enabled I can see\r\nthat the delegate has already been deinitialized.\r\n\r\nThis is likely a result of the delegate itself owning the stream and\r\nsetting the stream delegate to `self`, which IIUC is an established\r\npattern. This presents a race in teardown.\r\n\r\n### Modifications\r\n\r\nThis patch sets the output stream delegate to `nil` in the delegate\r\n`deinit`.\r\n\r\n### Result\r\n\r\nNo attempts to call the delegate will happen after it is has been\r\ndeinitailzed.\r\n\r\n### Test Plan\r\n\r\nWith this patch, the failing test passes when run an order of magnitude\r\nmore times than were required to reliably reproduce the crash without\r\nthe patch.","shortMessageHtmlLink":"Set OutputStream.delegate to nil in HTTPBodyOutputStreamBridge.deinit ("}},{"before":"aac0a8273fa1186641e0b336da3f1be01aa6a0eb","after":"3d1f6e7b403fc9ae892fe5497809a7d3427e67b3","ref":"refs/heads/main","pushedAt":"2024-01-16T08:43:19.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Tolerate both CancellationError and URLError in CancellationTests (#45)\n\n### Motivation\r\n\r\nWhen cancelling a Swift concurrency task during a streaming request then\r\nthe error returned might be `URLError` with `.cancelled` code or\r\n`CancellationError`. The tests tried to be smart and expect just one of\r\nthese depending on which stage of the request we were at, but there are\r\nstill some races, and this test fails very rarely because a\r\n`CancellationError` was thrown instead of a `URLError`.\r\n\r\n### Modifications\r\n\r\nThis patch updates the test to tolerate both kinds of error at this\r\nstage of the request.\r\n\r\n### Result\r\n\r\nThe test will pass if the error is either `URLError` with `.cancelled`\r\nor `CancellationError`, and continue to fail if there is any other kind\r\nof error or no error.\r\n\r\n### Test Plan\r\n\r\nExisting tests, which failed when run repeatedly for 1k runs, now pass\r\nwhen run for 10k runs.","shortMessageHtmlLink":"Tolerate both CancellationError and URLError in CancellationTests (#45)"}},{"before":"144464e8f55548dd6ec90a53532fc00f8a62e9d5","after":"aac0a8273fa1186641e0b336da3f1be01aa6a0eb","ref":"refs/heads/main","pushedAt":"2023-12-11T17:21:19.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"More checks for task cancellation and tests (#44)\n\n### Motivation\r\n\r\nIn our fallback, buffered implementation, we did not use a task\r\ncancellation handler so were not proactively cancelling the URLSession\r\ntask when the Swift concurrency task was cancelled. Additionally, while\r\nwe _did_ have a task cancellation handler in the streaming\r\nimplementation, so the URLSession task would be cancelled, we were not\r\nactively checking for task cancellation as often as we could.\r\n\r\n### Modifications\r\n\r\n- Added more cooperative task cancellation.\r\n- Added tests for both implementations that when the parent task for the\r\nclient request is cancelled that we get something sensible. Note that in\r\nsome cases, the request will succeed. In the cases where the request\r\nfails, it will surface as a `ClientError` to the user where the\r\n`underlyingError` is either `Swift.CancellationError` or `URLError` with\r\n`code == .cancelled`.\r\n\r\n### Result\r\n\r\nMore cooperative task and URLSession task cancellation and more thorough\r\ntests.\r\n\r\n### Test Plan\r\n\r\nAdded unit tests.","shortMessageHtmlLink":"More checks for task cancellation and tests (#44)"}},{"before":"d0dafbf21c651483d03049177d60b63826c4128a","after":"144464e8f55548dd6ec90a53532fc00f8a62e9d5","ref":"refs/heads/main","pushedAt":"2023-12-11T13:03:30.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Prep 1.0 (#43)\n\n### Motivation\r\n\r\nReady the docs for 1.0.\r\n\r\n### Modifications\r\n\r\nUpdated README.md and documentation, updated the runtime dependency.\r\n\r\n### Result\r\n\r\nReady for 1.0.\r\n\r\n### Test Plan\r\n\r\nReviewed locally.","shortMessageHtmlLink":"Prep 1.0 (#43)"}},{"before":"e8c1733d0d9a0fed2458ed813bbaae597f2e20d4","after":"d0dafbf21c651483d03049177d60b63826c4128a","ref":"refs/heads/main","pushedAt":"2023-12-11T10:29:14.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Add issue template, redirecting to swift-openapi-generator issues","shortMessageHtmlLink":"Add issue template, redirecting to swift-openapi-generator issues"}},{"before":"4290b2ceb83230df02bec19fe945823dbac12f28","after":"e8c1733d0d9a0fed2458ed813bbaae597f2e20d4","ref":"refs/heads/main","pushedAt":"2023-12-02T20:48:38.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"czechboy0","name":"Honza Dvorsky","path":"/czechboy0","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/2182121?s=80&v=4"},"commit":{"message":"fixes internal typo in source parameter (#42)","shortMessageHtmlLink":"fixes internal typo in source parameter (#42)"}},{"before":"4baf5fa6008c944adba5878d6f78af56f3433f5b","after":"4290b2ceb83230df02bec19fe945823dbac12f28","ref":"refs/heads/main","pushedAt":"2023-12-01T12:35:58.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"czechboy0","name":"Honza Dvorsky","path":"/czechboy0","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/2182121?s=80&v=4"},"commit":{"message":"Explicit dependency on HTTPTypes (#39)\n\n### Motivation\r\n\r\nRecent SwiftPM versions seem to be a bit stricter about using (i.e.,\r\n`import ...`) transitive dependencies without explicitly declaring them\r\nas direct dependencies.\r\n\r\n### Modifications\r\n\r\nExplicitly depend on the HTTPTypes module from swift-http-types.\r\n\r\n### Result\r\n\r\nMore explicitly declare the dependency graph.\r\n\r\n### Test Plan\r\n\r\nAll tests pass.","shortMessageHtmlLink":"Explicit dependency on HTTPTypes (#39)"}},{"before":"c703e84d21bd6e5aaafc6c4c5deb88899cfa5a12","after":"4baf5fa6008c944adba5878d6f78af56f3433f5b","ref":"refs/heads/main","pushedAt":"2023-12-01T09:03:49.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"czechboy0","name":"Honza Dvorsky","path":"/czechboy0","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/2182121?s=80&v=4"},"commit":{"message":"Remove no-longer-needed `@preconcurrency`s (#35)\n\nSee https://github.com/apple/swift-openapi-generator/pull/396.\r\n\r\nCo-authored-by: Honza Dvorsky ","shortMessageHtmlLink":"Remove no-longer-needed @preconcurrencys (#35)"}},{"before":"d16dc2f9cd73127d1dff50b2e81ae6132202b883","after":"c703e84d21bd6e5aaafc6c4c5deb88899cfa5a12","ref":"refs/heads/main","pushedAt":"2023-11-30T20:21:21.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Add Docker Compose file for Swift 5.9.0 (#40)","shortMessageHtmlLink":"Add Docker Compose file for Swift 5.9.0 (#40)"}},{"before":"d038c8965f4a9d436da905a6bca99c3121654288","after":"d16dc2f9cd73127d1dff50b2e81ae6132202b883","ref":"refs/heads/main","pushedAt":"2023-11-30T09:23:47.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Add visionOS platform support (#38)\n\n### Motivation\r\n\r\nWhile this isn't technically necessary, as all versions of a platform\r\nnot explicitly mentioned are assumed to be supported, it's better to be\r\nexplicit here.\r\n\r\n### Modifications\r\n\r\nAdd `visionOS(.v1)` to the list of supported platforms.\r\n\r\n### Result\r\n\r\nClearer support matrix.\r\n\r\n### Test Plan\r\n\r\nN/A, this is basically just a documentation change.","shortMessageHtmlLink":"Add visionOS platform support (#38)"}},{"before":"5e704f112ff58ef45b35ab8a77efe3ff463f1f83","after":"d038c8965f4a9d436da905a6bca99c3121654288","ref":"refs/heads/main","pushedAt":"2023-11-28T09:40:35.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"czechboy0","name":"Honza Dvorsky","path":"/czechboy0","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/2182121?s=80&v=4"},"commit":{"message":"Bump to 1.0.0-alpha.1 (#36)\n\nBump to 1.0.0-alpha.1\n\n### Motivation\n\nPrepare for 1.0.0-alpha.1.\n\n### Modifications\n\n- Updated runtime dependency.\n- Updated docs.\n\n### Result\n\nReady to tag 1.0.0-alpha.1.\n\n### Test Plan\n\nAll tests pass.\n\n\nReviewed by: simonjbeaumont\n\nBuilds:\n ✔︎ pull request validation (5.10) - Build finished. \n ✔︎ pull request validation (5.9) - Build finished. \n ✔︎ pull request validation (nightly) - Build finished. \n ✔︎ pull request validation (soundness) - Build finished. \n\nhttps://github.com/apple/swift-openapi-urlsession/pull/36","shortMessageHtmlLink":"Bump to 1.0.0-alpha.1 (#36)"}},{"before":"0e75335103a7ff8bd79ce6b4c81c6cfccef46d09","after":"5e704f112ff58ef45b35ab8a77efe3ff463f1f83","ref":"refs/heads/main","pushedAt":"2023-11-27T16:14:47.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Add missing available annotation to streaming tests (#33)\n\n### Motivation\r\n\r\nThe tests had a missing `@available` annotation which meant that they\r\ndidn't build iOS (annoyingly, when building for macOS, these things are\r\nnot checked so things were building fine locally).\r\n\r\n### Modifications\r\n\r\nAdd missing available annotation to streaming tests.\r\n\r\n### Result\r\n\r\nBuilds for iOS again.\r\n\r\n### Test Plan\r\n\r\nLocal testing, selecting generic iOS destination in Xcode. This failed\r\nbefore this patch, and succeeds with it.\r\n\r\nSigned-off-by: Si Beaumont ","shortMessageHtmlLink":"Add missing available annotation to streaming tests (#33)"}},{"before":"0b99785e04552ece226c8823133ecf6d8889c442","after":"0e75335103a7ff8bd79ce6b4c81c6cfccef46d09","ref":"refs/heads/main","pushedAt":"2023-11-27T16:10:21.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Remove AsyncStream.makeStream backports now we support only Swift 5.9+ (#34)\n\n### Motivation\r\n\r\nWe had some code in an `#if swift(<5.9)` block, which can now be removed\r\nbecause we only support Swift 5.9 and newer.\r\n\r\n### Modifications\r\n\r\nRemove code required to support Swift 5.8.\r\n\r\n### Result\r\n\r\nRemoved dead code.\r\n\r\n### Test Plan\r\n\r\nTests pass.","shortMessageHtmlLink":"Remove AsyncStream.makeStream backports now we support only Swift 5.9+ ("}},{"before":"fa75a83615ae8eb382e82a0d6b8ff6fdb7fb9644","after":"0b99785e04552ece226c8823133ecf6d8889c442","ref":"refs/heads/main","pushedAt":"2023-11-27T15:18:43.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"czechboy0","name":"Honza Dvorsky","path":"/czechboy0","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/2182121?s=80&v=4"},"commit":{"message":"Move to Swift 5.9 as the minimum version (#32)\n\n### Motivation\r\n\r\nPart of addressing\r\nhttps://github.com/apple/swift-openapi-generator/issues/75 and\r\nhttps://github.com/apple/swift-openapi-generator/issues/119.\r\n\r\n### Modifications\r\n\r\nBumped Swift tools version to 5.9 and made the `ExistentialAny` build\r\nsetting unconditional.\r\n\r\n### Result\r\n\r\nBuilding the package requires 5.9 now.\r\n\r\n### Test Plan\r\n\r\nRan tests, all passed when using a Swift 5.9 toolchain.","shortMessageHtmlLink":"Move to Swift 5.9 as the minimum version (#32)"}},{"before":"7d338462339cb1e91937bf4df727f1353d1e6fb3","after":"fa75a83615ae8eb382e82a0d6b8ff6fdb7fb9644","ref":"refs/heads/main","pushedAt":"2023-11-27T15:05:21.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"czechboy0","name":"Honza Dvorsky","path":"/czechboy0","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/2182121?s=80&v=4"},"commit":{"message":"Prep for 1.0 alpha, adapted to runtime changes in main (#31)\n\n### Motivation\r\n\r\nOn main, the HTTPBody length type changed from Int to Int64.\r\n\r\n### Modifications\r\n\r\nAdapted the transport with this change.\r\n\r\n### Result\r\n\r\nRepo builds again when using the latest runtime.\r\n\r\n### Test Plan\r\n\r\nAdapted tests.","shortMessageHtmlLink":"Prep for 1.0 alpha, adapted to runtime changes in main (#31)"}},{"before":"9229842c63e9fc3bbd32c661d8274b4d9d8715f1","after":"7d338462339cb1e91937bf4df727f1353d1e6fb3","ref":"refs/heads/main","pushedAt":"2023-11-24T15:48:56.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"czechboy0","name":"Honza Dvorsky","path":"/czechboy0","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/2182121?s=80&v=4"},"commit":{"message":"Improve inlining (#30)","shortMessageHtmlLink":"Improve inlining (#30)"}},{"before":"8c842856a40d24f29756fc02aa59c8c11b040ad3","after":"9229842c63e9fc3bbd32c661d8274b4d9d8715f1","ref":"refs/heads/main","pushedAt":"2023-11-23T20:34:57.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Replace AsyncBackpressuredStream with updated implementation (#29)\n\n### Motivation\r\n\r\nAs a follow up to #27, we noted it would be good to align on the latest\r\ndraft implementation of SE-0406 (AsyncStream with backpressure) to both\r\npickup the latest improvements in performance and correctness, and to\r\nminimise the churn if/when this lands in the standard library or\r\nstandalone package.\r\n\r\n### Modifications\r\n\r\nIn order to simplify reviewing the following modifications have been\r\nmade in independent commits:\r\n\r\n* `Add updated SE-0406 implementation as BufferedStream, incl. tests`:\r\nSkim over this—it's vendored in wholesale.\r\n* `Port the custom watermark support to BufferedStream`: Skim over\r\nthis—it's a 1:1 port of the logic that was added to\r\n`AsyncBackpressuredStream`.\r\n* `Switch from AsyncBackpressuredStream to BufferedStream in delegate`:\r\nReview this—it's a minimal change.\r\n* `Remove AsyncBackpressuredStream and its vendored locks`: Skim over\r\nthis—it's removing the old implementation.\r\n\r\n### Result\r\n\r\nNo functional change, but the internal async sequence we're using should\r\nbe more robust, performant, and more likely to match a future standard\r\nlibrary type.\r\n\r\n### Test Plan\r\n\r\n- The new vendored `BufferedStream` actually comes with a much greater\r\nnumber of vendored tests than the previous revision.\r\n- Also ported the tests from this repo for the custom watermark logic.\r\n- All our URLSessionTransport-specific tests continue to pass.\r\n\r\n---------\r\n\r\nSigned-off-by: Si Beaumont ","shortMessageHtmlLink":"Replace AsyncBackpressuredStream with updated implementation (#29)"}},{"before":"aee2c63eaebe02185bd864631367b75da028af30","after":"8c842856a40d24f29756fc02aa59c8c11b040ad3","ref":"refs/heads/main","pushedAt":"2023-11-23T14:07:31.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Avoid double continuation resume in URLSession delegate in corner case (#28)\n\n### Motivation\r\n\r\nIf the request completes with error after the response has already been\r\nreceived we can potentially resume a continuation twice. This was shown\r\nby running some of the tests in long loop.\r\n\r\n### Modifications\r\n\r\n- Add a shorter test that more reliably reproduced the issue. \r\n- Add the fix: to set the continuation to `nil` after resuming it, while\r\nstill holding the lock.\r\n\r\n### Result\r\n\r\n- Removed a source of a potential runtime crash.\r\n\r\n### Test Plan\r\n\r\n- The newly added test, which reliably failed, now reliably passes.","shortMessageHtmlLink":"Avoid double continuation resume in URLSession delegate in corner case ("}},{"before":"b1d5cfaf6e59289406575f731d2030711f895559","after":"aee2c63eaebe02185bd864631367b75da028af30","ref":"refs/heads/main","pushedAt":"2023-11-23T14:05:40.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Improve debug logging and add tests that it is not evaluated when disabled (#26)\n\n### Motivation\r\n\r\nThe transport code has some debug logging, which is compile-time omitted\r\nin release builds, and only enabled in tests.\r\n\r\nA number of tests produce an enormous amount of output (e.g. the\r\nstreaming tests that pull 10GB through 10MB buffers), which are unwieldy\r\nin CI and locally.\r\n\r\nAdditionally, we found that the logging produced by these tests had\r\ninterleaved output, both because of the mixed use of `print` and `debug`\r\nin tests and the lack of locking between multiple threads\r\n\r\nFinally, even when running in debug mode with debug logging _disabled_,\r\nthe function arguments to the `debug` function were still evaluated\r\nunnecessarily.\r\n\r\n### Modifications\r\n\r\n- Update the `debug` function to log to standard error (cf. standard\r\nout).\r\n- Pass an autoclosure as argument to `debug` so that it is only\r\nevaluated when logging is enabled.\r\n- Add a lock around the use of `FileHandle.standardError`.\r\n- Replace all stray uses of `print` in tests with `debug`.\r\n\r\n### Result\r\n\r\n- No debug logging should appear in tests by default (you can enable\r\nthem locally when reproducing failures).\r\n- When enabled, log lines should not be all jumbled up.\r\n- When disabled, no string interpolation is performed.\r\n\r\n### Test Plan\r\n\r\n- Added tests that check that the log message is not interpolated when\r\ndisabled.","shortMessageHtmlLink":"Improve debug logging and add tests that it is not evaluated when dis…"}},{"before":"8464a53a3b9b53ae460df4a17c69e5831142bd97","after":"b1d5cfaf6e59289406575f731d2030711f895559","ref":"refs/heads/main","pushedAt":"2023-11-23T14:05:25.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Add missing transition AsyncBackpressuredStream state machine (#27)\n\n### Motivation\r\n\r\nSome of our bidirectional streaming tests were failing intermittently.\r\nWhen they failed, the symptom was that more bytes were received by the\r\nend user (in the test) than the server sent.\r\n\r\nFor example, in the test\r\n`testStreamingDownload_1kChunk_10kChunks_100BDownloadWatermark`, we\r\nexpect:\r\n\r\n- ✅ The server sends 10,000 chunks of 1024 bytes:\r\n ```console\r\n ❯ cat repro.txt | grep -i \"server sent body chunk\" | head -3\r\n Server sent body chunk 1/10000 of 1024\r\n Server sent body chunk 2/10000 of 1024\r\n Server sent body chunk 3/10000 of 1024\r\n\r\n ❯ cat repro.txt | grep -i \"server sent body chunk\" | wc -l\r\n 10000\r\n ```\r\n\r\n- ✅ URLSession `didReceive data` callback called a non-deterministic\r\nnumber of times because it may re-chunk the bytes internally, but the\r\ntotal number of bytes through the delegate calls is 10,240,000:\r\n ```console\r\n ❯ cat repro.txt | grep \"didReceive data\" | head -3\r\n Task delegate: didReceive data (numBytes: 1024)\r\n Task delegate: didReceive data (numBytes: 2048)\r\n Task delegate: didReceive data (numBytes: 1024)\r\n\r\n❯ cat repro.txt | grep \"didReceive data\" | awk '{ print $6 }' | tr -d \\)\r\n| paste -sd+ | bc -l\r\n 10240000\r\n ```\r\n\r\n- ❌ The response body chunks emitted by the `AsyncBackpressuredStream`\r\nto the user (in the test) match 1:1 those received by the delegate\r\ncallback:\r\n ```console\r\n❯ cat repro.txt | grep \"Client received some response body bytes\" | head\r\n-3\r\n Client received some response body bytes (numBytes: 1024)\r\n Client received some response body bytes (numBytes: 2048)\r\n Client received some response body bytes (numBytes: 1024)\r\n\r\n❯ cat repro.txt | grep \"didReceive data\" | awk '{ print $6 }' | tr -d \\)\r\n| wc -l\r\n 333\r\n\r\n❯ cat repro.txt | grep \"Client received some response body bytes\" | wc\r\n-l\r\n 334\r\n ```\r\n\r\n- ❌ The total number of bytes emitted by the `AsyncBackpressuredStream`\r\nto the user (in the test) match is 10,240,000 and it can then\r\nreconstruct 10,000 chunks of 1024 to match what the server sent:\r\n ```console\r\n❯ cat repro.txt | grep \"Client received some response body bytes\" | awk\r\n'{ print $8 }' | tr -d \\) | paste -sd+ | bc -l\r\n 10280960\r\n\r\n ❯ cat repro.txt | grep \"Client reconstructing\" | tail -3\r\n Client reconstructing and verifying chunk 10038/10000\r\n Client reconstructing and verifying chunk 10039/10000\r\n Client reconstructing and verifying chunk 10040/10000\r\n ```\r\n\r\nSo we see that there was one more element emitted from the\r\n`AsyncBackpressuredStream` than the delegate callback wrote, which meant\r\nthe test saw an additional 40960 bytes than it expected to and\r\nconsequently reconstructed an additional 40 chunks of size 1024 over\r\nwhat the server sent.\r\n\r\nWe can see that the `AsyncBackpressuredStream` duplicates an element\r\nalong the way, of 40960 bytes,\r\n\r\n```diff\r\n❯ diff -u --label=received-in-delegate-callback <(cat repro.txt | grep \"didReceive data\" | awk '{ print $6 }' | tr -d \\)) --label=received-through-async-sequence <(cat repro.txt | grep \"Client received some response body bytes\" | awk '{ print $8 }' | tr -d \\))\r\n--- received-in-delegate-callback\r\n+++ received-through-async-sequence\r\n@@ -305,6 +305,7 @@\r\n 2048\r\n 1024\r\n 40960\r\n+40960\r\n 24576\r\n 2048\r\n 34841\r\n ```\r\n\r\nAfter some investigation, it turned out there was a missing transition in the state machine that underlies the `AsyncBackpressuredStream`. When calling `suspendNext` when there are buffered elements, but we are above the watermark, we popped the first item from the buffer and returned it _without_ updating the state (with the new buffer, without the popped element).\r\n\r\nConsequently, this meant that the _next_ call to `next()` would return the same element again. \r\n\r\n### Modifications\r\n\r\nThe following modifications have been made in separate commits to aid review:\r\n- Add debug logging to the state machine functions, logging the old state, event, new state, and resulting action.\r\n- Add two tests which reproduce this error.\r\n- Add the missing state transition (which causes the newly added tests to reliably pass).\r\n\r\n### Result\r\n\r\nDuplicate elements are no longer emitted from the response body.\r\n\r\n### Test Plan\r\n\r\n- Unit tests were added that fail without the fix, that now pass reliably.\r\n\r\n### Additional notes\r\n\r\nThe implementation we are using for `AsyncBackpressuredStream` was taken from an early draft of SE-0406. We should probably move to using something closer matching that of the current PR to the Swift tree, or that used by swift-grpc, which has also adopted this code and cleaned it up to remove the dependencies on the standard library internals. Additionally, that implementation does not have this missing state transition and also adds an intermediate state to the state machine to avoid unintended copy-on-write.","shortMessageHtmlLink":"Add missing transition AsyncBackpressuredStream state machine (#27)"}},{"before":"686df727d1865ce6d73e7bd8d89e6c2498f6e5b8","after":"8464a53a3b9b53ae460df4a17c69e5831142bd97","ref":"refs/heads/main","pushedAt":"2023-11-17T17:59:16.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Use APIs available on older macOS in tests (#25)\n\n### Motivation\r\n\r\nThe tests fail to compile on anything older than macOS 13, because they\r\nuse a number of APIs only available in macOS 13+:\r\n\r\n- `Duration`\r\n- `Task.sleep(for:)`\r\n- `DispatchQueue.asyncAndWait` (closure variant)\r\n\r\n### Modifications\r\n\r\nUse the following APIs instead:\r\n\r\n- `NIO.TimeInterval` (we have NIO dependency in tests already).\r\n- `Task.sleep(nanoseconds:)`\r\n- `DispatchQueue.asyncAndWait(execute:)`\r\n\r\n### Result\r\n\r\nTests can be built on older platforms.","shortMessageHtmlLink":"Use APIs available on older macOS in tests (#25)"}},{"before":"70b63efd9c53207e9f7d93e262513a21ee285046","after":"686df727d1865ce6d73e7bd8d89e6c2498f6e5b8","ref":"refs/heads/main","pushedAt":"2023-11-17T11:07:09.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"simonjbeaumont","name":"Si Beaumont","path":"/simonjbeaumont","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1125539?s=80&v=4"},"commit":{"message":"Add support for streaming on recent Darwin platforms (#24)\n\n### Motivation\r\n\r\nRecently, the `ClientTransport` protocol was updated to be in terms of\r\n`HTTPBody`, which is an `AsyncSequence>`. Until now,\r\nthe URLSession transport has buffered the request and response bodies in\r\nmemory. This PR seeks to bring streaming support to recent Darwin\r\nplatforms.\r\n\r\n### Modifications\r\n\r\nOn new enough Darwin platforms[^1], use URLSession delegate to perform\r\nbidirectional streaming with backpressure. Request body backpressure is\r\nprovided by the use of `StreamDelegate` with a bound stream pair.\r\nResponse body backpressure is provided by the use of\r\n`AsyncBackpressuredStream` which allows for a high and low watermark to\r\nsuspend and resume the URLSession task.\r\n\r\n[^1]: macOS 12, iOS 15, tvOS 15, watchOS 8\r\n\r\nIn more detail:\r\n\r\n- Vendor internal `AsyncBackpressuredStream` implementation from\r\nSE-0406.\r\n- Add `HTTPBodyOutputStreamBridge` which provides the\r\n`OutputStreamDelegate` required to bridge the `AsyncSequence`-based\r\n`HTTPBody` to an `OutputStream`.\r\n- Add `BidirectionalStreamingURLSessionDelegate` which makes use of\r\n`HTTPBodyOutputStreamBridge` for streaming request bodies and also uses\r\nthe delegate callbacks to bridge the response body to `HTTPBody`.\r\n- Add `URLSession.bidirectionalStreamingRequest(...) async throws`,\r\nwhich provides a high-level URLSession-like API for setting up the\r\nappropriate URLSession task and delegate.\r\n- Add `URLSession.bufferedRequest(...) async throws` to provide a\r\nsimilar interfaces on platforms that don't support the streaming APIs on\r\nwhich we depend.\r\n- Add internal `enum URLSessionTransport.Configuration.Implementation`\r\nto control whether to use buffered or streaming implementation.\r\n- Detect appropriate implementation depending on the platform.\r\n\r\n### Result\r\n\r\n- On new enough Darwin platforms[^1], streaming will be used.\r\n\r\n### Test Plan\r\n\r\n- Add a set of tests that run with both buffered and streaming\r\nimplementation on platforms that support streaming.\r\n- Add a set of tests that only run on platforms that support streaming,\r\nto test request flows only possible with streaming.\r\n\r\nHowever, it's worth noting that our CI only runs on Linux, so we won't\r\nbe testing the majority of this new feature in CI.","shortMessageHtmlLink":"Add support for streaming on recent Darwin platforms (#24)"}},{"before":"22ec9a69fcf834e508d42efea1d444f682a61613","after":"70b63efd9c53207e9f7d93e262513a21ee285046","ref":"refs/heads/main","pushedAt":"2023-11-16T08:39:55.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"czechboy0","name":"Honza Dvorsky","path":"/czechboy0","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/2182121?s=80&v=4"},"commit":{"message":"Add README badges (#23)\n\n### Motivation\r\n\r\nSurface the Swift version and platform support status from Swift Package\r\nIndex.\r\n\r\n### Modifications\r\n\r\nAdded badges, plus a quick link to the docc docs, to the top of the\r\nREADME.\r\n\r\n### Result\r\n\r\nEasier to quickly see our support matrix, plus the quick link to docs.\r\n\r\n### Test Plan\r\n\r\nPreviewed locally.","shortMessageHtmlLink":"Add README badges (#23)"}},{"before":"c1c96c76c60f24d0da9ec485e1a6b3b775f1fd2e","after":"22ec9a69fcf834e508d42efea1d444f682a61613","ref":"refs/heads/main","pushedAt":"2023-11-01T16:49:30.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"czechboy0","name":"Honza Dvorsky","path":"/czechboy0","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/2182121?s=80&v=4"},"commit":{"message":"Disable \"respectsExistingLineBreaks\" in .swift-format for more consistent styling (#20)\n\n### Motivation\r\n\r\n- Relates to\r\n[#230](https://github.com/apple/swift-openapi-generator/issues/230)\r\n\r\n### Modifications\r\n\r\n- Disable respectsExistingLineBreaks .swift-format rule and address\r\nchanges requested\r\n\r\n### Result\r\n\r\n- One of the .swift-format rules will be disabled\r\n\r\n### Test Plan\r\n\r\n- Run Tests\r\n\r\nCo-authored-by: Honza Dvorsky ","shortMessageHtmlLink":"Disable \"respectsExistingLineBreaks\" in .swift-format for more consis…"}},{"before":"cd42d96ea181f40a411de1d7025a6643c8026e82","after":null,"ref":"refs/heads/czechboy0-patch-1","pushedAt":"2023-11-01T16:48:16.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"czechboy0","name":"Honza Dvorsky","path":"/czechboy0","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/2182121?s=80&v=4"}},{"before":"f2b6460da057a2b81904eec592b0f369a80e0413","after":"c1c96c76c60f24d0da9ec485e1a6b3b775f1fd2e","ref":"refs/heads/main","pushedAt":"2023-11-01T16:48:15.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"czechboy0","name":"Honza Dvorsky","path":"/czechboy0","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/2182121?s=80&v=4"},"commit":{"message":"Disable warnings as errors in nightlies (#21)\n\nSame as in the other repos: disable warnings as errors in nightlies.","shortMessageHtmlLink":"Disable warnings as errors in nightlies (#21)"}},{"before":null,"after":"cd42d96ea181f40a411de1d7025a6643c8026e82","ref":"refs/heads/czechboy0-patch-1","pushedAt":"2023-11-01T15:38:59.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"czechboy0","name":"Honza Dvorsky","path":"/czechboy0","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/2182121?s=80&v=4"},"commit":{"message":"Disable warnings as errors in nightlies","shortMessageHtmlLink":"Disable warnings as errors in nightlies"}},{"before":"799082683ca264732daf68db24f83aed00c48eab","after":"f2b6460da057a2b81904eec592b0f369a80e0413","ref":"refs/heads/main","pushedAt":"2023-10-25T10:56:23.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"czechboy0","name":"Honza Dvorsky","path":"/czechboy0","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/2182121?s=80&v=4"},"commit":{"message":"Add a soundness --fix flag (#19)\n\nAdd a soundness --fix flag\n\n### Motivation\n\nWhen running `./scripts/soundness.sh` produces swift-format warnings, we ask adopters to manually copy/paste a call to swift format to fix the warnings up. This is tedious and unnecessary.\n\n### Modifications\n\nAdd a `--fix` option on the `soundness.sh` script to actually apply the fixes as well, avoiding the need to copy/paste long commands.\n\n### Result\n\nEasier fixing up of formatting warnings.\n\n### Test Plan\n\nManually tested the workflow locally.\n\n\nReviewed by: glbrntt\n\nBuilds:\n ✔︎ pull request validation (5.10) - Build finished. \n ✔︎ pull request validation (5.8) - Build finished. \n ✔︎ pull request validation (5.9) - Build finished. \n ✔︎ pull request validation (nightly) - Build finished. \n ✔︎ pull request validation (soundness) - Build finished. \n\nhttps://github.com/apple/swift-openapi-urlsession/pull/19","shortMessageHtmlLink":"Add a soundness --fix flag (#19)"}}],"hasNextPage":true,"hasPreviousPage":false,"activityType":"all","actor":null,"timePeriod":"all","sort":"DESC","perPage":30,"cursor":"djE6ks8AAAAEMh-BwgA","startCursor":null,"endCursor":null}},"title":"Activity · apple/swift-openapi-urlsession"}