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: introduce flag merge behaviour #414

Merged
merged 28 commits into from
Mar 1, 2023
Merged

feat: introduce flag merge behaviour #414

merged 28 commits into from
Mar 1, 2023

Conversation

james-milligan
Copy link
Contributor

This PR

  • introduces a priority merge order for sync providers
  • triggers a resync of the state store on delete events, ensuring the store doesn't fall out of sync with flag sources

Related Issues

Notes

Follow-up Tasks

How to test

Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
@codecov
Copy link

codecov bot commented Feb 15, 2023

Codecov Report

Merging #414 (c60db46) into main (ab3e674) will increase coverage by 1.24%.
The diff coverage is 69.33%.

❗ Current head c60db46 differs from pull request most recent head ad2ec77. Consider uploading reports for the commit ad2ec77 to get more accurate results

@@            Coverage Diff             @@
##             main     #414      +/-   ##
==========================================
+ Coverage   65.06%   66.30%   +1.24%     
==========================================
  Files          11       11              
  Lines        1374     1395      +21     
==========================================
+ Hits          894      925      +31     
+ Misses        425      414      -11     
- Partials       55       56       +1     
Impacted Files Coverage Δ
pkg/eval/ievaluator.go 100.00% <ø> (ø)
pkg/sync/grpc/grpc_sync.go 61.97% <41.93%> (+1.65%) ⬆️
pkg/store/flags.go 86.57% <82.60%> (+8.51%) ⬆️
pkg/eval/json_evaluator.go 87.89% <90.00%> (+0.05%) ⬆️
pkg/sync/file/filepath_sync.go 54.54% <100.00%> (+1.27%) ⬆️
pkg/sync/http/http_sync.go 46.53% <100.00%> (+3.98%) ⬆️

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

james-milligan and others added 12 commits February 15, 2023 13:20
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
@toddbaert
Copy link
Member

I'm looking at this now. Sorry about the wait @james-milligan

pkg/store/flags_test.go Outdated Show resolved Hide resolved
pkg/sync/isync.go Outdated Show resolved Hide resolved
pkg/sync/isync.go Outdated Show resolved Hide resolved
james-milligan and others added 3 commits February 27, 2023 16:54
Co-authored-by: Todd Baert <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
@Kavindu-Dodan
Copy link
Contributor

I had a look into the PR and I think we need some agreements.

Current implementation focus on resyncs after a deletion. This means the changes we introduce only concern the store delete scenarios. In my view, we need to be careful about core logic (ex:- store - runtime - isync ) changes and breaking changes must be justifiable.

With that, can't we simply rely on the following and ignore resyncs altogether,

  • Sync provider priority is defined by the order of sync args
  • If low-priority providers override an existing flag simply ignore
  • If high priority provider overrides an existing flag, accept that
  • Ignore any other assumptions - we rely on ISync impls to refresh any changes

wouldn't such an approach work or am I not seeing the big picture? 🤔

@toddbaert
Copy link
Member

  • Sync provider priority is defined by the order of sync args
  • If low-priority providers override an existing flag simply ignore
  • If high priority provider overrides an existing flag, accept that
  • Ignore any other assumptions - we rely on ISync impls to refresh any changes

wouldn't such an approach work or am I not seeing the big picture? thinking

That seems to be (to me) more or less what this PR does. See the tests here: https://github.com/open-feature/flagd/pull/414/files/5415b75a4c48bf3ff8014bd92428666711a0a1f8#diff-575f3e52e026f848e85c7a6cd9561cda5def99f4a58a9786801d4d4097f0ae03R12-R73

@Kavindu-Dodan
Copy link
Contributor

  • Sync provider priority is defined by the order of sync args
  • If low-priority providers override an existing flag simply ignore
  • If high priority provider overrides an existing flag, accept that
  • Ignore any other assumptions - we rely on ISync impls to refresh any changes

wouldn't such an approach work or am I not seeing the big picture? thinking

That seems to be (to me) more or less what this PR does. See the tests here: https://github.com/open-feature/flagd/pull/414/files/5415b75a4c48bf3ff8014bd92428666711a0a1f8#diff-575f3e52e026f848e85c7a6cd9561cda5def99f4a58a9786801d4d4097f0ae03R12-R73

