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

VPN-5854 - Implement infrastructure for creation of experimental features #8821

Closed
wants to merge 9 commits into from

Conversation

brizental
Copy link
Contributor

@brizental brizental commented Dec 15, 2023

Ok, this PR is on top of both #8819 and #8820. The only new commit here is f16f766.

The specification for the experimental feature can be found at: https://github.com/mozilla-mobile/mozilla-vpn-client/blob/main/docs/rfcs/0006-cirrus-experiments.md#3-apply-features.

Note I was not able to implement the APIs as specified in the RFC. This is how they will look like:

MZSettings.onboardingCtaStyleExperiment.get("color");
settingsHolder.onboardingCtaStyleExperiment.get("color");

Yeah, still learning about managing lifetimes without having
my hand held by the compiler. (I miss Rust).

Turns out I would have to cache the value of the setting in the SettigsGroup object for the previous design to work... I think that would not make much sense so I decided to diverge from the initial design and just expose the getter function itself.
@brizental brizental force-pushed the 5854-experimental-feature branch from f16f766 to 0f1c097 Compare December 18, 2023 11:24
@brizental brizental force-pushed the 5854-experimental-feature branch from 0f1c097 to daa295d Compare December 18, 2023 12:53
@brizental brizental changed the base branch from main to pre-experiments-work December 18, 2023 16:46
Intentionally though I will not move other feature files in
it just yet, I can do that in a separate PR.
@brizental brizental force-pushed the 5854-experimental-feature branch from 6bd5aa5 to 21615c7 Compare December 18, 2023 16:51
@brizental brizental force-pushed the pre-experiments-work branch from 7671674 to 6455399 Compare December 18, 2023 17:06
#include "setting.h"
#include "settingsmanager.h"

class SettingFactory {
Copy link
Contributor

@vinocher vinocher Dec 20, 2023

Choose a reason for hiding this comment

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

Should SettingsFactory be folded into SettingManager? Is a separate factory providing value?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done and added to the PRE-WORK PR.

Setting* SettingFactory::createOrGetSetting(
const QString& key, std::function<QVariant()> defaultValue,
bool removeWhenReset, bool sensitiveSetting) {
auto s = SettingsManager::getSetting(key);
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Consider using a more descriptive variable name for 's'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done and added to the PRE-WORK PR.

* @brief Represents a group of dynamic settings. Dynamic setttings can be
* defined at runtime.
*
* This abstraction serves as an aggregator of underlying storage settings.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice header comments!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks Vinoo, means a lot coming from the documentation king himself!

*
* @return QVariant
*/
Q_INVOKABLE QVariant get(const QString& key) const;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is getValue a better name? get(key) seems generic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hum, I think this falls down to personal preference. If you feel strongly about it, I'll change it. Personally, I prefer it like this. If I do change it, I'd change this in all places, right? i.e. get becomes getValue, set becomes setValue, remove becomes removeValue and so on. Let me know!


void SettingGroup::addSetting(const QString& key) {
auto settingKey = getSettingKey(key);
auto setting = SettingFactory::createOrGetSetting(
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this setting being leaked? Does it need a parent QObject, so it can be deleted?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The parent is the SettingsManager instance, whose parent it the QApplication.

* actually be removed when `reset` is called.
* @param sensitiveSetting Whether or not settings in this group are
* sensitive settings i.e. settings that must not be logged in plain text.
* @param acceptedKeys When this list has at least one member, only the listed
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is the enforcement using acceptedKeys needed? If not needed, should it and mayRecord() be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is pre-work for experiments related stuff, which will require an allow list of keys.

Comment on lines +23 to +25
sb->m_settings.beginGroup(m_groupKey);
QStringList keys = sb->m_settings.allKeys();
sb->m_settings.endGroup();
Copy link
Contributor

@vinocher vinocher Dec 20, 2023

Choose a reason for hiding this comment

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

For better encapsulation, consider replacing this block with SettingManager::instance()->getKeysInGroup(m_groupKey), which returns the list of keys of Settings in the group.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have addressed this and added it to the PRE-WORK PR. I did not do exactly what you propose here. I'd not like to add public methods to change the underlying settings to the SettingsManager, that is an invitation for mess ups. Instead, I created a connector for the QSettings that is passed to the Setting and SettingGroup for them to be able to access the QSettings. Let me know what you think about the approach.

Comment on lines +77 to +80
sb->m_settings.beginGroup(m_groupKey);
QStringList keys = sb->m_settings.allKeys();
sb->m_settings.remove("");
sb->m_settings.endGroup();
Copy link
Contributor

@vinocher vinocher Dec 20, 2023

Choose a reason for hiding this comment

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

For better encapsulation, consider replacing this with:
keys = SettingManager::instance()->getKeysInGroup(m_groupKey);
SettingManager::instance()->removeSettingsInGroup(m_groupKey)

Comment on lines +82 to +86
foreach (const QString& key, keys) {
auto setting = SettingsManager::getSetting(key);
Q_ASSERT(setting);
setting->changed();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the settings in the setting group also be removed from SettingManager.m_registeredSettings?

If so, won't SettingsManager::getSetting(key) fail because the setting has been removed? Appears that the change() signal should be emitted before the settings are removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, great catch. I'll address this and add it to the PRE_WORK PR.

@brizental
Copy link
Contributor Author

Ok, in hindsight I think it was confusing to open this PR before closing the PRE-WORK PR. All the current comments are related to PRE-WORK code, so I am closing this and will open a new PR once the PRE-WORK PR is complete!

@brizental brizental closed this Dec 20, 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.

2 participants