Skip to content
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

feat!: add CancellationTokens, ValueTasks hooks #268

Merged
merged 11 commits into from
Jun 17, 2024
Merged

feat!: add CancellationTokens, ValueTasks hooks #268

merged 11 commits into from
Jun 17, 2024

Conversation

toddbaert
Copy link
Member

@toddbaert toddbaert commented May 1, 2024

This PR is a combination of #184 and #185. Changes include:

  • adding cancellation tokens
    • in all cases where async operations include side-effects (setProviderAsync, InitializeAsync, I've specified in the in-line doc that the cancellation token's purpose is to cancel such side-effects - so setting a provider and canceling that operation still results in that provider's being set, but async side-effect should be cancelled. I'm interested in feedback here, I think we need to consider the semantics around this... I suppose the alternative would be to always ensure any state changes only occur after async side-effects, if they weren't cancelled beforehand.
  • adding "Async" suffix to all async methods
  • remove deprecated sync SetProvider methods
  • Using ValueTask for hook methods

    the default choice for any asynchronous method that does not return a result should be to return a Task. Only if performance analysis proves it worthwhile should a ValueTask be used instead of a Task.

    • I think for hooks, ValueTask especially makes sense since often hooks are synchronous, in fact async hooks are probably the less likely variant.
    • I've kept the resolver methods as Task, but there could be an argument for making them ValueTask, since some providers resolve asynchronously.
    • I'm still a bit dubious on the entire idea of ValueTask, so I'm really interested in feedback here
  • associated test updates

UPDATE:

After chewing on this for a night, I'm starting to feel:

  • We should simply remove cancellation tokens from Init/Shutdown. We can always add them later, which would be non-breaking. I think the value is low and the complexity is potentially high.
  • ValueTask is only a good idea for hooks, because:
    • Hooks will very often be synchronous under the hood
    • We (SDK authors) await the hooks, not consumer code, so we can be careful of the potential pitfalls of ValueTask. I think everywhere else we should stick to Task.

@toddbaert toddbaert requested a review from a team as a code owner May 1, 2024 18:34
@toddbaert toddbaert changed the title Value task feat!: add CancellationTokens, ValueTasks to various interfaces May 1, 2024
Copy link
Member

@askpt askpt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a few comments. It is a big diff, but most of it is just renaming.

Overall it looks good but I added some of my concerns.

README.md Show resolved Hide resolved
src/OpenFeature/Api.cs Outdated Show resolved Hide resolved
src/OpenFeature/Api.cs Outdated Show resolved Hide resolved
src/OpenFeature/EventExecutor.cs Show resolved Hide resolved
src/OpenFeature/Model/EvaluationContext.cs Outdated Show resolved Hide resolved
@toddbaert toddbaert requested a review from askpt May 2, 2024 13:42
@toddbaert
Copy link
Member Author

toddbaert commented May 2, 2024

After chewing on this for a night, I'm starting to feel:

  • We should simply remove cancellation tokens from Init/Shutdown. We can always add them later, which would be non-breaking. I think the value is low and the complexity is potentially high.
  • ValueTask is only a good idea for hooks, because:
    • Hooks will very often be synchronous under the hood
    • We (SDK authors) await the hooks, not consumer code, so we can be careful of the potential pitfalls of ValueTask. I think everywhere else we should stick to Task.

@toddbaert toddbaert changed the title feat!: add CancellationTokens, ValueTasks to various interfaces feat!: add CancellationTokens, ValueTasks hooks May 3, 2024
Copy link
Member

@kinyoklion kinyoklion left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we should probably have tests which have a dummy async provider that blocks evaluations until cancelled, then we should start an evaluation and cancel it to make sure all the steps happen. Maybe something similar with a hook implementation.

@toddbaert
Copy link
Member Author

I think that we should probably have tests which have a dummy async provider that blocks evaluations until cancelled, then we should start an evaluation and cancel it to make sure all the steps happen. Maybe something similar with a hook implementation.

That's a good idea. Will add.

@toddbaert toddbaert requested a review from kinyoklion May 13, 2024 18:46
@toddbaert
Copy link
Member Author

I think that we should probably have tests which have a dummy async provider that blocks evaluations until cancelled, then we should start an evaluation and cancel it to make sure all the steps happen. Maybe something similar with a hook implementation.

That's a good idea. Will add.

I've added tests for cancellation (evaluation/resolution and hooks): 036d7a4

Copy link
Member

@askpt askpt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a few suggestions around the tests.
We should await the async operations, and we should not use async void but async Task.

@askpt askpt self-requested a review May 14, 2024 07:41
Copy link
Member

@askpt askpt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resetting my approval. Sorry! 😃

@toddbaert toddbaert merged commit 33154d2 into main Jun 17, 2024
11 checks passed
toddbaert added a commit that referenced this pull request Aug 21, 2024
🤖 I have created a release *beep* *boop*
---


##
[2.0.0](v1.5.0...v2.0.0)
(2024-08-21)

Today we're announcing the release of the OpenFeature SDK for .NET,
v2.0! This release contains several ergonomic improvements to the SDK,
which .NET developers will appreciate. It also includes some performance
optimizations brought to you by the latest .NET primitives.

For details and migration tips, check out:
https://openfeature.dev/blog/dotnet-sdk-v2

### ⚠ BREAKING CHANGES

* domain instead of client name
([#294](#294))
* internally maintain provider status
([#276](#276))
* add CancellationTokens, ValueTasks hooks
([#268](#268))
* Use same type for flag metadata and event metadata
([#241](#241))
* Enable nullable reference types
([#253](#253))

### 🐛 Bug Fixes

* Add missing error message when an error occurred
([#256](#256))
([949d53c](949d53c))
* Should map metadata when converting from ResolutionDetails to
FlagEvaluationDetails
([#282](#282))
([2f8bd21](2f8bd21))


### ✨ New Features

* add CancellationTokens, ValueTasks hooks
([#268](#268))
([33154d2](33154d2))
* back targetingKey with internal map
([#287](#287))
([ccc2f7f](ccc2f7f))
* domain instead of client name
([#294](#294))
([4c0592e](4c0592e))
* Drop net7 TFM
([#284](#284))
([2dbe1f4](2dbe1f4))
* internally maintain provider status
([#276](#276))
([63faa84](63faa84))
* Use same type for flag metadata and event metadata
([#241](#241))
([ac7d7de](ac7d7de))


### 🧹 Chore

* cleanup code
([#277](#277))
([44cf586](44cf586))
* **deps:** Project file cleanup and remove unnecessary dependencies
([#251](#251))
([79def47](79def47))
* **deps:** update actions/upload-artifact action to v4.3.3
([#263](#263))
([7718649](7718649))
* **deps:** update actions/upload-artifact action to v4.3.4
([#278](#278))
([15189f1](15189f1))
* **deps:** update actions/upload-artifact action to v4.3.5
([#291](#291))
([00e99d6](00e99d6))
* **deps:** update codecov/codecov-action action to v4
([#227](#227))
([11a0333](11a0333))
* **deps:** update codecov/codecov-action action to v4.3.1
([#267](#267))
([ff9df59](ff9df59))
* **deps:** update codecov/codecov-action action to v4.5.0
([#272](#272))
([281295d](281295d))
* **deps:** update dependency benchmarkdotnet to v0.14.0
([#293](#293))
([aec222f](aec222f))
* **deps:** update dependency coverlet.collector to v6.0.2
([#247](#247))
([ab34c16](ab34c16))
* **deps:** update dependency coverlet.msbuild to v6.0.2
([#239](#239))
([e654222](e654222))
* **deps:** update dependency dotnet-sdk to v8.0.204
([#261](#261))
([8f82645](8f82645))
* **deps:** update dependency dotnet-sdk to v8.0.301
([#271](#271))
([acd0385](acd0385))
* **deps:** update dependency dotnet-sdk to v8.0.303
([#275](#275))
([871dcac](871dcac))
* **deps:** update dependency dotnet-sdk to v8.0.400
([#295](#295))
([bb4f352](bb4f352))
* **deps:** update dependency githubactionstestlogger to v2.4.1
([#274](#274))
([46c2b15](46c2b15))
* **deps:** update dependency microsoft.net.test.sdk to v17.10.0
([#273](#273))
([581ff81](581ff81))
* **deps:** update dotnet monorepo
([#218](#218))
([bc8301d](bc8301d))
* **deps:** update xunit-dotnet monorepo
([#262](#262))
([43f14cc](43f14cc))
* **deps:** update xunit-dotnet monorepo
([#279](#279))
([fb1cc66](fb1cc66))
* **deps:** update xunit-dotnet monorepo to v2.8.1
([#266](#266))
([a7b6d85](a7b6d85))
* Enable nullable reference types
([#253](#253))
([5a5312c](5a5312c))
* in-memory UpdateFlags to UpdateFlagsAsync
([#298](#298))
([390205a](390205a))
* prompt 2.0
([9b9c3fd](9b9c3fd))
* Support for determining spec support for the repo
([#270](#270))
([67a1a0a](67a1a0a))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: Todd Baert <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Todd Baert <[email protected]>
arttonoyan pushed a commit to arttonoyan/dotnet-sdk that referenced this pull request Oct 16, 2024
🤖 I have created a release *beep* *boop*
---

##
[2.0.0](open-feature/dotnet-sdk@v1.5.0...v2.0.0)
(2024-08-21)

Today we're announcing the release of the OpenFeature SDK for .NET,
v2.0! This release contains several ergonomic improvements to the SDK,
which .NET developers will appreciate. It also includes some performance
optimizations brought to you by the latest .NET primitives.

For details and migration tips, check out:
https://openfeature.dev/blog/dotnet-sdk-v2

### ⚠ BREAKING CHANGES

* domain instead of client name
([open-feature#294](open-feature#294))
* internally maintain provider status
([open-feature#276](open-feature#276))
* add CancellationTokens, ValueTasks hooks
([open-feature#268](open-feature#268))
* Use same type for flag metadata and event metadata
([open-feature#241](open-feature#241))
* Enable nullable reference types
([open-feature#253](open-feature#253))

### 🐛 Bug Fixes

* Add missing error message when an error occurred
([open-feature#256](open-feature#256))
([949d53c](open-feature@949d53c))
* Should map metadata when converting from ResolutionDetails to
FlagEvaluationDetails
([open-feature#282](open-feature#282))
([2f8bd21](open-feature@2f8bd21))

### ✨ New Features

* add CancellationTokens, ValueTasks hooks
([open-feature#268](open-feature#268))
([33154d2](open-feature@33154d2))
* back targetingKey with internal map
([open-feature#287](open-feature#287))
([ccc2f7f](open-feature@ccc2f7f))
* domain instead of client name
([open-feature#294](open-feature#294))
([4c0592e](open-feature@4c0592e))
* Drop net7 TFM
([open-feature#284](open-feature#284))
([2dbe1f4](open-feature@2dbe1f4))
* internally maintain provider status
([open-feature#276](open-feature#276))
([63faa84](open-feature@63faa84))
* Use same type for flag metadata and event metadata
([open-feature#241](open-feature#241))
([ac7d7de](open-feature@ac7d7de))

### 🧹 Chore

* cleanup code
([open-feature#277](open-feature#277))
([44cf586](open-feature@44cf586))
* **deps:** Project file cleanup and remove unnecessary dependencies
([open-feature#251](open-feature#251))
([79def47](open-feature@79def47))
* **deps:** update actions/upload-artifact action to v4.3.3
([open-feature#263](open-feature#263))
([7718649](open-feature@7718649))
* **deps:** update actions/upload-artifact action to v4.3.4
([open-feature#278](open-feature#278))
([15189f1](open-feature@15189f1))
* **deps:** update actions/upload-artifact action to v4.3.5
([open-feature#291](open-feature#291))
([00e99d6](open-feature@00e99d6))
* **deps:** update codecov/codecov-action action to v4
([open-feature#227](open-feature#227))
([11a0333](open-feature@11a0333))
* **deps:** update codecov/codecov-action action to v4.3.1
([open-feature#267](open-feature#267))
([ff9df59](open-feature@ff9df59))
* **deps:** update codecov/codecov-action action to v4.5.0
([open-feature#272](open-feature#272))
([281295d](open-feature@281295d))
* **deps:** update dependency benchmarkdotnet to v0.14.0
([open-feature#293](open-feature#293))
([aec222f](open-feature@aec222f))
* **deps:** update dependency coverlet.collector to v6.0.2
([open-feature#247](open-feature#247))
([ab34c16](open-feature@ab34c16))
* **deps:** update dependency coverlet.msbuild to v6.0.2
([open-feature#239](open-feature#239))
([e654222](open-feature@e654222))
* **deps:** update dependency dotnet-sdk to v8.0.204
([open-feature#261](open-feature#261))
([8f82645](open-feature@8f82645))
* **deps:** update dependency dotnet-sdk to v8.0.301
([open-feature#271](open-feature#271))
([acd0385](open-feature@acd0385))
* **deps:** update dependency dotnet-sdk to v8.0.303
([open-feature#275](open-feature#275))
([871dcac](open-feature@871dcac))
* **deps:** update dependency dotnet-sdk to v8.0.400
([open-feature#295](open-feature#295))
([bb4f352](open-feature@bb4f352))
* **deps:** update dependency githubactionstestlogger to v2.4.1
([open-feature#274](open-feature#274))
([46c2b15](open-feature@46c2b15))
* **deps:** update dependency microsoft.net.test.sdk to v17.10.0
([open-feature#273](open-feature#273))
([581ff81](open-feature@581ff81))
* **deps:** update dotnet monorepo
([open-feature#218](open-feature#218))
([bc8301d](open-feature@bc8301d))
* **deps:** update xunit-dotnet monorepo
([open-feature#262](open-feature#262))
([43f14cc](open-feature@43f14cc))
* **deps:** update xunit-dotnet monorepo
([open-feature#279](open-feature#279))
([fb1cc66](open-feature@fb1cc66))
* **deps:** update xunit-dotnet monorepo to v2.8.1
([open-feature#266](open-feature#266))
([a7b6d85](open-feature@a7b6d85))
* Enable nullable reference types
([open-feature#253](open-feature#253))
([5a5312c](open-feature@5a5312c))
* in-memory UpdateFlags to UpdateFlagsAsync
([open-feature#298](open-feature#298))
([390205a](open-feature@390205a))
* prompt 2.0
([9b9c3fd](open-feature@9b9c3fd))
* Support for determining spec support for the repo
([open-feature#270](open-feature#270))
([67a1a0a](open-feature@67a1a0a))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: Todd Baert <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Todd Baert <[email protected]>
Signed-off-by: Artyom Tonoyan <[email protected]>
arttonoyan pushed a commit to arttonoyan/dotnet-sdk that referenced this pull request Nov 17, 2024
This PR is a combination of
open-feature#184 and
open-feature#185. Changes include:

- adding cancellation tokens
- in all cases where async operations include side-effects
(`setProviderAsync`, `InitializeAsync`, I've specified in the in-line
doc that the cancellation token's purpose is to cancel such side-effects
- so setting a provider and canceling that operation still results in
that provider's being set, but async side-effect should be cancelled.
I'm interested in feedback here, I think we need to consider the
semantics around this... I suppose the alternative would be to always
ensure any state changes only occur after async side-effects, if they
weren't cancelled beforehand.
- adding "Async" suffix to all async methods
- remove deprecated sync `SetProvider` methods
- Using `ValueTask` for hook methods
- I've decided against converting all `Tasks` to `ValueTasks`, from the
[official .NET
docs](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.valuetask?view=net-8.0):
> the default choice for any asynchronous method that does not return a
result should be to return a
[Task](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task?view=net-8.0).
Only if performance analysis proves it worthwhile should a ValueTask be
used instead of a
[Task](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task?view=net-8.0).
- I think for hooks, `ValueTask` especially makes sense since often
hooks are synchronous, in fact async hooks are probably the less likely
variant.
- I've kept the resolver methods as `Task`, but there could be an
argument for making them `ValueTask`, since some providers resolve
asynchronously.
- I'm still a bit dubious on the entire idea of `ValueTask`, so I'm
really interested in feedback here
- associated test updates

UPDATE:

After chewing on this for a night, I'm starting to feel:
- We should simply remove cancellation tokens from Init/Shutdown. We can
always add them later, which would be non-breaking. I think the value is
low and the complexity is potentially high.
- ValueTask is only a good idea for hooks, because:
  - Hooks will very often be synchronous under the hood
- We (SDK authors) await the hooks, not consumer code, so we can be
careful of the potential pitfalls of ValueTask. I think everywhere else
we should stick to Task.

---------

Signed-off-by: Austin Drenski <[email protected]>
Signed-off-by: Todd Baert <[email protected]>
Co-authored-by: Austin Drenski <[email protected]>
Co-authored-by: André Silva <[email protected]>
Co-authored-by: Ryan Lamb <[email protected]>
Signed-off-by: Artyom Tonoyan <[email protected]>
arttonoyan pushed a commit to arttonoyan/dotnet-sdk that referenced this pull request Nov 17, 2024
🤖 I have created a release *beep* *boop*
---

##
[2.0.0](open-feature/dotnet-sdk@v1.5.0...v2.0.0)
(2024-08-21)

Today we're announcing the release of the OpenFeature SDK for .NET,
v2.0! This release contains several ergonomic improvements to the SDK,
which .NET developers will appreciate. It also includes some performance
optimizations brought to you by the latest .NET primitives.

For details and migration tips, check out:
https://openfeature.dev/blog/dotnet-sdk-v2

### ⚠ BREAKING CHANGES

* domain instead of client name
([open-feature#294](open-feature#294))
* internally maintain provider status
([open-feature#276](open-feature#276))
* add CancellationTokens, ValueTasks hooks
([open-feature#268](open-feature#268))
* Use same type for flag metadata and event metadata
([open-feature#241](open-feature#241))
* Enable nullable reference types
([open-feature#253](open-feature#253))

### 🐛 Bug Fixes

* Add missing error message when an error occurred
([open-feature#256](open-feature#256))
([949d53c](open-feature@949d53c))
* Should map metadata when converting from ResolutionDetails to
FlagEvaluationDetails
([open-feature#282](open-feature#282))
([2f8bd21](open-feature@2f8bd21))

### ✨ New Features

* add CancellationTokens, ValueTasks hooks
([open-feature#268](open-feature#268))
([33154d2](open-feature@33154d2))
* back targetingKey with internal map
([open-feature#287](open-feature#287))
([ccc2f7f](open-feature@ccc2f7f))
* domain instead of client name
([open-feature#294](open-feature#294))
([4c0592e](open-feature@4c0592e))
* Drop net7 TFM
([open-feature#284](open-feature#284))
([2dbe1f4](open-feature@2dbe1f4))
* internally maintain provider status
([open-feature#276](open-feature#276))
([63faa84](open-feature@63faa84))
* Use same type for flag metadata and event metadata
([open-feature#241](open-feature#241))
([ac7d7de](open-feature@ac7d7de))

### 🧹 Chore

* cleanup code
([open-feature#277](open-feature#277))
([44cf586](open-feature@44cf586))
* **deps:** Project file cleanup and remove unnecessary dependencies
([open-feature#251](open-feature#251))
([79def47](open-feature@79def47))
* **deps:** update actions/upload-artifact action to v4.3.3
([open-feature#263](open-feature#263))
([7718649](open-feature@7718649))
* **deps:** update actions/upload-artifact action to v4.3.4
([open-feature#278](open-feature#278))
([15189f1](open-feature@15189f1))
* **deps:** update actions/upload-artifact action to v4.3.5
([open-feature#291](open-feature#291))
([00e99d6](open-feature@00e99d6))
* **deps:** update codecov/codecov-action action to v4
([open-feature#227](open-feature#227))
([11a0333](open-feature@11a0333))
* **deps:** update codecov/codecov-action action to v4.3.1
([open-feature#267](open-feature#267))
([ff9df59](open-feature@ff9df59))
* **deps:** update codecov/codecov-action action to v4.5.0
([open-feature#272](open-feature#272))
([281295d](open-feature@281295d))
* **deps:** update dependency benchmarkdotnet to v0.14.0
([open-feature#293](open-feature#293))
([aec222f](open-feature@aec222f))
* **deps:** update dependency coverlet.collector to v6.0.2
([open-feature#247](open-feature#247))
([ab34c16](open-feature@ab34c16))
* **deps:** update dependency coverlet.msbuild to v6.0.2
([open-feature#239](open-feature#239))
([e654222](open-feature@e654222))
* **deps:** update dependency dotnet-sdk to v8.0.204
([open-feature#261](open-feature#261))
([8f82645](open-feature@8f82645))
* **deps:** update dependency dotnet-sdk to v8.0.301
([open-feature#271](open-feature#271))
([acd0385](open-feature@acd0385))
* **deps:** update dependency dotnet-sdk to v8.0.303
([open-feature#275](open-feature#275))
([871dcac](open-feature@871dcac))
* **deps:** update dependency dotnet-sdk to v8.0.400
([open-feature#295](open-feature#295))
([bb4f352](open-feature@bb4f352))
* **deps:** update dependency githubactionstestlogger to v2.4.1
([open-feature#274](open-feature#274))
([46c2b15](open-feature@46c2b15))
* **deps:** update dependency microsoft.net.test.sdk to v17.10.0
([open-feature#273](open-feature#273))
([581ff81](open-feature@581ff81))
* **deps:** update dotnet monorepo
([open-feature#218](open-feature#218))
([bc8301d](open-feature@bc8301d))
* **deps:** update xunit-dotnet monorepo
([open-feature#262](open-feature#262))
([43f14cc](open-feature@43f14cc))
* **deps:** update xunit-dotnet monorepo
([open-feature#279](open-feature#279))
([fb1cc66](open-feature@fb1cc66))
* **deps:** update xunit-dotnet monorepo to v2.8.1
([open-feature#266](open-feature#266))
([a7b6d85](open-feature@a7b6d85))
* Enable nullable reference types
([open-feature#253](open-feature#253))
([5a5312c](open-feature@5a5312c))
* in-memory UpdateFlags to UpdateFlagsAsync
([open-feature#298](open-feature#298))
([390205a](open-feature@390205a))
* prompt 2.0
([9b9c3fd](open-feature@9b9c3fd))
* Support for determining spec support for the repo
([open-feature#270](open-feature#270))
([67a1a0a](open-feature@67a1a0a))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: Todd Baert <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Todd Baert <[email protected]>
Signed-off-by: Artyom Tonoyan <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants