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

refactor: Improve EventExecutor #393

Merged
merged 9 commits into from
Mar 12, 2025
Merged

Conversation

askpt
Copy link
Member

@askpt askpt commented Feb 28, 2025

This PR

This pull request to src/OpenFeature/EventExecutor.cs includes changes to improve code readability and performance. The most important changes include replacing List and Dictionary initializations with shorthand syntax, switching from Thread to Task for asynchronous operations, and refactoring methods for better clarity and maintainability.

Improvements to code readability and performance:

Refactoring for better clarity and maintainability:

  • src/OpenFeature/EventExecutor.cs: Refactored EmitOnRegistration method to use a switch expression for setting the message based on provider status and event type, improving readability.
  • src/OpenFeature/EventExecutor.cs: Split ProcessEventAsync method into smaller methods (ProcessApiHandlers, ProcessClientHandlers, ProcessDefaultProviderHandlers) for better organization and maintainability. [1] [2] [3]
  • src/OpenFeature/EventExecutor.cs: Converted ProcessFeatureProviderEventsAsync and ProcessEventAsync from void to Task to follow best practices for asynchronous methods. [1] [2]

Related Issues

Reference #358

@askpt askpt linked an issue Feb 28, 2025 that may be closed by this pull request
Copy link

codecov bot commented Feb 28, 2025

Codecov Report

Attention: Patch coverage is 87.95181% with 10 lines in your changes missing coverage. Please review.

Project coverage is 85.90%. Comparing base (9b6feab) to head (e2c1f3a).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/OpenFeature/EventExecutor.cs 87.95% 5 Missing and 5 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #393      +/-   ##
==========================================
- Coverage   86.16%   85.90%   -0.27%     
==========================================
  Files          39       39              
  Lines        1605     1603       -2     
  Branches      173      172       -1     
==========================================
- Hits         1383     1377       -6     
- Misses        186      189       +3     
- Partials       36       37       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@askpt askpt marked this pull request as ready for review February 28, 2025 13:01
@askpt askpt requested a review from a team as a code owner February 28, 2025 13:01
@askpt askpt enabled auto-merge February 28, 2025 13:11
@askpt askpt changed the title refactor!: improve EventExecutor refactor!: Improve EventExecutor Feb 28, 2025
@askpt askpt requested a review from Copilot February 28, 2025 13:45
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

PR Overview

This PR refactors the EventExecutor and related classes for improved code readability, performance, and enhanced null safety. Key changes include replacing explicit constructor calls with array initializer syntax for collections, switching from Thread to Task-based asynchronous processing, and adding null-safety checks on EventChannel usages.

Reviewed Changes

File Description
src/OpenFeature/EventExecutor.cs Refactored to use Task.Run instead of Thread, updated collection initializations, and improved event handling.
test/OpenFeature.Tests/Providers/Memory/InMemoryProviderTests.cs Added null-forgiving operator to EventChannel usage in tests.
src/OpenFeature/Providers/Memory/InMemoryProvider.cs Added null checks before writing to the EventChannel to improve null safety.
test/OpenFeature.Tests/TestImplementations.cs Updated EventChannel usage with null-forgiving operator.
src/OpenFeature/FeatureProvider.cs Updated EventChannel to be nullable for enhanced null safety.

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Copy link
Member

@toddbaert toddbaert left a comment

Choose a reason for hiding this comment

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

Good improvements, thanks.

@toddbaert toddbaert self-requested a review March 7, 2025 18:40
@toddbaert
Copy link
Member

@askpt could you explain the breaking change? How could the event channel be null if we set it? I must be missing something.

I guess this would force providers to do a null check, right? I guess this would only break providers? I won't have any impact on consumers will it? I don't think we want to release a v3 for this.

@askpt
Copy link
Member Author

askpt commented Mar 10, 2025

@askpt could you explain the breaking change? How could the event channel be null if we set it? I must be missing something.

I guess this would force providers to do a null check, right? I guess this would only break providers? I won't have any impact on consumers will it? I don't think we want to release a v3 for this.

@toddbaert If you check test OpenFeature_Should_Shutdown_Unused_Provider you will see the test will fail if you don't do a null check in the method StartListeningAndShutdownOld, particularly on the line oldProvider.GetEventChannel()?.Writer.Complete();. It seems there is the possibility for the EventChannel to be null in this case, so it needs to be marked as a nullable. This is why I needed to mark it as null and the potential breaking change (even though it would be at compile time).

@toddbaert toddbaert requested a review from chrfwow March 11, 2025 20:25
@toddbaert
Copy link
Member

toddbaert commented Mar 11, 2025

@askpt could you explain the breaking change? How could the event channel be null if we set it? I must be missing something.
I guess this would force providers to do a null check, right? I guess this would only break providers? I won't have any impact on consumers will it? I don't think we want to release a v3 for this.

@toddbaert If you check test OpenFeature_Should_Shutdown_Unused_Provider you will see the test will fail if you don't do a null check in the method StartListeningAndShutdownOld, particularly on the line oldProvider.GetEventChannel()?.Writer.Complete();. It seems there is the possibility for the EventChannel to be null in this case, so it needs to be marked as a nullable. This is why I needed to mark it as null and the potential breaking change (even though it would be at compile time).

Isn't that just because we use Substitute.For in that test to create these providers?

What if we remove the virtual from the GetEventChannel accessor though? So it cannot be overridden... that might be a way to guarantee it cannot be null in any case, right? I think that technically still might be breaking (in case somebody overrode it) but it seems more correct and more ergonomic, and also "less breaking".

@askpt
Copy link
Member Author

askpt commented Mar 12, 2025

@askpt could you explain the breaking change? How could the event channel be null if we set it? I must be missing something.
I guess this would force providers to do a null check, right? I guess this would only break providers? I won't have any impact on consumers will it? I don't think we want to release a v3 for this.

@toddbaert If you check test OpenFeature_Should_Shutdown_Unused_Provider you will see the test will fail if you don't do a null check in the method StartListeningAndShutdownOld, particularly on the line oldProvider.GetEventChannel()?.Writer.Complete();. It seems there is the possibility for the EventChannel to be null in this case, so it needs to be marked as a nullable. This is why I needed to mark it as null and the potential breaking change (even though it would be at compile time).

Isn't that just because we use Substitute.For in that test to create these providers?

What if we remove the virtual from the GetEventChannel accessor though? So it cannot be overridden... that might be a way to guarantee it cannot be null in any case, right? I think that technically still might be breaking (in case somebody overrode it) but it seems more correct and more ergonomic, and also "less breaking".

@toddbaert That is a good point. Let's do this. I removed the breaking change part, and we can discuss it on another topic. This PR is already complex enough. Plus, I need to investigate it better to be able to reply to your points! 👍

@askpt askpt changed the title refactor!: Improve EventExecutor refactor: Improve EventExecutor Mar 12, 2025
@askpt askpt requested a review from Copilot March 12, 2025 11:17
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This pull request refactors the EventExecutor to improve readability and performance by adopting shorthand collection initializers, switching from Thread to Task for asynchronous operations, and reorganizing event processing methods. Additional changes include emitting events in the in-memory provider and removing duplicate test helper methods.

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/OpenFeature/EventExecutor.cs Refactored initialization with shorthand syntax, replaced Thread with Task, and reorganized event processing.
src/OpenFeature/Providers/Memory/InMemoryProvider.cs Updated the flag update event emission using the EventChannel.
test/OpenFeature.Tests/TestImplementations.cs Removed duplicate SendEventAsync method to simplify test implementations.
Comments suppressed due to low confidence (2)

src/OpenFeature/EventExecutor.cs:18

  • Using '[]' for List initialization is unconventional in C#. It is recommended to use 'new()' to maintain clarity and avoid potential compilation issues.
private readonly List<FeatureProvider> _activeSubscriptions = [];

src/OpenFeature/EventExecutor.cs:20

  • The shorthand syntax '[]' for initializing a Dictionary may not be supported in all C# versions. Consider using 'new()' for better readability and consistency.
private readonly Dictionary<ProviderEventTypes, List<EventHandlerDelegate>> _apiHandlers = [];

@toddbaert toddbaert disabled auto-merge March 12, 2025 14:22
@toddbaert toddbaert merged commit 46274a2 into main Mar 12, 2025
17 of 18 checks passed
@askpt askpt deleted the askpt/358-clean-eventexecutor branch March 12, 2025 14:28
github-merge-queue bot pushed a commit that referenced this pull request Mar 27, 2025
🤖 I have created a release *beep* *boop*
---


##
[2.3.2](v2.3.1...v2.3.2)
(2025-03-24)


### 🐛 Bug Fixes

* Address issue with newline characters when running Logging Hook Unit
Tests on linux
([#374](#374))
([a98334e](a98334e))
* Remove virtual GetEventChannel from FeatureProvider
([#401](#401))
([00a4e4a](00a4e4a))
* Update project name in solution file
([#380](#380))
([1f13258](1f13258))


### 🧹 Chore

* Correct LoggingHookTest timestamp handling.
([#386](#386))
([c69a6e5](c69a6e5))
* **deps:** update actions/setup-dotnet digest to 67a3573
([#402](#402))
([2e2c489](2e2c489))
* **deps:** update actions/upload-artifact action to v4.6.1
([#385](#385))
([accf571](accf571))
* **deps:** update actions/upload-artifact action to v4.6.2
([#406](#406))
([16c92b7](16c92b7))
* **deps:** update codecov/codecov-action action to v5.4.0
([#392](#392))
([06e4e3a](06e4e3a))
* **deps:** update dependency dotnet-sdk to v9.0.202
([#405](#405))
([a4beaae](a4beaae))
* **deps:** update dependency microsoft.net.test.sdk to 17.13.0
([#375](#375))
([7a735f8](7a735f8))
* **deps:** update dependency reqnroll.xunit to 2.3.0
([#378](#378))
([96ba568](96ba568))
* **deps:** update dependency reqnroll.xunit to 2.4.0
([#396](#396))
([b30350b](b30350b))
* **deps:** update dependency system.valuetuple to 4.6.0
([#403](#403))
([75468d2](75468d2))
* **deps:** update dotnet monorepo
([#379](#379))
([53ced91](53ced91))
* **deps:** update dotnet monorepo to 9.0.2
([#377](#377))
([3bdc79b](3bdc79b))
* **deps:** update github/codeql-action digest to 1b549b9
([#407](#407))
([ae9fc79](ae9fc79))
* **deps:** update github/codeql-action digest to 5f8171a
([#404](#404))
([73a5040](73a5040))
* **deps:** update github/codeql-action digest to 6bb031a
([#398](#398))
([9b6feab](9b6feab))
* **deps:** update github/codeql-action digest to 9e8d078
([#371](#371))
([e74e8e7](e74e8e7))
* **deps:** update github/codeql-action digest to b56ba49
([#384](#384))
([cc2990f](cc2990f))
* **deps:** update spec digest to 0cd553d
([#389](#389))
([85075ac](85075ac))
* **deps:** update spec digest to 54952f3
([#373](#373))
([1e8b230](1e8b230))
* **deps:** update spec digest to a69f748
([#382](#382))
([4977542](4977542))
* remove FluentAssertions
([#361](#361))
([4ecfd24](4ecfd24))
* Replace SpecFlow with Reqnroll for testing framework
([#368](#368))
([ed6ee2c](ed6ee2c)),
closes [#354](#354)
* update release please repo, specify action permissions
([#369](#369))
([63846ad](63846ad))


### 🔄 Refactoring

* Improve EventExecutor
([#393](#393))
([46274a2](46274a2))

---
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: OpenFeature Bot <[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.

3 participants