@@ -286,7 +286,7 @@ open class Nimbus(
286286 @VisibleForTesting(otherwise = VisibleForTesting .PRIVATE )
287287 internal fun initializeOnThisThread () = withCatchAll(" initialize" ) {
288288 nimbusClient.initialize()
289- postEnrolmentCalculation(initial = true )
289+ postEnrolmentCalculation(emptyList(), initial = true )
290290 }
291291
292292 override fun fetchExperiments () {
@@ -333,33 +333,31 @@ open class Nimbus(
333333 }
334334 }
335335
336- override fun applyPendingExperiments (): Job =
336+ override fun applyPendingExperiments (initial : Boolean ): Job =
337337 dbScope.launch {
338338 withContext(NonCancellable ) {
339- applyPendingExperimentsOnThisThread()
339+ applyPendingExperimentsOnThisThread(initial )
340340 }
341341 }
342342
343343 @WorkerThread
344344 @VisibleForTesting(otherwise = VisibleForTesting .PRIVATE )
345- internal fun applyPendingExperimentsOnThisThread () = withCatchAll(" applyPendingExperiments" ) {
346- try {
347- var events: List <EnrollmentChangeEvent >?
348- val time = measureTimeMillis {
349- events = nimbusClient.applyPendingExperiments()
345+ internal fun applyPendingExperimentsOnThisThread (initial : Boolean = false) {
346+ withCatchAll(" applyPendingExperiments" ) {
347+ try {
348+ var enrollmentChangeEvents: List <EnrollmentChangeEvent >?
349+ val time = measureTimeMillis {
350+ enrollmentChangeEvents = nimbusClient.applyPendingExperiments()
351+ }
352+ NimbusHealth .applyPendingExperimentsTime.accumulateSingleSample(time)
353+
354+ // SAFETY: events is only null at declaration time and is
355+ // immediately assigned a non-null value inside the
356+ // measureTimeMillis lambda.
357+ postEnrolmentCalculation(enrollmentChangeEvents!! , initial)
358+ } catch (e: NimbusException .InvalidExperimentFormat ) {
359+ reportError(" Invalid experiment format" , e)
350360 }
351- NimbusHealth .applyPendingExperimentsTime.accumulateSingleSample(time)
352-
353- // SAFETY: events is only null at declaration time and is
354- // immediately assigned a non-null value inside the
355- // measureTimeMillis lambda.
356- recordExperimentTelemetryEvents(events!! )
357-
358- // Get the experiments to record in telemetry
359- postEnrolmentCalculation()
360- updateDispatcher.notifyChanged(events)
361- } catch (e: NimbusException .InvalidExperimentFormat ) {
362- reportError(" Invalid experiment format" , e)
363361 }
364362 }
365363
@@ -395,31 +393,52 @@ open class Nimbus(
395393 withContext(NonCancellable ) {
396394 if (experimentsJson != null ) {
397395 setExperimentsLocallyOnThisThread(experimentsJson)
398- applyPendingExperimentsOnThisThread()
396+ applyPendingExperimentsOnThisThread(initial = true )
399397 } else {
400398 initializeOnThisThread()
401399 }
402400 }
403401 }
404402
405403 @WorkerThread
406- private fun postEnrolmentCalculation (initial : Boolean = false) {
407- nimbusClient.getActiveExperiments().also { experiments ->
408- recordExperimentTelemetry(experiments)
404+ private fun postEnrolmentCalculation (
405+ enrollmentChangeEvents : List <EnrollmentChangeEvent >,
406+ initial : Boolean = false,
407+ ) {
408+ val experiments = nimbusClient.getActiveExperiments()
409+
410+ if (initial) {
411+ // During initialization we need to report the experiment status of
412+ // all pre-existing experiments.
413+ for (experiment in experiments) {
414+ Glean .setExperimentActive(experiment.slug, experiment.branchSlug)
415+ }
416+ }
417+
418+ if (initial || enrollmentChangeEvents.isNotEmpty()) {
419+ // During initialization we need to inform the application when we've
420+ // finished applying updates, even if there is nothing enrolled.
421+ recordExperimentTelemetryEvents(enrollmentChangeEvents)
409422 updateObserver { observer ->
410423 observer.onUpdatesApplied(experiments)
411424 }
425+ }
412426
413- if (initial) {
414- val featureIds = mutableSetOf<String >()
415- for (experiment in experiments) {
416- for (featureId in experiment.featureIds) {
417- featureIds.add(featureId)
418- }
427+ if (initial) {
428+ // Likewise, during initialization we need to include trigger
429+ // updates for all pre-existing experiments.
430+ val featureIds = mutableSetOf<String >()
431+ for (experiment in experiments) {
432+ for (featureId in experiment.featureIds) {
433+ featureIds.add(featureId)
419434 }
420-
421- updateDispatcher.notifyFeatures(featureIds)
422435 }
436+
437+ updateDispatcher.notifyFeatures(featureIds)
438+ } else {
439+ // However, during subsequent enrollment changes we only need to
440+ // trigger updates to features that changed.
441+ updateDispatcher.notifyChanged(enrollmentChangeEvents)
423442 }
424443 }
425444
@@ -445,24 +464,16 @@ open class Nimbus(
445464 @VisibleForTesting(otherwise = VisibleForTesting .PRIVATE )
446465 internal fun setExperimentParticipationOnThisThread (active : Boolean ) =
447466 withCatchAll(" setExperimentParticipation" ) {
448- val enrolmentChanges = nimbusClient.setExperimentParticipation(active)
449- if (enrolmentChanges.isNotEmpty()) {
450- recordExperimentTelemetryEvents(enrolmentChanges)
451- postEnrolmentCalculation()
452- updateDispatcher.notifyChanged(enrolmentChanges)
453- }
467+ val enrollmentChangeEvents = nimbusClient.setExperimentParticipation(active)
468+ postEnrolmentCalculation(enrollmentChangeEvents)
454469 }
455470
456471 @WorkerThread
457472 @VisibleForTesting(otherwise = VisibleForTesting .PRIVATE )
458473 internal fun setRolloutParticipationOnThisThread (active : Boolean ) =
459474 withCatchAll(" setRolloutParticipation" ) {
460- val enrolmentChanges = nimbusClient.setRolloutParticipation(active)
461- if (enrolmentChanges.isNotEmpty()) {
462- recordExperimentTelemetryEvents(enrolmentChanges)
463- postEnrolmentCalculation()
464- updateDispatcher.notifyChanged(enrolmentChanges)
465- }
475+ val enrollmentChangeEvents = nimbusClient.setRolloutParticipation(active)
476+ postEnrolmentCalculation(enrollmentChangeEvents)
466477 }
467478
468479 override fun optOut (experimentId : String ) {
@@ -489,9 +500,7 @@ open class Nimbus(
489500 ): List <EnrollmentChangeEvent >? {
490501 return withCatchAll(" unenrollForGeckoPref" ) {
491502 val enrollmentChangeEvents = nimbusClient.unenrollForGeckoPref(geckoPrefState, prefUnenrollReason)
492- recordExperimentTelemetryEvents(enrollmentChangeEvents)
493- postEnrolmentCalculation()
494- updateDispatcher.notifyChanged(enrollmentChangeEvents)
503+ postEnrolmentCalculation(enrollmentChangeEvents)
495504 enrollmentChangeEvents
496505 }
497506 }
@@ -521,9 +530,7 @@ open class Nimbus(
521530 internal fun optOutOnThisThread (experimentId : String ) {
522531 withCatchAll(" optOut" ) {
523532 val enrollmentChangeEvents = nimbusClient.optOut(experimentId)
524- recordExperimentTelemetryEvents(enrollmentChangeEvents)
525- postEnrolmentCalculation()
526- updateDispatcher.notifyChanged(enrollmentChangeEvents)
533+ postEnrolmentCalculation(enrollmentChangeEvents)
527534 }
528535 }
529536
@@ -539,9 +546,7 @@ open class Nimbus(
539546 internal fun resetTelemetryIdentifiersOnThisThread () {
540547 withCatchAll(" resetTelemetryIdentifiers" ) {
541548 val enrollmentChangeEvents = nimbusClient.resetTelemetryIdentifiers()
542- recordExperimentTelemetryEvents(enrollmentChangeEvents)
543- postEnrolmentCalculation()
544- updateDispatcher.notifyChanged(enrollmentChangeEvents)
549+ postEnrolmentCalculation(enrollmentChangeEvents)
545550 }
546551 }
547552
@@ -557,9 +562,7 @@ open class Nimbus(
557562 internal fun optInWithBranchOnThisThread (experimentId : String , branch : String ) {
558563 withCatchAll(" optIn" ) {
559564 val enrollmentChangeEvents = nimbusClient.optInWithBranch(experimentId, branch)
560- recordExperimentTelemetryEvents(enrollmentChangeEvents)
561- postEnrolmentCalculation()
562- updateDispatcher.notifyChanged(enrollmentChangeEvents)
565+ postEnrolmentCalculation(enrollmentChangeEvents)
563566 }
564567 }
565568
@@ -637,6 +640,11 @@ open class Nimbus(
637640 branch = event.branchSlug,
638641 ),
639642 )
643+
644+ Glean .setExperimentActive(
645+ event.experimentSlug,
646+ event.branchSlug,
647+ )
640648 }
641649
642650 EnrollmentChangeEventType .DISQUALIFICATION -> {
@@ -646,6 +654,10 @@ open class Nimbus(
646654 branch = event.branchSlug,
647655 ),
648656 )
657+
658+ Glean .setExperimentInactive(
659+ event.experimentSlug,
660+ )
649661 }
650662
651663 EnrollmentChangeEventType .UNENROLLMENT -> {
@@ -655,6 +667,10 @@ open class Nimbus(
655667 branch = event.branchSlug,
656668 ),
657669 )
670+
671+ Glean .setExperimentInactive(
672+ event.experimentSlug,
673+ )
658674 }
659675
660676 EnrollmentChangeEventType .ENROLL_FAILED -> {
@@ -717,11 +733,7 @@ open class Nimbus(
717733 internal fun enrollInFirefoxLabOnThisThread (slug : String ): FirefoxLabsEnrollStatus {
718734 return withCatchAll(" enrollInFirefoxLab" ) {
719735 val result = nimbusClient.enrollInFirefoxLab(slug)
720- if (result.enrollmentChangeEvents.isNotEmpty()) {
721- recordExperimentTelemetryEvents(result.enrollmentChangeEvents)
722- postEnrolmentCalculation()
723- updateDispatcher.notifyChanged(result.enrollmentChangeEvents)
724- }
736+ postEnrolmentCalculation(result.enrollmentChangeEvents)
725737
726738 result.status
727739 } ? : FirefoxLabsEnrollStatus .ERROR
@@ -735,11 +747,7 @@ open class Nimbus(
735747 internal fun unenrollFromFirefoxLabOnThisThread (slug : String ): FirefoxLabsUnenrollStatus {
736748 return withCatchAll(" unenrollFromFirefoxLab" ) {
737749 val result = nimbusClient.unenrollFromFirefoxLab(slug)
738- if (result.enrollmentChangeEvents.isNotEmpty()) {
739- recordExperimentTelemetryEvents(result.enrollmentChangeEvents)
740- postEnrolmentCalculation()
741- updateDispatcher.notifyChanged(result.enrollmentChangeEvents)
742- }
750+ postEnrolmentCalculation(result.enrollmentChangeEvents)
743751
744752 result.status
745753 } ? : FirefoxLabsUnenrollStatus .ERROR
@@ -753,11 +761,7 @@ open class Nimbus(
753761 internal fun unenrollFromAllFirefoxLabsOnThisThread () {
754762 withCatchAll(" unenrollFromAllFirefoxLabs" ) {
755763 val enrollmentChangeEvents = nimbusClient.unenrollFromAllFirefoxLabs()
756- if (enrollmentChangeEvents.isNotEmpty()) {
757- recordExperimentTelemetryEvents(enrollmentChangeEvents)
758- postEnrolmentCalculation()
759- updateDispatcher.notifyChanged(enrollmentChangeEvents)
760- }
764+ postEnrolmentCalculation(enrollmentChangeEvents)
761765 }
762766 }
763767
0 commit comments