@@ -449,21 +449,68 @@ public virtual Result<FeatureDecision> GetVariationForFeatureRollout(FeatureFlag
449
449
return Result < FeatureDecision > . NullResult ( reasons ) ;
450
450
}
451
451
452
+ var userId = user . GetUserId ( ) ;
453
+ var attributes = user . GetAttributes ( ) ;
454
+
452
455
var index = 0 ;
453
456
while ( index < rolloutRulesLength )
454
457
{
455
- /// TODO: add findvalidated forced decision here, no need to add separate function.
456
- var decisionResult = GetVariationFromDeliveryRule ( config , featureFlag . Key , rolloutRules , index , user ) ;
457
- reasons += decisionResult . DecisionReasons ;
458
+ // To skip rules
459
+ var skipToEveryoneElse = false ;
458
460
459
- if ( decisionResult . ResultObject ? . Variation ? . Key != null )
461
+ //Check forced decision first
462
+ var rule = rolloutRules [ index ] ;
463
+ var decisionContext = new OptimizelyDecisionContext ( featureFlag . Key , rule . Key ) ;
464
+ var forcedDecisionResponse = user . FindValidatedForcedDecision ( decisionContext , config ) ;
465
+
466
+ reasons += forcedDecisionResponse . DecisionReasons ;
467
+ if ( forcedDecisionResponse . ResultObject != null )
468
+ {
469
+ return Result < FeatureDecision > . NewResult ( new FeatureDecision ( rule , forcedDecisionResponse . ResultObject , null ) , reasons ) ;
470
+ }
471
+
472
+ // Regular decision
473
+
474
+ // Get Bucketing ID from user attributes.
475
+ var bucketingIdResult = GetBucketingId ( userId , attributes ) ;
476
+ reasons += bucketingIdResult . DecisionReasons ;
477
+
478
+ var everyoneElse = index == rolloutRulesLength - 1 ;
479
+
480
+ var loggingKey = everyoneElse ? "Everyone Else" : string . Format ( "{0}" , index + 1 ) ;
481
+
482
+ // Evaluate if user meets the audience condition of this rollout rule
483
+ var doesUserMeetAudienceConditionsResult = ExperimentUtils . DoesUserMeetAudienceConditions ( config , rule , attributes , LOGGING_KEY_TYPE_RULE , rule . Key , Logger ) ;
484
+ reasons += doesUserMeetAudienceConditionsResult . DecisionReasons ;
485
+ if ( doesUserMeetAudienceConditionsResult . ResultObject )
486
+ {
487
+ Logger . Log ( LogLevel . INFO , reasons . AddInfo ( $ "User \" { userId } \" meets condition for targeting rule \" { loggingKey } \" .") ) ;
488
+
489
+ var bucketedVariation = Bucketer . Bucket ( config , rule , bucketingIdResult . ResultObject , userId ) ;
490
+ reasons += bucketedVariation ? . DecisionReasons ;
491
+
492
+ if ( bucketedVariation ? . ResultObject ? . Key != null )
493
+ {
494
+ Logger . Log ( LogLevel . INFO , reasons . AddInfo ( $ "User \" { userId } \" is in the traffic group of targeting rule \" { loggingKey } \" .") ) ;
495
+
496
+ return Result < FeatureDecision > . NewResult ( new FeatureDecision ( rule , bucketedVariation . ResultObject , FeatureDecision . DECISION_SOURCE_ROLLOUT ) , reasons ) ;
497
+ }
498
+ else if ( ! everyoneElse )
499
+ {
500
+ //skip this logging for everyoneElse rule since this has a message not for everyoneElse
501
+ Logger . Log ( LogLevel . INFO , reasons . AddInfo ( $ "User \" { userId } \" is not in the traffic group for targeting rule \" { loggingKey } \" . Checking EveryoneElse rule now.") ) ;
502
+ skipToEveryoneElse = true ;
503
+ }
504
+ }
505
+ else
460
506
{
461
- return Result < FeatureDecision > . NewResult ( new FeatureDecision ( rolloutRules [ index ] , decisionResult . ResultObject . Variation , FeatureDecision . DECISION_SOURCE_ROLLOUT ) , reasons ) ;
507
+ Logger . Log ( LogLevel . DEBUG , reasons . AddInfo ( $ "User \" { userId } \" does not meet the conditions for targeting rule \" { loggingKey } \" ." ) ) ;
462
508
}
463
509
464
510
// the last rule is special for "Everyone Else"
465
- index = decisionResult . SkipToEveryoneElse ? ( rolloutRulesLength - 1 ) : ( index + 1 ) ;
511
+ index = skipToEveryoneElse ? ( rolloutRulesLength - 1 ) : ( index + 1 ) ;
466
512
}
513
+
467
514
return Result < FeatureDecision > . NullResult ( reasons ) ;
468
515
}
469
516
@@ -504,140 +551,36 @@ public virtual Result<FeatureDecision> GetVariationForFeatureExperiment(FeatureF
504
551
if ( string . IsNullOrEmpty ( experiment . Key ) )
505
552
continue ;
506
553
507
-
508
554
var forcedDecisionResponse = user . FindValidatedForcedDecision (
509
- new OptimizelyDecisionContext ( featureFlag . Key , experiment ? . Key ) , config ) ;
555
+ new OptimizelyDecisionContext ( featureFlag . Key , experiment ? . Key ) ,
556
+ config ) ;
510
557
reasons += forcedDecisionResponse . DecisionReasons ;
511
558
512
- if ( forcedDecisionResponse ? . ResultObject != null ) {
559
+ if ( forcedDecisionResponse ? . ResultObject != null )
560
+ {
513
561
decisionVariation = forcedDecisionResponse . ResultObject ;
514
- } else {
562
+ }
563
+ else
564
+ {
515
565
var decisionResponse = GetVariation ( experiment , user , config , options ) ;
516
-
566
+
517
567
reasons += decisionResponse ? . DecisionReasons ;
518
-
519
568
decisionVariation = decisionResponse . ResultObject ;
520
569
}
521
570
522
-
523
-
524
571
if ( decisionVariation ? . Id != null )
525
572
{
526
573
Logger . Log ( LogLevel . INFO , reasons . AddInfo ( $ "The user \" { userId } \" is bucketed into experiment \" { experiment . Key } \" of feature \" { featureFlag . Key } \" .") ) ;
527
574
528
575
var featureDecision = new FeatureDecision ( experiment , decisionVariation , FeatureDecision . DECISION_SOURCE_FEATURE_TEST ) ;
529
576
return Result < FeatureDecision > . NewResult ( featureDecision , reasons ) ;
530
577
}
531
-
532
578
}
533
579
534
580
Logger . Log ( LogLevel . INFO , reasons . AddInfo ( $ "The user \" { userId } \" is not bucketed into any of the experiments on the feature \" { featureFlag . Key } \" .") ) ;
535
581
return Result < FeatureDecision > . NullResult ( reasons ) ;
536
582
}
537
583
538
- /// <summary>
539
- /// TODO: Remove this one as well. Keep it simple.
540
- /// </summary>
541
- /// <param name="config"></param>
542
- /// <param name="key"></param>
543
- /// <param name="rules"></param>
544
- /// <param name="ruleIndex"></param>
545
- /// <param name="user"></param>
546
- /// <returns></returns>
547
- private Result < FeatureDecision > GetVariationFromDeliveryRule ( ProjectConfig config , string key , List < Experiment > rules , int ruleIndex , OptimizelyUserContext user )
548
- {
549
- var reasons = new DecisionReasons ( ) ;
550
-
551
- bool skipToEveryoneElse = false ;
552
-
553
- //Check forced decision first
554
- var rule = rules [ ruleIndex ] ;
555
- var decisionContext = new OptimizelyDecisionContext ( key , rule . Key ) ;
556
- var forcedDecisionResponse = user . FindValidatedForcedDecision ( decisionContext , config ) ;
557
-
558
- reasons += forcedDecisionResponse . DecisionReasons ;
559
- if ( forcedDecisionResponse . ResultObject != null )
560
- {
561
- return Result < FeatureDecision > . NewResult ( new FeatureDecision ( rule , forcedDecisionResponse . ResultObject , null ) , skipToEveryoneElse , reasons ) ;
562
- }
563
-
564
- // Regular decision
565
- var userId = user . GetUserId ( ) ;
566
- var attributes = user . GetAttributes ( ) ;
567
-
568
- // Get Bucketing ID from user attributes.
569
- var bucketingIdResult = GetBucketingId ( userId , attributes ) ;
570
- reasons += bucketingIdResult . DecisionReasons ;
571
-
572
- var everyoneElse = ruleIndex == rules . Count - 1 ;
573
-
574
- var loggingKey = everyoneElse ? "Everyone Else" : ruleIndex + 1 + "" ;
575
-
576
- Result < Variation > bucketedVariation = null ;
577
-
578
- // Evaluate if user meets the audience condition of this rollout rule
579
- var doesUserMeetAudienceConditionsResult = ExperimentUtils . DoesUserMeetAudienceConditions ( config , rule , attributes , LOGGING_KEY_TYPE_RULE , rule . Key , Logger ) ;
580
- reasons += doesUserMeetAudienceConditionsResult . DecisionReasons ;
581
- if ( doesUserMeetAudienceConditionsResult . ResultObject )
582
- {
583
- Logger . Log ( LogLevel . INFO , reasons . AddInfo ( $ "User \" { userId } \" meets condition for targeting rule \" { loggingKey } \" .") ) ;
584
-
585
- bucketedVariation = Bucketer . Bucket ( config , rule , bucketingIdResult . ResultObject , userId ) ;
586
- reasons += bucketedVariation ? . DecisionReasons ;
587
-
588
- if ( bucketedVariation ? . ResultObject ? . Key != null )
589
- {
590
- Logger . Log ( LogLevel . INFO , reasons . AddInfo ( $ "User \" { userId } \" is in the traffic group of targeting rule \" { loggingKey } \" .") ) ;
591
- }
592
- else if ( ! everyoneElse )
593
- {
594
- //skip this loggng for everyoneElse rule since this has a message not for everyoneElse
595
- Logger . Log ( LogLevel . INFO , reasons . AddInfo ( $ "User \" { userId } \" is not in the traffic group for targeting rule \" { loggingKey } \" . Checking EveryoneElse rule now.") ) ;
596
- skipToEveryoneElse = true ;
597
- }
598
- }
599
- else
600
- {
601
- Logger . Log ( LogLevel . DEBUG , reasons . AddInfo ( $ "User \" { userId } \" does not meet the conditions for targeting rule \" { loggingKey } \" .") ) ;
602
- }
603
-
604
- return Result < FeatureDecision > . NewResult ( new FeatureDecision ( rule , bucketedVariation ? . ResultObject , null ) , skipToEveryoneElse , reasons ) ;
605
- }
606
-
607
- /// <summary>
608
- /// TODO: Need to remove.
609
- /// </summary>
610
- /// <param name="config"></param>
611
- /// <param name="key"></param>
612
- /// <param name="experiment"></param>
613
- /// <param name="user"></param>
614
- /// <param name="options"></param>
615
- /// <returns></returns>
616
- private Result < Variation > GetVariationFromExperimentRule ( ProjectConfig config , string key , Experiment experiment , OptimizelyUserContext user , OptimizelyDecideOption [ ] options )
617
- {
618
- var reasons = new DecisionReasons ( ) ;
619
-
620
- var decisionContext = new OptimizelyDecisionContext ( key , experiment ? . Key ) ;
621
-
622
- var forcedDecisionResponse = user . FindValidatedForcedDecision ( decisionContext , config ) ;
623
-
624
- reasons += forcedDecisionResponse . DecisionReasons ;
625
-
626
- var variation = forcedDecisionResponse ? . ResultObject ;
627
-
628
- if ( variation != null )
629
- {
630
- return Result < Variation > . NewResult ( variation , reasons ) ;
631
- }
632
-
633
- var decisionResponse = GetVariation ( experiment , user , config , options ) ;
634
-
635
- reasons += decisionResponse ? . DecisionReasons ;
636
-
637
- return Result < Variation > . NewResult ( decisionResponse ? . ResultObject , reasons ) ;
638
- }
639
-
640
-
641
584
/// <summary>
642
585
/// Get the variation the user is bucketed into for the FeatureFlag
643
586
/// </summary>
0 commit comments