-
Notifications
You must be signed in to change notification settings - Fork 59
[Repo Assist] feat: add CancellationToken support to OpenApiClientProvider generated methods (closes #212) #336
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
sergey-tihon
merged 13 commits into
master
from
repo-assist/feat-cancellationtoken-issue-212-2026-03-23-448c1cde90ec7d95
Mar 25, 2026
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
859cd73
feat: add CancellationToken support to OpenApiClientProvider generate…
github-actions[bot] 27ff627
ci: trigger checks
github-actions[bot] bd22135
fix: replace optional struct CancellationToken parameter with method …
Copilot b2f0d80
Add type provider integration tests for CancellationToken-overloaded …
Copilot ee4db30
Fix: CT parameter name uniqueness in CancellationToken overload gener…
Copilot c56be43
Fix CancellationToken parameter ordering and name collision in v3 Ope…
Copilot e77c843
refactor: use UniqueNameGenerator for CT param name uniqueness
github-actions[bot] e1c8879
feat: add optional occupiedNames parameter to UniqueNameGenerator con…
github-actions[bot] 3824c00
refactor: single CallAsync overload + single generated method with op…
github-actions[bot] e06b5b0
cleanup: simplify OperationCompiler and add default/async CT tests
sergey-tihon 16053ea
feat: propagate CancellationToken through ReadAsStringAsync/ReadAsStr…
sergey-tihon 74d62a7
test: add CT coverage for stream, text/plain, async cancellation, and…
sergey-tihon 7686997
fix: async tests
sergey-tihon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| { | ||
| "sdk": { | ||
| "version": "10.0.200", | ||
| "version": "10.0.102", | ||
| "rollForward": "latestMinor" | ||
| } | ||
| } | ||
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
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
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
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
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
138 changes: 138 additions & 0 deletions
138
tests/SwaggerProvider.ProviderTests/v3/Swashbuckle.CancellationToken.Tests.fs
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| module Swashbuckle.v3.CancellationTokenTests | ||
|
|
||
| open Xunit | ||
| open FsUnitTyped | ||
| open System | ||
| open System.Net.Http | ||
| open System.Threading | ||
| open SwaggerProvider | ||
| open Swashbuckle.v3.ReturnControllersTests | ||
|
|
||
| type WebAPIAsync = | ||
| OpenApiClientProvider<"http://localhost:5000/swagger/v1/openapi.json", IgnoreOperationId=true, SsrfProtection=false, PreferAsync=true> | ||
|
|
||
| let apiAsync = | ||
| let handler = new HttpClientHandler(UseCookies = false) | ||
|
|
||
| let client = | ||
| new HttpClient(handler, true, BaseAddress = Uri("http://localhost:5000")) | ||
|
|
||
| WebAPIAsync.Client(client) | ||
|
|
||
| [<Fact>] | ||
| let ``Call generated method without CancellationToken uses default token``() = | ||
| task { | ||
| let! result = api.GetApiReturnBoolean() | ||
| result |> shouldEqual true | ||
| } | ||
|
|
||
| [<Fact>] | ||
| let ``Call generated method with explicit CancellationToken None``() = | ||
| task { | ||
| let! result = api.GetApiReturnBoolean(CancellationToken.None) | ||
| result |> shouldEqual true | ||
| } | ||
|
|
||
| [<Fact>] | ||
| let ``Call generated method with valid CancellationTokenSource token``() = | ||
| task { | ||
| use cts = new CancellationTokenSource() | ||
| let! result = api.GetApiReturnInt32(cts.Token) | ||
| result |> shouldEqual 42 | ||
| } | ||
|
|
||
| [<Fact>] | ||
| let ``Call generated method with already-cancelled token raises OperationCanceledException``() = | ||
| task { | ||
| use cts = new CancellationTokenSource() | ||
| cts.Cancel() | ||
|
|
||
| try | ||
| let! _ = api.GetApiReturnString(cts.Token) | ||
| failwith "Expected OperationCanceledException" | ||
| with | ||
| | :? OperationCanceledException -> () | ||
| | :? System.AggregateException as aex when (aex.InnerException :? OperationCanceledException) -> () | ||
| } | ||
|
|
||
| [<Fact>] | ||
| let ``Call POST generated method with explicit CancellationToken None``() = | ||
| task { | ||
| let! result = api.PostApiReturnString(CancellationToken.None) | ||
| result |> shouldEqual "Hello world" | ||
| } | ||
|
|
||
| [<Fact>] | ||
| let ``Call async generated method without CancellationToken uses default token``() = | ||
| async { | ||
| let! result = apiAsync.GetApiReturnBoolean() | ||
| result |> shouldEqual true | ||
| } | ||
sergey-tihon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| |> Async.StartAsTask | ||
|
|
||
| [<Fact>] | ||
| let ``Call method with required param and explicit CancellationToken``() = | ||
| task { | ||
| use cts = new CancellationTokenSource() | ||
| let! result = api.GetApiUpdateString("Serge", cts.Token) | ||
| result |> shouldEqual "Hello, Serge" | ||
| } | ||
|
|
||
| [<Fact>] | ||
| let ``Call method with optional param and explicit CancellationToken``() = | ||
| task { | ||
| use cts = new CancellationTokenSource() | ||
| let! result = api.GetApiUpdateBool(Some true, cts.Token) | ||
| result |> shouldEqual false | ||
| } | ||
|
|
||
| [<Fact>] | ||
| let ``Call async generated method with explicit CancellationToken``() = | ||
| async { | ||
| use cts = new CancellationTokenSource() | ||
| let! result = apiAsync.GetApiReturnInt32(cts.Token) | ||
| result |> shouldEqual 42 | ||
| } | ||
sergey-tihon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| |> Async.StartAsTask | ||
|
|
||
| [<Fact>] | ||
| let ``Call stream-returning method with explicit CancellationToken``() = | ||
| task { | ||
| use cts = new CancellationTokenSource() | ||
| let! result = api.GetApiReturnFile(cts.Token) | ||
| use reader = new IO.StreamReader(result) | ||
| let! content = reader.ReadToEndAsync() | ||
| content |> shouldEqual "I am totally a file's\ncontent" | ||
| } | ||
|
|
||
| [<Fact>] | ||
| let ``Call text-returning method with explicit CancellationToken``() = | ||
| task { | ||
| use cts = new CancellationTokenSource() | ||
| let! result = api.GetApiReturnPlain(cts.Token) | ||
| result |> shouldEqual "Hello world" | ||
| } | ||
|
|
||
| [<Fact>] | ||
| let ``Call async generated method with already-cancelled token raises OperationCanceledException``() = | ||
| async { | ||
| use cts = new CancellationTokenSource() | ||
| cts.Cancel() | ||
|
|
||
| try | ||
| let! _ = apiAsync.GetApiReturnString(cts.Token) | ||
| failwith "Expected OperationCanceledException" | ||
| with | ||
| | :? OperationCanceledException -> () | ||
| | :? AggregateException as aex when (aex.InnerException :? OperationCanceledException) -> () | ||
| } | ||
| |> Async.StartAsTask | ||
|
|
||
| [<Fact>] | ||
| let ``Call async POST generated method with explicit CancellationToken``() = | ||
| async { | ||
| use cts = new CancellationTokenSource() | ||
| let! result = apiAsync.PostApiReturnString(cts.Token) | ||
| result |> shouldEqual "Hello world" | ||
| } | ||
| |> Async.StartAsTask | ||
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.