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(27254): implement new remote-feature-flag-controller #4931

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

DDDDDanica
Copy link

@DDDDDanica DDDDDanica commented Nov 14, 2024

Explanation

Following the ADR here

Adds a new controller, remote-feature-flag-controller that fetches the remote feature flags and provide cache solution for consumers.

References

Related to #67890

Changelog

@metamask/remote-feature-flag-controller

ADDED: Initial release

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've highlighted breaking changes using the "BREAKING" category above as appropriate
  • I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes

@DDDDDanica DDDDDanica force-pushed the feature/27254-feature-flag-controller branch 6 times, most recently from 78af7f4 to cd93f7a Compare November 15, 2024 03:13
Copy link

socket-security bot commented Nov 15, 2024

No dependency changes detected. Learn more about Socket for GitHub ↗︎

👍 No dependency changes detected in pull request

@DDDDDanica DDDDDanica force-pushed the feature/27254-feature-flag-controller branch from cd93f7a to 82f7997 Compare November 16, 2024 03:42
@DDDDDanica DDDDDanica self-assigned this Nov 16, 2024
@DDDDDanica DDDDDanica force-pushed the feature/27254-feature-flag-controller branch 2 times, most recently from 78ca22b to a7a3cf1 Compare November 19, 2024 11:53
@DDDDDanica DDDDDanica marked this pull request as ready for review November 19, 2024 23:04
@DDDDDanica DDDDDanica requested a review from a team as a code owner November 19, 2024 23:04
@DDDDDanica DDDDDanica force-pushed the feature/27254-feature-flag-controller branch 9 times, most recently from 0519340 to fcc71a0 Compare November 20, 2024 12:19
@DDDDDanica
Copy link
Author

@metamaskbot publish-preview

Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/accounts-controller": "19.0.0-preview-fcc71a0",
  "@metamask-previews/address-book-controller": "6.0.1-preview-fcc71a0",
  "@metamask-previews/announcement-controller": "7.0.1-preview-fcc71a0",
  "@metamask-previews/approval-controller": "7.1.1-preview-fcc71a0",
  "@metamask-previews/assets-controllers": "44.0.1-preview-fcc71a0",
  "@metamask-previews/base-controller": "7.0.2-preview-fcc71a0",
  "@metamask-previews/build-utils": "3.0.1-preview-fcc71a0",
  "@metamask-previews/chain-controller": "0.1.3-preview-fcc71a0",
  "@metamask-previews/composable-controller": "9.0.1-preview-fcc71a0",
  "@metamask-previews/controller-utils": "11.4.3-preview-fcc71a0",
  "@metamask-previews/ens-controller": "15.0.0-preview-fcc71a0",
  "@metamask-previews/eth-json-rpc-provider": "4.1.6-preview-fcc71a0",
  "@metamask-previews/gas-fee-controller": "22.0.1-preview-fcc71a0",
  "@metamask-previews/json-rpc-engine": "10.0.1-preview-fcc71a0",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.5-preview-fcc71a0",
  "@metamask-previews/keyring-controller": "18.0.0-preview-fcc71a0",
  "@metamask-previews/logging-controller": "6.0.2-preview-fcc71a0",
  "@metamask-previews/message-manager": "11.0.1-preview-fcc71a0",
  "@metamask-previews/multichain": "0.0.0-preview-fcc71a0",
  "@metamask-previews/name-controller": "8.0.1-preview-fcc71a0",
  "@metamask-previews/network-controller": "22.0.2-preview-fcc71a0",
  "@metamask-previews/notification-controller": "7.0.0-preview-fcc71a0",
  "@metamask-previews/notification-services-controller": "0.13.0-preview-fcc71a0",
  "@metamask-previews/permission-controller": "11.0.3-preview-fcc71a0",
  "@metamask-previews/permission-log-controller": "3.0.1-preview-fcc71a0",
  "@metamask-previews/phishing-controller": "12.3.0-preview-fcc71a0",
  "@metamask-previews/polling-controller": "12.0.1-preview-fcc71a0",
  "@metamask-previews/preferences-controller": "14.0.0-preview-fcc71a0",
  "@metamask-previews/profile-sync-controller": "1.0.2-preview-fcc71a0",
  "@metamask-previews/queued-request-controller": "7.0.1-preview-fcc71a0",
  "@metamask-previews/rate-limit-controller": "6.0.1-preview-fcc71a0",
  "@metamask-previews/selected-network-controller": "19.0.0-preview-fcc71a0",
  "@metamask-previews/signature-controller": "22.0.0-preview-fcc71a0",
  "@metamask-previews/transaction-controller": "39.0.0-preview-fcc71a0",
  "@metamask-previews/user-operation-controller": "18.0.0-preview-fcc71a0"
}

