Skip to content

Commit 0e21cb4

Browse files
committed
Revert "EXP-5700: Change from global rollout opt-out to experiments and rollouts separately (#6888) (#6919)"
This reverts commit cf4f4a8.
1 parent f3ca921 commit 0e21cb4

File tree

19 files changed

+153
-630
lines changed

19 files changed

+153
-630
lines changed

components/nimbus/android/src/main/java/org/mozilla/experiments/nimbus/Nimbus.kt

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -141,30 +141,11 @@ open class Nimbus(
141141

142142
private val nimbusClient: NimbusClientInterface
143143

144-
override var experimentParticipation: Boolean
145-
get() = nimbusClient.getExperimentParticipation()
146-
set(active) {
147-
dbScope.launch {
148-
nimbusClient.setExperimentParticipation(active)
149-
applyPendingExperimentsOnThisThread()
150-
}
151-
}
152-
153-
override var rolloutParticipation: Boolean
154-
get() = nimbusClient.getRolloutParticipation()
155-
set(active) {
156-
dbScope.launch {
157-
nimbusClient.setRolloutParticipation(active)
158-
applyPendingExperimentsOnThisThread()
159-
}
160-
}
161-
162144
override var globalUserParticipation: Boolean
163145
get() = nimbusClient.getGlobalUserParticipation()
164146
set(active) {
165147
dbScope.launch {
166-
setExperimentParticipationOnThisThread(active)
167-
setRolloutParticipationOnThisThread(active)
148+
setGlobalUserParticipationOnThisThread(active)
168149
}
169150
}
170151

@@ -419,36 +400,13 @@ open class Nimbus(
419400

420401
@WorkerThread
421402
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
422-
internal fun setExperimentParticipationOnThisThread(active: Boolean) =
423-
withCatchAll("setExperimentParticipation") {
424-
val enrolmentChanges = nimbusClient.setExperimentParticipation(active)
425-
if (enrolmentChanges.isNotEmpty()) {
426-
recordExperimentTelemetryEvents(enrolmentChanges)
427-
postEnrolmentCalculation()
428-
}
429-
}
430-
431-
@WorkerThread
432-
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
433-
internal fun setRolloutParticipationOnThisThread(active: Boolean) =
434-
withCatchAll("setRolloutParticipation") {
435-
val enrolmentChanges = nimbusClient.setRolloutParticipation(active)
436-
if (enrolmentChanges.isNotEmpty()) {
437-
recordExperimentTelemetryEvents(enrolmentChanges)
438-
postEnrolmentCalculation()
439-
}
440-
}
441-
442-
@WorkerThread
443-
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
444-
internal fun setGlobalUserParticipationOnThisThread(active: Boolean) =
445-
withCatchAll("setGlobalUserParticipation") {
446-
val enrolmentChanges = nimbusClient.setGlobalUserParticipation(active)
447-
if (enrolmentChanges.isNotEmpty()) {
448-
recordExperimentTelemetryEvents(enrolmentChanges)
449-
postEnrolmentCalculation()
450-
}
403+
internal fun setGlobalUserParticipationOnThisThread(active: Boolean) = withCatchAll("setGlobalUserParticipation") {
404+
val enrolmentChanges = nimbusClient.setGlobalUserParticipation(active)
405+
if (enrolmentChanges.isNotEmpty()) {
406+
recordExperimentTelemetryEvents(enrolmentChanges)
407+
postEnrolmentCalculation()
451408
}
409+
}
452410

453411
override fun optOut(experimentId: String) {
454412
dbScope.launch {

components/nimbus/android/src/main/java/org/mozilla/experiments/nimbus/NimbusInterface.kt

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -198,27 +198,11 @@ interface NimbusInterface : FeaturesInterface, NimbusMessagingInterface, NimbusE
198198
*/
199199
fun resetTelemetryIdentifiers() = Unit
200200

201-
var globalUserParticipation: Boolean
202-
get() = experimentParticipation && rolloutParticipation
203-
set(value) {
204-
experimentParticipation = value
205-
rolloutParticipation = value
206-
}
207-
208-
/**
209-
* Control the opt out for experiments. This is likely a user action.
210-
* When set to false, the user will be opted out of all experiments but not rollouts.
211-
*/
212-
var experimentParticipation: Boolean
213-
get() = true
214-
set(_) = Unit
215-
216201
/**
217-
* Control the opt out for rollouts. This is likely a user action.
218-
* When set to false, the user will be opted out of all rollouts but not experiments.
219-
*/
220-
var rolloutParticipation: Boolean
221-
get() = true
202+
* Control the opt out for all experiments at once. This is likely a user action.
203+
*/
204+
var globalUserParticipation: Boolean
205+
get() = false
222206
set(_) = Unit
223207

224208
override val events: NimbusEventStore

components/nimbus/android/src/test/java/org/mozilla/experiments/nimbus/NimbusTests.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,8 +450,8 @@ class NimbusTests {
450450
NimbusEvents.disqualification.testGetValue(),
451451
)
452452

453-
// Opt out of experiments but keep rollouts
454-
nimbus.setExperimentParticipationOnThisThread(false)
453+
// Opt out of all experiments
454+
nimbus.setGlobalUserParticipationOnThisThread(false)
455455

456456
// Use the Glean test API to check that the valid event is present
457457
assertNotNull("Event must have a value", NimbusEvents.disqualification.testGetValue())

components/nimbus/src/enrollment.rs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,6 @@ impl Display for NotEnrolledReason {
7575
}
7676
}
7777

78-
#[derive(Serialize, Deserialize, Debug, Clone)]
79-
pub struct Participation {
80-
pub in_experiments: bool,
81-
pub in_rollouts: bool,
82-
}
83-
84-
impl Default for Participation {
85-
fn default() -> Self {
86-
Self {
87-
in_experiments: true,
88-
in_rollouts: true,
89-
}
90-
}
91-
}
92-
9378
// These are types we use internally for managing disqualifications.
9479

9580
// ⚠️ Attention : Changes to this type should be accompanied by a new test ⚠️
@@ -598,7 +583,7 @@ impl<'a> EnrollmentsEvolver<'a> {
598583

599584
pub(crate) fn evolve_enrollments<E>(
600585
&mut self,
601-
participation: Participation,
586+
is_user_participating: bool,
602587
prev_experiments: &[E],
603588
next_experiments: &[Experiment],
604589
prev_enrollments: &[ExperimentEnrollment],
@@ -619,7 +604,7 @@ impl<'a> EnrollmentsEvolver<'a> {
619604
let next_rollouts = filter_experiments(next_experiments, ExperimentMetadata::is_rollout);
620605

621606
let (next_ro_enrollments, ro_events) = self.evolve_enrollment_recipes(
622-
participation.in_rollouts,
607+
is_user_participating,
623608
&prev_rollouts,
624609
&next_rollouts,
625610
&ro_enrollments,
@@ -643,7 +628,7 @@ impl<'a> EnrollmentsEvolver<'a> {
643628
.collect();
644629

645630
let (next_exp_enrollments, exp_events) = self.evolve_enrollment_recipes(
646-
participation.in_experiments,
631+
is_user_participating,
647632
&prev_experiments,
648633
&next_experiments,
649634
&prev_enrollments,

components/nimbus/src/nimbus.udl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ interface NimbusClient {
239239
[Throws=NimbusError]
240240
sequence<AvailableExperiment> get_available_experiments();
241241

242-
/// Getter and setter for user's participation in experiments only.
242+
/// Getter and setter for user's participation in all experiments.
243243
/// Possible values are:
244244
/// * `true`: the user will enroll in experiments as usual.
245245
/// * `false`: the user will not enroll in new experiments, and opt out of all existing ones.
@@ -276,7 +276,7 @@ interface NimbusClient {
276276
/// Toggles the enablement of the fetch. If `false`, then calling `fetch_experiments`
277277
/// returns immediately, having not done any fetching from remote settings.
278278
/// This is only useful for QA, and should not be used in production: use
279-
/// `set_experiment_participation` or `set_rollout_participation` instead.
279+
/// `set_global_user_participation` instead.
280280
[Throws=NimbusError]
281281
void set_fetch_enabled(boolean flag);
282282

components/nimbus/src/stateful/enrollment.rs

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
/* This Source Code Form is subject to the terms of the Mozilla Public
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4-
use crate::enrollment::Participation;
5-
use crate::stateful::persistence::{
6-
DB_KEY_EXPERIMENT_PARTICIPATION, DB_KEY_ROLLOUT_PARTICIPATION,
7-
DEFAULT_EXPERIMENT_PARTICIPATION, DEFAULT_ROLLOUT_PARTICIPATION,
8-
};
94
use crate::{
105
enrollment::{
116
map_enrollments, EnrollmentChangeEvent, EnrollmentChangeEventType, EnrollmentsEvolver,
@@ -19,6 +14,9 @@ use crate::{
1914
EnrolledExperiment, EnrollmentStatus, Experiment,
2015
};
2116

17+
const DB_KEY_GLOBAL_USER_PARTICIPATION: &str = "user-opt-in";
18+
const DEFAULT_GLOBAL_USER_PARTICIPATION: bool = true;
19+
2220
impl EnrollmentsEvolver<'_> {
2321
/// Convenient wrapper around `evolve_enrollments` that fetches the current state of experiments,
2422
/// enrollments and user participation from the database.
@@ -28,22 +26,15 @@ impl EnrollmentsEvolver<'_> {
2826
writer: &mut Writer,
2927
next_experiments: &[Experiment],
3028
) -> Result<Vec<EnrollmentChangeEvent>> {
31-
// Get separate participation states from the db
32-
let is_participating_in_experiments = get_experiment_participation(db, writer)?;
33-
let is_participating_in_rollouts = get_rollout_participation(db, writer)?;
34-
35-
let participation = Participation {
36-
in_experiments: is_participating_in_experiments,
37-
in_rollouts: is_participating_in_rollouts,
38-
};
39-
29+
// Get the state from the db.
30+
let is_user_participating = get_global_user_participation(db, writer)?;
4031
let experiments_store = db.get_store(StoreId::Experiments);
4132
let enrollments_store = db.get_store(StoreId::Enrollments);
4233
let prev_experiments: Vec<Experiment> = experiments_store.collect_all(writer)?;
4334
let prev_enrollments: Vec<ExperimentEnrollment> = enrollments_store.collect_all(writer)?;
4435
// Calculate the changes.
4536
let (next_enrollments, enrollments_change_events) = self.evolve_enrollments(
46-
participation,
37+
is_user_participating,
4738
&prev_experiments,
4839
next_experiments,
4940
&prev_enrollments,
@@ -180,41 +171,26 @@ pub fn unenroll_for_pref(
180171
Ok(events)
181172
}
182173

183-
pub fn get_experiment_participation<'r>(
174+
pub fn get_global_user_participation<'r>(
184175
db: &Database,
185176
reader: &'r impl Readable<'r>,
186177
) -> Result<bool> {
187178
let store = db.get_store(StoreId::Meta);
188-
let opted_in = store.get::<bool, _>(reader, DB_KEY_EXPERIMENT_PARTICIPATION)?;
189-
if let Some(opted_in) = opted_in {
190-
Ok(opted_in)
191-
} else {
192-
Ok(DEFAULT_EXPERIMENT_PARTICIPATION)
193-
}
194-
}
195-
196-
pub fn get_rollout_participation<'r>(db: &Database, reader: &'r impl Readable<'r>) -> Result<bool> {
197-
let store = db.get_store(StoreId::Meta);
198-
let opted_in = store.get::<bool, _>(reader, DB_KEY_ROLLOUT_PARTICIPATION)?;
179+
let opted_in = store.get::<bool, _>(reader, DB_KEY_GLOBAL_USER_PARTICIPATION)?;
199180
if let Some(opted_in) = opted_in {
200181
Ok(opted_in)
201182
} else {
202-
Ok(DEFAULT_ROLLOUT_PARTICIPATION)
183+
Ok(DEFAULT_GLOBAL_USER_PARTICIPATION)
203184
}
204185
}
205186

206-
pub fn set_experiment_participation(
187+
pub fn set_global_user_participation(
207188
db: &Database,
208189
writer: &mut Writer,
209190
opt_in: bool,
210191
) -> Result<()> {
211192
let store = db.get_store(StoreId::Meta);
212-
store.put(writer, DB_KEY_EXPERIMENT_PARTICIPATION, &opt_in)
213-
}
214-
215-
pub fn set_rollout_participation(db: &Database, writer: &mut Writer, opt_in: bool) -> Result<()> {
216-
let store = db.get_store(StoreId::Meta);
217-
store.put(writer, DB_KEY_ROLLOUT_PARTICIPATION, &opt_in)
193+
store.put(writer, DB_KEY_GLOBAL_USER_PARTICIPATION, &opt_in)
218194
}
219195

220196
/// Reset unique identifiers in response to application-level telemetry reset.

components/nimbus/src/stateful/nimbus_client.rs

Lines changed: 8 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ use crate::{
2626
client::{create_client, SettingsClient},
2727
dbcache::DatabaseCache,
2828
enrollment::{
29-
get_experiment_participation, get_rollout_participation, opt_in_with_branch, opt_out,
30-
reset_telemetry_identifiers, set_experiment_participation, set_rollout_participation,
31-
unenroll_for_pref,
29+
get_global_user_participation, opt_in_with_branch, opt_out,
30+
reset_telemetry_identifiers, set_global_user_participation, unenroll_for_pref,
3231
},
3332
gecko_prefs::{
3433
GeckoPref, GeckoPrefHandler, GeckoPrefState, GeckoPrefStore, PrefBranch,
@@ -253,73 +252,30 @@ impl NimbusClient {
253252
.ok_or(NimbusError::NoSuchExperiment(slug))
254253
}
255254

256-
pub fn get_experiment_participation(&self) -> Result<bool> {
257-
let db = self.db()?;
258-
let reader = db.read()?;
259-
get_experiment_participation(db, &reader)
260-
}
261-
262-
pub fn get_rollout_participation(&self) -> Result<bool> {
255+
pub fn get_global_user_participation(&self) -> Result<bool> {
263256
let db = self.db()?;
264257
let reader = db.read()?;
265-
get_rollout_participation(db, &reader)
258+
get_global_user_participation(db, &reader)
266259
}
267260

268-
pub fn set_experiment_participation(
269-
&self,
270-
user_participating: bool,
271-
) -> Result<Vec<EnrollmentChangeEvent>> {
272-
let db = self.db()?;
273-
let mut writer = db.write()?;
274-
let mut state = self.mutable_state.lock().unwrap();
275-
set_experiment_participation(db, &mut writer, user_participating)?;
276-
277-
let existing_experiments: Vec<Experiment> =
278-
db.get_store(StoreId::Experiments).collect_all(&writer)?;
279-
let events = self.evolve_experiments(db, &mut writer, &mut state, &existing_experiments)?;
280-
self.end_initialize(db, writer, &mut state)?;
281-
Ok(events)
282-
}
283-
284-
pub fn set_rollout_participation(
261+
pub fn set_global_user_participation(
285262
&self,
286263
user_participating: bool,
287264
) -> Result<Vec<EnrollmentChangeEvent>> {
288265
let db = self.db()?;
289266
let mut writer = db.write()?;
290267
let mut state = self.mutable_state.lock().unwrap();
291-
set_rollout_participation(db, &mut writer, user_participating)?;
268+
set_global_user_participation(db, &mut writer, user_participating)?;
292269

293270
let existing_experiments: Vec<Experiment> =
294271
db.get_store(StoreId::Experiments).collect_all(&writer)?;
272+
// We pass the existing experiments as "updated experiments"
273+
// to the evolver.
295274
let events = self.evolve_experiments(db, &mut writer, &mut state, &existing_experiments)?;
296275
self.end_initialize(db, writer, &mut state)?;
297276
Ok(events)
298277
}
299278

300-
// DEPRECATED: Will be removed once Firefox is using the
301-
// new get_experiment_participation and get_rollout_participation
302-
pub fn get_global_user_participation(&self) -> Result<bool> {
303-
// For simplicity, just return the experiment participation value
304-
self.get_experiment_participation()
305-
}
306-
307-
// DEPRECATED: Will be removed once Firefox is using the
308-
// new set_experiment_participation and set_rollout_participation
309-
pub fn set_global_user_participation(
310-
&self,
311-
user_participating: bool,
312-
) -> Result<Vec<EnrollmentChangeEvent>> {
313-
// Call both set_experiment_participation and set_rollout_participation with the same value
314-
let experiment_events = self.set_experiment_participation(user_participating)?;
315-
let rollout_events = self.set_rollout_participation(user_participating)?;
316-
317-
// Combine the events from both calls
318-
let mut all_events = experiment_events;
319-
all_events.extend(rollout_events);
320-
Ok(all_events)
321-
}
322-
323279
pub fn get_active_experiments(&self) -> Result<Vec<EnrolledExperiment>> {
324280
self.database_cache.get_active_experiments()
325281
}

0 commit comments

Comments
 (0)