Yes, I also think this is what it does. But I am yet to see the need for a resync 🤔 If a low-priority sync provider can't override an existing flag & if sync providers publish updates for changes, then is there any reason for a force refill?

@james-milligan
Copy link
Contributor Author

james-milligan commented Feb 28, 2023

  • Sync provider priority is defined by the order of sync args
  • If low-priority providers override an existing flag simply ignore
  • If high priority provider overrides an existing flag, accept that
  • Ignore any other assumptions - we rely on ISync impls to refresh any changes

wouldn't such an approach work or am I not seeing the big picture? thinking

That seems to be (to me) more or less what this PR does. See the tests here: https://github.com/open-feature/flagd/pull/414/files/5415b75a4c48bf3ff8014bd92428666711a0a1f8#diff-575f3e52e026f848e85c7a6cd9561cda5def99f4a58a9786801d4d4097f0ae03R12-R73

Yes, I also think this is what it does. But I am yet to see the need for a resync 🤔 If a low-priority sync provider can't override an existing flag & if sync providers publish updates for changes, then is there any reason for a force refill?

If flag-a exists in 2 sync providers, (provider-A and provider-B) with provider-A taking priority, then the starup and initial datasync will result in the value of flag-a from provider-B being discarded. In the event that the value of flag-a is then deleted in provider-A then we will not recieve the previously discarded flag-a value from provider-B until there is another update event from it, and the sdk will always return the default value.
We could habdle this with with the existing Sync method, however is many cases we will be starting a new watcher just to close it after the first event is written to the channel IMO this is innapropriate.
Another option is to store all 'discarded' states incase they are needed (or become the highest priority via a deletion) but again this is overly complex for an event that will not happen too often.
The infrequency of these update events also suggests that in the example described above flagd would not have a flag value for flag-a for a long time

@Kavindu-Dodan
Copy link
Contributor

  • Sync provider priority is defined by the order of sync args
  • If low-priority providers override an existing flag simply ignore
  • If high priority provider overrides an existing flag, accept that
  • Ignore any other assumptions - we rely on ISync impls to refresh any changes

wouldn't such an approach work or am I not seeing the big picture? thinking

That seems to be (to me) more or less what this PR does. See the tests here: https://github.com/open-feature/flagd/pull/414/files/5415b75a4c48bf3ff8014bd92428666711a0a1f8#diff-575f3e52e026f848e85c7a6cd9561cda5def99f4a58a9786801d4d4097f0ae03R12-R73

Yes, I also think this is what it does. But I am yet to see the need for a resync 🤔 If a low-priority sync provider can't override an existing flag & if sync providers publish updates for changes, then is there any reason for a force refill?

If flag-a exists in 2 sync providers, (provider-A and provider-B) with provider-A taking priority, then the starup and initial datasync will result in the value of flag-a from provider-B being discarded. In the event that the value of flag-a is then deleted in provider-A then we will not recieve the previously discarded flag-a value from provider-B until there is another update event from it, and the sdk will always return the default value. We could habdle this with with the existing Sync method, however is many cases we will be starting a new watcher just to close it after the first event is written to the channel IMO this is innapropriate. Another option is to store all 'discarded' states incase they are needed (or become the highest priority via a deletion) but again this is overly complex for an event that will not happen too often. The infrequency of these update events also suggests that in the example described above flagd would not have a flag value for flag-a for a long time

Thank you. I now understand the scenario you want to handle. This shows the impact of caching and the difficulty to maintain them.

I am still in favor of not having a refill strategy for removals to minimize the complexity of store and runtime components. But may be others have different opinions and this could be a desirable feature.

pkg/store/flags.go Outdated Show resolved Hide resolved
pkg/store/flags.go Outdated Show resolved Hide resolved
pkg/sync/grpc/grpc_sync_test.go Outdated Show resolved Hide resolved
pkg/sync/grpc/grpc_sync.go Outdated Show resolved Hide resolved
pkg/runtime/runtime.go Show resolved Hide resolved
james-milligan and others added 4 commits March 1, 2023 13:09
Signed-off-by: James Milligan <[email protected]>
Co-authored-by: Skye Gill <[email protected]>
Signed-off-by: James Milligan <[email protected]>
Signed-off-by: James Milligan <[email protected]>
@beeme1mr beeme1mr self-requested a review March 1, 2023 18:42
@beeme1mr
Copy link
Member

beeme1mr commented Mar 1, 2023