@DDDDDanica DDDDDanica force-pushed the feature/27254-feature-flag-controller branch 6 times, most recently from 153ebc9 to 0fab160 Compare November 21, 2024 21:20
@DDDDDanica DDDDDanica force-pushed the feature/27254-feature-flag-controller branch 2 times, most recently from 993bda6 to 63c3764 Compare November 22, 2024 14:05
Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

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

Hi @DDDDDanica, nice job in creating this controller! This looks really nice. A lot of my comments were minor, to make tests more readable and that sort of thing. I think there might be one missing test.

.idea/core.iml Outdated
Copy link
Contributor

@mcmire mcmire Nov 22, 2024

Choose a reason for hiding this comment

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

Thoughts on adding these .idea files in another commit? I'm not sure what they are. Perhaps they are useful, but another PR would give us a place to explain.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.0]
Copy link
Contributor

Choose a reason for hiding this comment

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

There are two kinds of sections in each changelog: one for each version that's been released so far, and then an "Unreleased" section for change that haven't shown up in a release yet. For new packages, there aren't any versions released, so all we should have here is an "Unreleased" section:

Suggested change
## [0.1.0]
## [Unreleased]

@@ -0,0 +1,15 @@
# `@metamask/example-controllers`
Copy link
Contributor

Choose a reason for hiding this comment

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

We should update this to reflect the name of the package:

Suggested change
# `@metamask/example-controllers`
# `@metamask/remote-feature-flag-controller`

@@ -0,0 +1,15 @@
# `@metamask/example-controllers`

This package is designed to illustrate best practices for controller packages and controller files, including tests.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a description you can give this package? Here's the one you gave in package.json:

Suggested change
This package is designed to illustrate best practices for controller packages and controller files, including tests.
Controller with caching, fallback, and privacy for managing feature flags via ClientConfigAPI.

@@ -0,0 +1,70 @@
{
"name": "@metamask/remote-feature-flag-controller",
"version": "0.0.1",
Copy link
Contributor

Choose a reason for hiding this comment

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

New packages start out at 0.0.0. We will assign a new version when we release the package:

Suggested change
"version": "0.0.1",
"version": "0.0.0",

disabled: true,
});

controller.enable();
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Your setup for this test mirrors how consumers might use this method along with other methods in the API for this controller, so it makes sense you wrote it this way. But remember that when you instantiate the controller you can specify whatever initial state or options you want. So you don't need to necessarily call enable to enable the controller; if you already know that enable sets disabled to false — and you should have a test which confirms this — would it still make sense to pass disabled: false instead?

expect(result2).toStrictEqual(mockFlags);
});

it('should emit state change when updating cache', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you think this test is necessary? The fact that stateChange gets emitted when state is updated is already built in to BaseController, and we have tests for this there. So could we trust that this already happens?

});
});

it('should initialize with disabled parameter', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

What is being tested? If we really want to test the state, should we be more clear?

Suggested change
it('should initialize with disabled parameter', () => {
it('should initialize the controller with default state if the disabled parameter is provided', () => {

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, should we add a test which verifies that you can override any part of state?

});

it('should get feature flags from API when cache is invalid', async () => {
const controller = createController({ clientConfigApiService });
Copy link
Contributor

Choose a reason for hiding this comment

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

What in this test is making the cache invalid?

If it's the default data that we are having the service object return, what are your thoughts on including that data in this test? Otherwise it's not totally clear. Something like:

Suggested change
const controller = createController({ clientConfigApiService });
const controller = createController({ clientConfigApiService });
jest
.spyOn(clientConfigApiService, 'fetchFlags')
.mockImplementation(async () => ({
error: false,
message: 'Success',
statusCode: '200',
statusText: 'OK',
cachedData: { differentFlag: true },
cacheTimestamp: Date.now(),
}));

expect(remoteFeatureFlags).toStrictEqual(mockFlags);
});

it('should handle concurrent flag updates', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I see we have a test which verifies if getRemoteFeatureFlags is called more than one without awaiting then the invocations get resolved in the order in which they occurred. However, what about a test which simulates calling getRemoteFeatureFlags twice, awaiting at each step, and waiting an appropriate amount in between so that the second call creates another fetch? This would essentially verify that #inProgressFlagUpdate gets cleared at the end of the method.


### Added

- Initial release
Copy link
Contributor

Choose a reason for hiding this comment

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

It's best if every changelog entry has a link to the PR that introduced this change. In this case, it's this very PR that introduces the package. So, how about:

Suggested change
- Initial release
- Initial release ([#4931](https://github.com/MetaMask/core/pull/4931))

@DDDDDanica DDDDDanica force-pushed the feature/27254-feature-flag-controller branch from 63c3764 to 2878ef6 Compare November 23, 2024 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Needs dev review
Development

Successfully merging this pull request may close these issues.

2 participants