From 6295fba9e2995efdaea7038becbc2ed4ab8d50e0 Mon Sep 17 00:00:00 2001 From: Beth Rennie Date: Wed, 18 Feb 2026 15:17:09 -0500 Subject: [PATCH] Bug 2018013 - Clean up Nimbus SDK imports --- components/nimbus/src/defaults.rs | 6 +- components/nimbus/src/enrollment.rs | 27 +++--- components/nimbus/src/error.rs | 4 +- components/nimbus/src/evaluator.rs | 23 +++-- components/nimbus/src/json.rs | 1 + components/nimbus/src/lib.rs | 21 +++-- components/nimbus/src/metrics.rs | 8 +- components/nimbus/src/sampling.rs | 3 +- components/nimbus/src/schema.rs | 12 ++- components/nimbus/src/stateful/behavior.rs | 14 +-- .../nimbus/src/stateful/client/fs_client.rs | 7 +- .../nimbus/src/stateful/client/http_client.rs | 5 +- components/nimbus/src/stateful/client/mod.rs | 10 ++- components/nimbus/src/stateful/dbcache.rs | 21 ++--- components/nimbus/src/stateful/enrollment.rs | 21 ++--- components/nimbus/src/stateful/evaluator.rs | 20 ++--- components/nimbus/src/stateful/gecko_prefs.rs | 16 ++-- .../nimbus/src/stateful/nimbus_client.rs | 90 +++++++++---------- components/nimbus/src/stateful/persistence.rs | 15 ++-- components/nimbus/src/stateful/targeting.rs | 15 ++-- .../nimbus/src/stateless/cirrus_client.rs | 27 +++--- components/nimbus/src/stateless/evaluator.rs | 9 +- components/nimbus/src/strings.rs | 3 +- components/nimbus/src/targeting.rs | 22 +++-- components/nimbus/src/tests/helpers.rs | 45 ++++++---- .../tests/stateful/client/test_null_client.rs | 3 +- .../nimbus/src/tests/stateful/helpers.rs | 3 - .../src/tests/stateful/test_evaluator.rs | 8 +- components/nimbus/src/tests/test_defaults.rs | 9 +- .../nimbus/src/tests/test_enrollment.rs | 46 ++++------ .../src/tests/test_enrollment_bw_compat.rs | 3 +- components/nimbus/src/tests/test_evaluator.rs | 11 +-- .../nimbus/src/tests/test_lib_bw_compat.rs | 1 + components/nimbus/src/tests/test_schema.rs | 3 +- 34 files changed, 270 insertions(+), 262 deletions(-) delete mode 100644 components/nimbus/src/tests/stateful/helpers.rs diff --git a/components/nimbus/src/defaults.rs b/components/nimbus/src/defaults.rs index 92cc23af84..77f43e23f1 100644 --- a/components/nimbus/src/defaults.rs +++ b/components/nimbus/src/defaults.rs @@ -2,6 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use std::collections::HashMap; + +use serde_json::{Map, Value}; + use crate::error::Result; /// Simple trait to allow merging of similar objects. @@ -34,7 +38,6 @@ impl Defaults for Option { } } -use serde_json::{Map, Value}; /// We implement https://datatracker.ietf.org/doc/html/rfc7396 /// such that self is patching the fallback. /// The result is the patched object. @@ -76,7 +79,6 @@ impl Defaults for Map { } } -use std::collections::HashMap; /// Merge the two `HashMap`s, with self acting as the dominant /// of the two. /// diff --git a/components/nimbus/src/enrollment.rs b/components/nimbus/src/enrollment.rs index d65dba1233..5e73f36906 100644 --- a/components/nimbus/src/enrollment.rs +++ b/components/nimbus/src/enrollment.rs @@ -1,21 +1,22 @@ // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. + +use std::collections::{HashMap, HashSet}; +use std::fmt::{self, Display}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use serde_derive::{Deserialize, Serialize}; + +use crate::defaults::Defaults; +use crate::error::{NimbusError, Result, debug, warn}; +use crate::evaluator::evaluate_enrollment; +use crate::json; #[cfg(feature = "stateful")] use crate::stateful::gecko_prefs::{GeckoPrefStore, OriginalGeckoPref, PrefUnenrollReason}; use crate::{ AvailableRandomizationUnits, Experiment, FeatureConfig, NimbusTargetingHelper, SLUG_REPLACEMENT_PATTERN, - defaults::Defaults, - error::{NimbusError, Result, debug, warn}, - evaluator::evaluate_enrollment, - json, -}; -use serde_derive::*; -use std::{ - collections::{HashMap, HashSet}, - fmt::{Display, Formatter, Result as FmtResult}, - time::{Duration, SystemTime, UNIX_EPOCH}, }; pub(crate) const PREVIOUS_ENROLLMENTS_GC_TIME: Duration = Duration::from_secs(365 * 24 * 3600); @@ -32,7 +33,7 @@ pub enum EnrolledReason { } impl Display for EnrolledReason { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Display::fmt( match self { EnrolledReason::Qualified => "Qualified", @@ -66,7 +67,7 @@ pub enum NotEnrolledReason { } impl Display for NotEnrolledReason { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Display::fmt( match self { NotEnrolledReason::DifferentAppName => "DifferentAppName", @@ -117,7 +118,7 @@ pub enum DisqualifiedReason { } impl Display for DisqualifiedReason { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Display::fmt( match self { DisqualifiedReason::Error => "Error", diff --git a/components/nimbus/src/error.rs b/components/nimbus/src/error.rs index 0ea8308919..5c7bc80079 100644 --- a/components/nimbus/src/error.rs +++ b/components/nimbus/src/error.rs @@ -8,12 +8,12 @@ //! TODO: Implement proper error handling, this would include defining the error enum, //! impl std::error::Error using `thiserror` and ensuring all errors are handled appropriately +use std::num::{ParseIntError, TryFromIntError}; + // reexport logging helpers. pub use error_support::{debug, error, info, trace, warn}; - #[cfg(feature = "stateful")] use firefox_versioning::error::VersionParsingError; -use std::num::{ParseIntError, TryFromIntError}; #[derive(Debug, thiserror::Error)] pub enum NimbusError { diff --git a/components/nimbus/src/evaluator.rs b/components/nimbus/src/evaluator.rs index d4571b8009..553830ef3c 100644 --- a/components/nimbus/src/evaluator.rs +++ b/components/nimbus/src/evaluator.rs @@ -3,22 +3,19 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use crate::{ - AvailableRandomizationUnits, Branch, Experiment, NimbusTargetingHelper, - enrollment::{EnrolledReason, EnrollmentStatus, ExperimentEnrollment, NotEnrolledReason}, - error::{NimbusError, Result, debug, info}, - sampling, -}; use serde_derive::*; use serde_json::Value; -cfg_if::cfg_if! { - if #[cfg(feature = "stateful")] { - pub use crate::stateful::evaluator::*; - } else { - pub use crate::stateless::evaluator::*; - } -} +use crate::enrollment::{ + EnrolledReason, EnrollmentStatus, ExperimentEnrollment, NotEnrolledReason, +}; +use crate::error::{NimbusError, Result, debug, info}; +use crate::sampling; +#[cfg(feature = "stateful")] +pub use crate::stateful::evaluator::*; +#[cfg(not(feature = "stateful"))] +pub use crate::stateless::evaluator::*; +use crate::{AvailableRandomizationUnits, Branch, Experiment, NimbusTargetingHelper}; #[derive(Serialize, Deserialize, Debug, Clone, Default)] pub struct Bucket {} diff --git a/components/nimbus/src/json.rs b/components/nimbus/src/json.rs index c802c4237b..94dd9a561f 100644 --- a/components/nimbus/src/json.rs +++ b/components/nimbus/src/json.rs @@ -3,6 +3,7 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. use serde_json::{Map, Value}; + use std::collections::HashMap; #[cfg(feature = "stateful")] diff --git a/components/nimbus/src/lib.rs b/components/nimbus/src/lib.rs index b693eba665..8c86e0cafa 100644 --- a/components/nimbus/src/lib.rs +++ b/components/nimbus/src/lib.rs @@ -2,8 +2,6 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -extern crate core; - mod defaults; mod enrollment; mod evaluator; @@ -16,26 +14,27 @@ pub mod error; pub mod metrics; pub mod schema; -pub use enrollment::{EnrolledFeature, EnrollmentStatus}; -pub use error::{NimbusError, Result}; +pub use crate::enrollment::{EnrolledFeature, EnrollmentStatus}; +pub use crate::error::{NimbusError, Result}; #[cfg(debug_assertions)] -pub use evaluator::evaluate_enrollment; -pub use schema::*; -pub use targeting::NimbusTargetingHelper; +pub use crate::evaluator::evaluate_enrollment; +pub use crate::schema::*; +pub use crate::targeting::NimbusTargetingHelper; cfg_if::cfg_if! { if #[cfg(feature = "stateful")] { pub mod stateful; - pub use stateful::nimbus_client::*; - pub use stateful::matcher::AppContext; pub use remote_settings::{RemoteSettingsConfig, RemoteSettingsServer}; + + pub use crate::stateful::nimbus_client::*; + pub use crate::stateful::matcher::AppContext; } else { pub mod stateless; - pub use stateless::cirrus_client::*; - pub use stateless::matcher::AppContext; + pub use crate::stateless::cirrus_client::*; + pub use crate::stateless::matcher::AppContext; } } diff --git a/components/nimbus/src/metrics.rs b/components/nimbus/src/metrics.rs index b17d09450d..a7333caa26 100644 --- a/components/nimbus/src/metrics.rs +++ b/components/nimbus/src/metrics.rs @@ -2,12 +2,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use serde_derive::{Deserialize, Serialize}; + +use crate::enrollment::ExperimentEnrollment; +use crate::{EnrolledFeature, EnrollmentStatus}; + #[cfg(feature = "stateful")] use crate::enrollment::PreviousGeckoPrefState; -use crate::{EnrolledFeature, EnrollmentStatus, enrollment::ExperimentEnrollment}; -use serde_derive::{Deserialize, Serialize}; - pub trait MetricsHandler: Send + Sync { #[cfg(feature = "stateful")] fn record_enrollment_statuses(&self, enrollment_status_extras: Vec); diff --git a/components/nimbus/src/sampling.rs b/components/nimbus/src/sampling.rs index a65d081cee..0e3a43b6d9 100644 --- a/components/nimbus/src/sampling.rs +++ b/components/nimbus/src/sampling.rs @@ -5,9 +5,10 @@ //! This module implements the sampling logic required to hash, //! randomize and pick branches using pre-set ratios. -use crate::error::{NimbusError, Result}; use sha2::{Digest, Sha256}; +use crate::error::{NimbusError, Result}; + const HASH_BITS: u32 = 48; const HASH_LENGTH: u32 = HASH_BITS / 4; diff --git a/components/nimbus/src/schema.rs b/components/nimbus/src/schema.rs index 9c211a28c3..7065004024 100644 --- a/components/nimbus/src/schema.rs +++ b/components/nimbus/src/schema.rs @@ -2,13 +2,17 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -use crate::error::{trace, warn}; -use crate::{NimbusError, Result, defaults::Defaults, enrollment::ExperimentMetadata}; -use serde_derive::*; -use serde_json::{Map, Value}; use std::collections::HashSet; + +use serde_derive::{Deserialize, Serialize}; +use serde_json::{Map, Value}; use uuid::Uuid; +use crate::defaults::Defaults; +use crate::enrollment::ExperimentMetadata; +use crate::error::{trace, warn}; +use crate::{NimbusError, Result}; + const DEFAULT_TOTAL_BUCKETS: u32 = 10000; #[derive(Debug, Clone)] diff --git a/components/nimbus/src/stateful/behavior.rs b/components/nimbus/src/stateful/behavior.rs index 472a0f870c..11cbd6b2b7 100644 --- a/components/nimbus/src/stateful/behavior.rs +++ b/components/nimbus/src/stateful/behavior.rs @@ -2,13 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::{ - error::{BehaviorError, NimbusError, Result}, - stateful::persistence::{Database, StoreId}, -}; -use chrono::{DateTime, Datelike, Duration, TimeZone, Utc}; -use serde::{Deserialize, Serialize}; -use serde_json::{Value, json}; use std::collections::vec_deque::Iter; use std::collections::{HashMap, VecDeque}; use std::fmt; @@ -16,6 +9,13 @@ use std::hash::{Hash, Hasher}; use std::str::FromStr; use std::sync::{Arc, Mutex}; +use chrono::{DateTime, Datelike, Duration, TimeZone, Utc}; +use serde::{Deserialize, Serialize}; +use serde_json::{Value, json}; + +use crate::error::{BehaviorError, NimbusError, Result}; +use crate::stateful::persistence::{Database, StoreId}; + #[derive(Clone, Debug, Serialize, Deserialize)] pub enum Interval { Minutes, diff --git a/components/nimbus/src/stateful/client/fs_client.rs b/components/nimbus/src/stateful/client/fs_client.rs index 4cfdb9d173..a96f553d26 100644 --- a/components/nimbus/src/stateful/client/fs_client.rs +++ b/components/nimbus/src/stateful/client/fs_client.rs @@ -6,14 +6,15 @@ //! (eg, for testing against experiments which are not deployed anywhere) and //! for tests. -use crate::Experiment; -use crate::error::{Result, info, warn}; -use crate::stateful::client::SettingsClient; use std::ffi::OsStr; use std::fs::File; use std::io::BufReader; use std::path::{Path, PathBuf}; +use crate::Experiment; +use crate::error::{Result, info, warn}; +use crate::stateful::client::SettingsClient; + pub struct FileSystemClient { path: PathBuf, } diff --git a/components/nimbus/src/stateful/client/http_client.rs b/components/nimbus/src/stateful/client/http_client.rs index 0362473801..474527650f 100644 --- a/components/nimbus/src/stateful/client/http_client.rs +++ b/components/nimbus/src/stateful/client/http_client.rs @@ -15,12 +15,13 @@ use std::sync::Arc; +use remote_settings::{RemoteSettingsClient, RemoteSettingsError}; +use serde_json::json; + use crate::NimbusError; use crate::error::Result; use crate::schema::parse_experiments; use crate::stateful::client::{Experiment, SettingsClient}; -use remote_settings::{RemoteSettingsClient, RemoteSettingsError}; -use serde_json::json; impl SettingsClient for Arc { fn get_experiments_metadata(&self) -> Result { diff --git a/components/nimbus/src/stateful/client/mod.rs b/components/nimbus/src/stateful/client/mod.rs index 023af3eebe..b370b9b751 100644 --- a/components/nimbus/src/stateful/client/mod.rs +++ b/components/nimbus/src/stateful/client/mod.rs @@ -5,15 +5,17 @@ mod fs_client; pub(crate) mod http_client; pub(crate) mod null_client; + use std::sync::Arc; -use crate::Experiment; -use crate::error::{NimbusError, Result}; -use fs_client::FileSystemClient; -use null_client::NullClient; use remote_settings::RemoteSettingsService; use url::Url; +use crate::Experiment; +use crate::error::{NimbusError, Result}; +use crate::stateful::client::fs_client::FileSystemClient; +use crate::stateful::client::null_client::NullClient; + pub struct NimbusServerSettings { pub rs_service: Arc, pub collection_name: String, diff --git a/components/nimbus/src/stateful/dbcache.rs b/components/nimbus/src/stateful/dbcache.rs index c63f90dc4d..f63b744cfa 100644 --- a/components/nimbus/src/stateful/dbcache.rs +++ b/components/nimbus/src/stateful/dbcache.rs @@ -2,21 +2,18 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::{ - EnrolledExperiment, Experiment, - enrollment::{ - EnrolledFeature, EnrolledFeatureConfig, ExperimentEnrollment, map_features_by_feature_id, - }, - error::{NimbusError, Result, warn}, - stateful::{ - enrollment::get_enrollments, - gecko_prefs::GeckoPrefStore, - persistence::{Database, StoreId, Writer}, - }, -}; use std::collections::{HashMap, HashSet}; use std::sync::{Arc, RwLock}; +use crate::enrollment::{ + EnrolledFeature, EnrolledFeatureConfig, ExperimentEnrollment, map_features_by_feature_id, +}; +use crate::error::{NimbusError, Result, warn}; +use crate::stateful::enrollment::get_enrollments; +use crate::stateful::gecko_prefs::GeckoPrefStore; +use crate::stateful::persistence::{Database, StoreId, Writer}; +use crate::{EnrolledExperiment, Experiment}; + // This module manages an in-memory cache of the database, so that some // functions exposed by nimbus can return results without blocking on any // IO. Consumers are expected to call our public `update()` function whenever diff --git a/components/nimbus/src/stateful/enrollment.rs b/components/nimbus/src/stateful/enrollment.rs index f70d961e8f..a72c90217d 100644 --- a/components/nimbus/src/stateful/enrollment.rs +++ b/components/nimbus/src/stateful/enrollment.rs @@ -1,24 +1,21 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + use crate::enrollment::Participation; +use crate::enrollment::{ + EnrollmentChangeEvent, EnrollmentChangeEventType, EnrollmentsEvolver, ExperimentEnrollment, + map_enrollments, +}; +use crate::error::{Result, debug, warn}; use crate::stateful::gecko_prefs::GeckoPrefStore; +use crate::stateful::gecko_prefs::PrefUnenrollReason; use crate::stateful::persistence::{ DB_KEY_EXPERIMENT_PARTICIPATION, DB_KEY_ROLLOUT_PARTICIPATION, DEFAULT_EXPERIMENT_PARTICIPATION, DEFAULT_ROLLOUT_PARTICIPATION, }; -use crate::{ - EnrolledExperiment, EnrollmentStatus, Experiment, - enrollment::{ - EnrollmentChangeEvent, EnrollmentChangeEventType, EnrollmentsEvolver, ExperimentEnrollment, - map_enrollments, - }, - error::{Result, debug, warn}, - stateful::{ - gecko_prefs::PrefUnenrollReason, - persistence::{Database, Readable, StoreId, Writer}, - }, -}; +use crate::stateful::persistence::{Database, Readable, StoreId, Writer}; +use crate::{EnrolledExperiment, EnrollmentStatus, Experiment}; impl EnrollmentsEvolver<'_> { /// Convenient wrapper around `evolve_enrollments` that fetches the current state of experiments, diff --git a/components/nimbus/src/stateful/evaluator.rs b/components/nimbus/src/stateful/evaluator.rs index 6106f40eef..4de95c91f3 100644 --- a/components/nimbus/src/stateful/evaluator.rs +++ b/components/nimbus/src/stateful/evaluator.rs @@ -2,18 +2,18 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::stateful::persistence::{Database, StoreId}; -use crate::{ - DB_KEY_UPDATE_DATE, - enrollment::{EnrollmentStatus, ExperimentEnrollment}, - error::{Result, warn}, - evaluator::split_locale, - json::JsonObject, - stateful::matcher::AppContext, -}; +use std::collections::{HashMap, HashSet}; + use chrono::{DateTime, NaiveDateTime, Utc}; use serde_derive::*; -use std::collections::{HashMap, HashSet}; + +use crate::DB_KEY_UPDATE_DATE; +use crate::enrollment::{EnrollmentStatus, ExperimentEnrollment}; +use crate::error::{Result, warn}; +use crate::evaluator::split_locale; +use crate::json::JsonObject; +use crate::stateful::matcher::AppContext; +use crate::stateful::persistence::{Database, StoreId}; #[derive(Serialize, Deserialize, Debug, Clone, Default)] pub struct TargetingAttributes { diff --git a/components/nimbus/src/stateful/gecko_prefs.rs b/components/nimbus/src/stateful/gecko_prefs.rs index af3056c904..5824823e12 100644 --- a/components/nimbus/src/stateful/gecko_prefs.rs +++ b/components/nimbus/src/stateful/gecko_prefs.rs @@ -1,19 +1,19 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::{ - EnrolledExperiment, Experiment, NimbusError, - enrollment::{EnrollmentStatus, ExperimentEnrollment, PreviousGeckoPrefState}, - error::Result, - json::PrefValue, -}; -use serde_derive::{Deserialize, Serialize}; -use serde_json::Value; use std::cmp::Ordering; use std::collections::{HashMap, HashSet}; use std::fmt::{Display, Formatter}; use std::sync::{Arc, Mutex, MutexGuard}; +use serde_derive::{Deserialize, Serialize}; +use serde_json::Value; + +use crate::enrollment::{EnrollmentStatus, ExperimentEnrollment, PreviousGeckoPrefState}; +use crate::error::Result; +use crate::json::PrefValue; +use crate::{EnrolledExperiment, Experiment, NimbusError}; + #[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq, Copy)] #[serde(rename_all = "lowercase")] pub enum PrefBranch { diff --git a/components/nimbus/src/stateful/nimbus_client.rs b/components/nimbus/src/stateful/nimbus_client.rs index 5826a6b146..7df00f9ff5 100644 --- a/components/nimbus/src/stateful/nimbus_client.rs +++ b/components/nimbus/src/stateful/nimbus_client.rs @@ -2,57 +2,57 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -#[cfg(test)] -use crate::tests::helpers::{TestGeckoPrefHandler, TestMetrics, TestRecordedContext}; -use crate::{ - AvailableExperiment, AvailableRandomizationUnits, EnrolledExperiment, EnrollmentStatus, - Experiment, ExperimentBranch, NimbusError, NimbusTargetingHelper, Result, - defaults::Defaults, - enrollment::{ - EnrolledFeature, EnrollmentChangeEvent, EnrollmentChangeEventType, EnrollmentsEvolver, - ExperimentEnrollment, PreviousGeckoPrefState, - }, - error::{BehaviorError, info}, - evaluator::{ - CalculatedAttributes, ExperimentAvailable, TargetingAttributes, get_calculated_attributes, - is_experiment_available, - }, - json::{JsonObject, PrefValue}, - metrics::{ - EnrollmentStatusExtraDef, FeatureExposureExtraDef, MalformedFeatureConfigExtraDef, - MetricsHandler, - }, - schema::parse_experiments, - stateful::{ - behavior::EventStore, - client::{NimbusServerSettings, SettingsClient, create_client}, - dbcache::DatabaseCache, - enrollment::{ - get_experiment_participation, get_rollout_participation, opt_in_with_branch, opt_out, - reset_telemetry_identifiers, set_experiment_participation, set_rollout_participation, - unenroll_for_pref, - }, - gecko_prefs::{ - GeckoPref, GeckoPrefHandler, GeckoPrefState, GeckoPrefStore, OriginalGeckoPref, - PrefBranch, PrefEnrollmentData, PrefUnenrollReason, - }, - matcher::AppContext, - persistence::{Database, StoreId, Writer}, - targeting::{RecordedContext, validate_event_queries}, - updating::{read_and_remove_pending_experiments, write_pending_experiments}, - }, - strings::fmt_with_map, -}; -use chrono::{DateTime, NaiveDateTime, Utc}; -use once_cell::sync::OnceCell; -use remote_settings::RemoteSettingsService; -use serde_json::Value; use std::collections::HashSet; use std::fmt::Debug; use std::path::PathBuf; use std::sync::{Arc, Mutex, MutexGuard}; + +use chrono::{DateTime, NaiveDateTime, Utc}; +use once_cell::sync::OnceCell; +use remote_settings::RemoteSettingsService; +use serde_json::Value; use uuid::Uuid; +use crate::defaults::Defaults; +use crate::enrollment::{ + EnrolledFeature, EnrollmentChangeEvent, EnrollmentChangeEventType, EnrollmentsEvolver, + ExperimentEnrollment, PreviousGeckoPrefState, +}; +use crate::error::{BehaviorError, info}; +use crate::evaluator::{ + CalculatedAttributes, ExperimentAvailable, TargetingAttributes, get_calculated_attributes, + is_experiment_available, +}; +use crate::json::{JsonObject, PrefValue}; +use crate::metrics::{ + EnrollmentStatusExtraDef, FeatureExposureExtraDef, MalformedFeatureConfigExtraDef, + MetricsHandler, +}; +use crate::schema::parse_experiments; +use crate::stateful::behavior::EventStore; +use crate::stateful::client::{NimbusServerSettings, SettingsClient, create_client}; +use crate::stateful::dbcache::DatabaseCache; +use crate::stateful::enrollment::{ + get_experiment_participation, get_rollout_participation, opt_in_with_branch, opt_out, + reset_telemetry_identifiers, set_experiment_participation, set_rollout_participation, + unenroll_for_pref, +}; +use crate::stateful::gecko_prefs::{ + GeckoPref, GeckoPrefHandler, GeckoPrefState, GeckoPrefStore, OriginalGeckoPref, PrefBranch, + PrefEnrollmentData, PrefUnenrollReason, +}; +use crate::stateful::matcher::AppContext; +use crate::stateful::persistence::{Database, StoreId, Writer}; +use crate::stateful::targeting::{RecordedContext, validate_event_queries}; +use crate::stateful::updating::{read_and_remove_pending_experiments, write_pending_experiments}; +use crate::strings::fmt_with_map; +#[cfg(test)] +use crate::tests::helpers::{TestGeckoPrefHandler, TestMetrics, TestRecordedContext}; +use crate::{ + AvailableExperiment, AvailableRandomizationUnits, EnrolledExperiment, EnrollmentStatus, +}; +use crate::{Experiment, ExperimentBranch, NimbusError, NimbusTargetingHelper, Result}; + const DB_KEY_NIMBUS_ID: &str = "nimbus-id"; pub const DB_KEY_INSTALLATION_DATE: &str = "installation-date"; pub const DB_KEY_UPDATE_DATE: &str = "update-date"; diff --git a/components/nimbus/src/stateful/persistence.rs b/components/nimbus/src/stateful/persistence.rs index a993cf9e7f..2fe497cdf1 100644 --- a/components/nimbus/src/stateful/persistence.rs +++ b/components/nimbus/src/stateful/persistence.rs @@ -4,19 +4,20 @@ //! Our storage abstraction, currently backed by Rkv. +use rkv::{StoreError, StoreOptions}; +use std::collections::HashSet; +use std::fs; +use std::path::Path; + +use crate::Experiment; +use crate::enrollment::ExperimentEnrollment; use crate::error::{NimbusError, Result, debug, info, warn}; + // This uses the lmdb backend for rkv, which is unstable. // We use it for now since glean didn't seem to have trouble with it (although // it must be noted that the rkv documentation explicitly says "To use rkv in // production/release environments at Mozilla, you may do so with the "SafeMode" // backend", so we really should get more guidance here.) -use crate::Experiment; -use crate::enrollment::ExperimentEnrollment; -use core::iter::Iterator; -use rkv::{StoreError, StoreOptions}; -use std::collections::HashSet; -use std::fs; -use std::path::Path; // We use an incrementing integer to manage database migrations. // If you need to make a backwards-incompatible change to the data schema, diff --git a/components/nimbus/src/stateful/targeting.rs b/components/nimbus/src/stateful/targeting.rs index 7bff950254..dfa805e076 100644 --- a/components/nimbus/src/stateful/targeting.rs +++ b/components/nimbus/src/stateful/targeting.rs @@ -2,17 +2,16 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -use crate::stateful::gecko_prefs::GeckoPrefStore; -use crate::{ - NimbusError, NimbusTargetingHelper, Result, TargetingAttributes, - enrollment::ExperimentEnrollment, - error::{BehaviorError, warn}, - json::JsonObject, - stateful::behavior::{EventQueryType, EventStore}, -}; use std::collections::HashMap; use std::sync::{Arc, Mutex}; +use crate::enrollment::ExperimentEnrollment; +use crate::error::{BehaviorError, warn}; +use crate::json::JsonObject; +use crate::stateful::behavior::{EventQueryType, EventStore}; +use crate::stateful::gecko_prefs::GeckoPrefStore; +use crate::{NimbusError, NimbusTargetingHelper, Result, TargetingAttributes}; + impl NimbusTargetingHelper { pub(crate) fn with_targeting_attributes( targeting_attributes: &TargetingAttributes, diff --git a/components/nimbus/src/stateless/cirrus_client.rs b/components/nimbus/src/stateless/cirrus_client.rs index 4de1a88337..808efd4a4e 100644 --- a/components/nimbus/src/stateless/cirrus_client.rs +++ b/components/nimbus/src/stateless/cirrus_client.rs @@ -2,23 +2,24 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::{ - AppContext, AvailableRandomizationUnits, Experiment, NimbusError, NimbusTargetingHelper, - Result, TargetingAttributes, - enrollment::{ - EnrolledFeatureConfig, EnrollmentChangeEvent, EnrollmentsEvolver, ExperimentEnrollment, - map_features_by_feature_id, - }, - error::CirrusClientError, - metrics::{EnrollmentStatusExtraDef, MetricsHandler}, - parse_experiments, -}; -use serde_derive::*; -use serde_json::{Map, Value}; use std::collections::HashMap; use std::fmt; use std::sync::{Arc, Mutex}; +use serde_derive::{Deserialize, Serialize}; +use serde_json::{Map, Value}; + +use crate::enrollment::{ + EnrolledFeatureConfig, EnrollmentChangeEvent, EnrollmentsEvolver, ExperimentEnrollment, + map_features_by_feature_id, +}; +use crate::error::CirrusClientError; +use crate::metrics::{EnrollmentStatusExtraDef, MetricsHandler}; +use crate::{ + AppContext, AvailableRandomizationUnits, Experiment, NimbusError, NimbusTargetingHelper, + Result, TargetingAttributes, parse_experiments, +}; + /// EnrollmentResponse is a DTO for the response from handling enrollment for a given client. /// /// Definitions for the fields are as follows: diff --git a/components/nimbus/src/stateless/evaluator.rs b/components/nimbus/src/stateless/evaluator.rs index 52a784e7ec..7c74f785f2 100644 --- a/components/nimbus/src/stateless/evaluator.rs +++ b/components/nimbus/src/stateless/evaluator.rs @@ -2,10 +2,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::{evaluator::split_locale, stateless::matcher::AppContext}; -use serde_derive::*; -use serde_json::Map; -use serde_json::Value; +use serde_derive::{Deserialize, Serialize}; +use serde_json::{Map, Value}; + +use crate::evaluator::split_locale; +use crate::stateless::matcher::AppContext; #[derive(Serialize, Deserialize, Debug, Clone, Default)] pub struct TargetingAttributes { diff --git a/components/nimbus/src/strings.rs b/components/nimbus/src/strings.rs index 5ae81a80a0..f723f5670c 100644 --- a/components/nimbus/src/strings.rs +++ b/components/nimbus/src/strings.rs @@ -2,10 +2,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::{NimbusError, Result}; use icu_segmenter::GraphemeClusterSegmenter; use serde_json::{Map, value::Value}; +use crate::{NimbusError, Result}; + #[allow(dead_code)] pub fn fmt(template: &str, context: &T) -> Result { let obj: Value = match serde_json::to_value(context) { diff --git a/components/nimbus/src/targeting.rs b/components/nimbus/src/targeting.rs index f3533a2ffa..107c038e3d 100644 --- a/components/nimbus/src/targeting.rs +++ b/components/nimbus/src/targeting.rs @@ -2,20 +2,24 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -use crate::{NimbusError, Result}; +#[cfg(feature = "stateful")] +use std::sync::{Arc, Mutex}; +#[cfg(feature = "stateful")] +use anyhow::anyhow; +#[cfg(feature = "stateful")] +use firefox_versioning::compare::version_compare; use jexl_eval::Evaluator; use serde::Serialize; use serde_json::Value; -cfg_if::cfg_if! { - if #[cfg(feature = "stateful")] { - use anyhow::anyhow; - use crate::{TargetingAttributes, stateful::{behavior::{EventStore, EventQueryType, query_event_store}, gecko_prefs::{GeckoPrefStore, query_gecko_pref_store}}}; - use std::sync::{Arc, Mutex}; - use firefox_versioning::compare::version_compare; - } -} +#[cfg(feature = "stateful")] +use crate::TargetingAttributes; +#[cfg(feature = "stateful")] +use crate::stateful::behavior::{EventQueryType, EventStore, query_event_store}; +#[cfg(feature = "stateful")] +use crate::stateful::gecko_prefs::{GeckoPrefStore, query_gecko_pref_store}; +use crate::{NimbusError, Result}; #[derive(Clone)] pub struct NimbusTargetingHelper { diff --git a/components/nimbus/src/tests/helpers.rs b/components/nimbus/src/tests/helpers.rs index 03d6facfda..56e120c8bf 100644 --- a/components/nimbus/src/tests/helpers.rs +++ b/components/nimbus/src/tests/helpers.rs @@ -4,32 +4,39 @@ #![allow(unexpected_cfgs)] +#[cfg(feature = "stateful")] +use std::collections::HashMap; +use std::collections::HashSet; +use std::sync::{Arc, Mutex}; + +use serde::Serialize; +#[cfg(feature = "stateful")] +use serde_json::Map; +use serde_json::{Value, json}; + +use crate::enrollment::{ + EnrolledFeatureConfig, EnrolledReason, ExperimentEnrollment, NotEnrolledReason, +}; +#[cfg(feature = "stateful")] +use crate::json::JsonObject; +use crate::metrics::{EnrollmentStatusExtraDef, MetricsHandler}; +#[cfg(feature = "stateful")] +use crate::metrics::{FeatureExposureExtraDef, MalformedFeatureConfigExtraDef}; +#[cfg(feature = "stateful")] +use crate::stateful::behavior::EventStore; #[cfg(feature = "stateful")] use crate::stateful::gecko_prefs::OriginalGeckoPref; +#[cfg(feature = "stateful")] +use crate::stateful::gecko_prefs::{ + GeckoPrefHandler, GeckoPrefState, MapOfFeatureIdToPropertyNameToGeckoPrefState, +}; +#[cfg(feature = "stateful")] +use crate::stateful::targeting::RecordedContext; use crate::{ AppContext, EnrollmentStatus, Experiment, FeatureConfig, NimbusTargetingHelper, TargetingAttributes, - enrollment::{EnrolledFeatureConfig, EnrolledReason, ExperimentEnrollment, NotEnrolledReason}, - metrics::{EnrollmentStatusExtraDef, MetricsHandler}, }; -cfg_if::cfg_if! { - if #[cfg(feature = "stateful")] { - use crate::{ - metrics::{FeatureExposureExtraDef, MalformedFeatureConfigExtraDef}, - json::JsonObject, - stateful::{behavior::EventStore, gecko_prefs::{GeckoPrefHandler, GeckoPrefState, MapOfFeatureIdToPropertyNameToGeckoPrefState}, targeting::RecordedContext} - }; - use std::collections::HashMap; - use serde_json::Map; - } -} - -use serde::Serialize; -use serde_json::{Value, json}; -use std::collections::HashSet; -use std::sync::{Arc, Mutex}; - #[ctor::ctor] fn init() { error_support::init_for_tests_with_level(error_support::Level::Info); diff --git a/components/nimbus/src/tests/stateful/client/test_null_client.rs b/components/nimbus/src/tests/stateful/client/test_null_client.rs index 0072df677f..c4aaa45dbd 100644 --- a/components/nimbus/src/tests/stateful/client/test_null_client.rs +++ b/components/nimbus/src/tests/stateful/client/test_null_client.rs @@ -5,14 +5,13 @@ // Allow this to run in "safe mode" #![allow(unused_imports)] +use crate::NimbusClient; use crate::error::Result; use crate::tests::helpers::TestMetrics; #[cfg(feature = "rkv-safe-mode")] #[test] fn test_null_client() -> Result<()> { - use crate::NimbusClient; - let metrics = TestMetrics::new(); error_support::init_for_tests(); diff --git a/components/nimbus/src/tests/stateful/helpers.rs b/components/nimbus/src/tests/stateful/helpers.rs deleted file mode 100644 index 7137d02bf2..0000000000 --- a/components/nimbus/src/tests/stateful/helpers.rs +++ /dev/null @@ -1,3 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public -* License, v. 2.0. If a copy of the MPL was not distributed with this -* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ diff --git a/components/nimbus/src/tests/stateful/test_evaluator.rs b/components/nimbus/src/tests/stateful/test_evaluator.rs index 9b83ec63b0..cdd4418c36 100644 --- a/components/nimbus/src/tests/stateful/test_evaluator.rs +++ b/components/nimbus/src/tests/stateful/test_evaluator.rs @@ -388,13 +388,7 @@ fn test_targeting_is_already_enrolled() { custom_targeting_attributes: None, ..Default::default() }; - cfg_if::cfg_if! { - if #[cfg(feature = "stateful")] { - let mut targeting_attributes = TargetingAttributes::from(ac); - } else { - let mut targeting_attributes = TargetingAttributes::new(ac, Default::default()); - } - } + let mut targeting_attributes = TargetingAttributes::from(ac); targeting_attributes.is_already_enrolled = true; // The targeting should pass! diff --git a/components/nimbus/src/tests/test_defaults.rs b/components/nimbus/src/tests/test_defaults.rs index aac0f57f86..355e6e49dd 100644 --- a/components/nimbus/src/tests/test_defaults.rs +++ b/components/nimbus/src/tests/test_defaults.rs @@ -4,15 +4,18 @@ // cargo test --package nimbus-sdk --lib --all-features -- tests::test_defaults --nocapture -use crate::{NimbusError::InternalError, defaults::Defaults, error::Result}; -use serde_json::{Value, json}; use std::collections::HashMap; +use serde_json::{Value, json}; + +use crate::defaults::Defaults; +use crate::error::{NimbusError, Result}; + #[cfg(test)] impl Defaults for &str { fn defaults(&self, fb: &Self) -> Result { if self.starts_with("err") || fb.starts_with("err") { - Err(InternalError("OMG Error")) + Err(NimbusError::InternalError("OMG Error")) } else { Ok(self) } diff --git a/components/nimbus/src/tests/test_enrollment.rs b/components/nimbus/src/tests/test_enrollment.rs index 3ef6c3d88e..92888177bb 100644 --- a/components/nimbus/src/tests/test_enrollment.rs +++ b/components/nimbus/src/tests/test_enrollment.rs @@ -4,39 +4,31 @@ // Testing enrollment.rs #[cfg(feature = "stateful")] -use crate::stateful::gecko_prefs::{OriginalGeckoPref, PrefBranch}; -use crate::tests::helpers::{get_bucketed_rollout, get_experiment_with_published_date}; -use crate::{ - AppContext, AvailableRandomizationUnits, Branch, BucketConfig, Experiment, FeatureConfig, - NimbusTargetingHelper, TargetingAttributes, - defaults::Defaults, - enrollment::*, - error::{Result, debug}, - tests::helpers::{ - get_multi_feature_experiment, get_single_feature_experiment, get_test_experiments, - no_coenrolling_features, - }, -}; -#[cfg(feature = "stateful")] -use crate::{ - stateful::gecko_prefs::{ - GeckoPrefHandler, GeckoPrefState, GeckoPrefStore, create_feature_prop_pref_map, - }, - tests::helpers::TestGeckoPrefHandler, -}; -#[cfg(feature = "stateful")] use std::sync::Arc; -cfg_if::cfg_if! { - if #[cfg(feature = "stateful")] { - use crate::tests::helpers::get_ios_rollout_experiment; - - } -} use serde_json::{Value, json}; use std::collections::{HashMap, HashSet}; use uuid::Uuid; +use crate::defaults::Defaults; +use crate::enrollment::*; +use crate::error::{Result, debug}; +#[cfg(feature = "stateful")] +use crate::stateful::gecko_prefs::{ + GeckoPrefHandler, GeckoPrefState, GeckoPrefStore, OriginalGeckoPref, PrefBranch, + create_feature_prop_pref_map, +}; +#[cfg(feature = "stateful")] +use crate::tests::helpers::{TestGeckoPrefHandler, get_ios_rollout_experiment}; +use crate::tests::helpers::{ + get_bucketed_rollout, get_experiment_with_published_date, get_multi_feature_experiment, + get_single_feature_experiment, get_test_experiments, no_coenrolling_features, +}; +use crate::{ + AppContext, AvailableRandomizationUnits, Branch, BucketConfig, Experiment, FeatureConfig, + NimbusTargetingHelper, TargetingAttributes, +}; + impl From for NimbusTargetingHelper { fn from(context: AppContext) -> Self { cfg_if::cfg_if! { diff --git a/components/nimbus/src/tests/test_enrollment_bw_compat.rs b/components/nimbus/src/tests/test_enrollment_bw_compat.rs index f1c04e58d9..fd70cc818b 100644 --- a/components/nimbus/src/tests/test_enrollment_bw_compat.rs +++ b/components/nimbus/src/tests/test_enrollment_bw_compat.rs @@ -2,9 +2,10 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -use crate::enrollment::*; use serde_json::json; +use crate::enrollment::*; + /// A suite of tests for b/w compat of data storage schema. /// /// We use the `Serialize/`Deserialize` impls on various structs in order to persist them diff --git a/components/nimbus/src/tests/test_evaluator.rs b/components/nimbus/src/tests/test_evaluator.rs index 6d94b7ddef..58fb18b8a6 100644 --- a/components/nimbus/src/tests/test_evaluator.rs +++ b/components/nimbus/src/tests/test_evaluator.rs @@ -1,16 +1,17 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + #![cfg_attr(not(feature = "stateful"), allow(clippy::needless_update))] +use serde_json::{Map, Value, json}; + +use crate::enrollment::{EnrolledReason, EnrollmentStatus, NotEnrolledReason}; +use crate::evaluator::{ExperimentAvailable, choose_branch, is_experiment_available, targeting}; use crate::{ AppContext, AvailableRandomizationUnits, Branch, BucketConfig, Experiment, RandomizationUnit, - Result, TargetingAttributes, - enrollment::{EnrolledReason, EnrollmentStatus, NotEnrolledReason}, - evaluate_enrollment, - evaluator::{ExperimentAvailable, choose_branch, is_experiment_available, targeting}, + Result, TargetingAttributes, evaluate_enrollment, }; -use serde_json::{Map, Value, json}; pub fn ta_with_locale(locale: String) -> TargetingAttributes { let app_ctx = AppContext { diff --git a/components/nimbus/src/tests/test_lib_bw_compat.rs b/components/nimbus/src/tests/test_lib_bw_compat.rs index f5aa2acf04..af93a27307 100644 --- a/components/nimbus/src/tests/test_lib_bw_compat.rs +++ b/components/nimbus/src/tests/test_lib_bw_compat.rs @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::{Branch, Experiment, FeatureConfig}; + /// A suite of tests for b/w compat of data storage schema. /// /// We use the `Serialize/`Deserialize` impls on various structs in order to persist them diff --git a/components/nimbus/src/tests/test_schema.rs b/components/nimbus/src/tests/test_schema.rs index 248b8f52fa..586700896d 100644 --- a/components/nimbus/src/tests/test_schema.rs +++ b/components/nimbus/src/tests/test_schema.rs @@ -2,9 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::{FeatureConfig, error::Result}; use serde_json::json; +use crate::{FeatureConfig, error::Result}; + #[test] fn test_deserialize_untyped_json() -> Result<()> { let without_value = serde_json::from_value::(json!(