Could you please add a section in the docs that describes the merge behavior. It can basically be a summary of the conversations we've had in this thread.

@beeme1mr
Copy link
Member

beeme1mr commented Mar 1, 2023

Please add some debug logging when a duplicate flag key is detected from another source. While the behavior defined in this PR makes sense, it would be very difficult to troubleshoot without any indication that merging occurred.

@beeme1mr beeme1mr merged commit 524f65e into open-feature:main Mar 1, 2023
beeme1mr pushed a commit that referenced this pull request Mar 2, 2023
🤖 I have created a release *beep* *boop*
---


##
[0.4.0](v0.3.7...v0.4.0)
(2023-03-02)


### ⚠ BREAKING CHANGES

* Use OTel to export metrics (metric name changes)
([#419](#419))

### 🧹 Chore

* add additional sections to the release notes
([#449](#449))
([798f71a](798f71a))
* attach image sbom to release artefacts
([#407](#407))
([fb4ee50](fb4ee50))
* **deps:** update actions/configure-pages digest to fc89b04
([#417](#417))
([04014e7](04014e7))
* **deps:** update amannn/action-semantic-pull-request digest to b6bca70
([#441](#441))
([ce0ebe1](ce0ebe1))
* **deps:** update docker/login-action digest to ec9cdf0
([#437](#437))
([2650670](2650670))
* **deps:** update docker/metadata-action digest to 3343011
([#438](#438))
([e7ebf32](e7ebf32))
* **deps:** update github/codeql-action digest to 32dc499
([#439](#439))
([f91d91b](f91d91b))
* **deps:** update google-github-actions/release-please-action digest to
d3c71f9 ([#406](#406))
([6e1ffb2](6e1ffb2))
* disable caching tests in CI
([#442](#442))
([28a35f6](28a35f6))
* fix race condition on init read
([#409](#409))
([0c9eb23](0c9eb23))
* integration test stability
([#432](#432))
([5a6a5d5](5a6a5d5))
* integration tests
([#312](#312))
([6192ac8](6192ac8))
* reorder release note sections
([df7bfce](df7bfce))
* use -short flag in benchmark tests
([#431](#431))
([e68a6aa](e68a6aa))


### 🐛 Bug Fixes

* **deps:** update kubernetes packages to v0.26.2
([#450](#450))
([2885227](2885227))
* **deps:** update module github.com/bufbuild/connect-go to v1.5.2
([#416](#416))
([feb7f04](feb7f04))
* **deps:** update module
github.com/open-feature/go-sdk-contrib/providers/flagd to v0.1.9
([#427](#427))
([42d2705](42d2705))
* **deps:** update module github.com/open-feature/open-feature-operator
to v0.2.29 ([#429](#429))
([b7fae81](b7fae81))
* **deps:** update module github.com/stretchr/testify to v1.8.2
([#440](#440))
([ab3e674](ab3e674))
* **deps:** update module golang.org/x/net to v0.7.0
([#410](#410))
([c6133b6](c6133b6))
* **deps:** update module sigs.k8s.io/controller-runtime to v0.14.5
([#454](#454))
([f907f11](f907f11))
* remove non-error error log from parseFractionalEvaluationData
([#446](#446))
([34aca79](34aca79))


### ✨ New Features

* add debug logging for merge behaviour
([#456](#456))
([dc71e84](dc71e84))
* add Health and Readiness probes
([#418](#418))
([7f2358c](7f2358c))
* Add version to startup message
([#430](#430))
([8daf613](8daf613))
* introduce flag merge behaviour
([#414](#414))
([524f65e](524f65e))
* introduce grpc sync for flagd
([#297](#297))
([33413f2](33413f2))
* refactor and improve K8s sync provider
([#443](#443))
([4c03bfc](4c03bfc))
* Use OTel to export metrics (metric name changes)
([#419](#419))
([eb3982a](eb3982a))


### 📚 Documentation

* add .net flagd provider
([73d7840](73d7840))
* configuration merge docs
([#455](#455))
([6cb66b1](6cb66b1))
* documentation for creating a provider
([#413](#413))
([d0c099d](d0c099d))
* updated filepaths for schema store regex
([#344](#344))
([2d0e9d9](2d0e9d9))

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

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@github-actions github-actions bot mentioned this pull request Dec 2, 2023
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.

5 participants