@@ -12,6 +12,7 @@ namespace NuGetGallery
1212 public class ABTestEnrollmentFactory : IABTestEnrollmentFactory
1313 {
1414 private const int SchemaVersion1 = 1 ;
15+ private const int SchemaVersion2 = 2 ;
1516
1617 private static readonly RNGCryptoServiceProvider _secureRng = new RNGCryptoServiceProvider ( ) ;
1718 private static readonly ThreadLocal < byte [ ] > _bytes = new ThreadLocal < byte [ ] > ( ( ) => new byte [ sizeof ( ulong ) ] ) ;
@@ -31,12 +32,14 @@ public ABTestEnrollment Initialize()
3132 {
3233 var enrollment = new ABTestEnrollment (
3334 ABTestEnrollmentState . FirstHit ,
34- SchemaVersion1 ,
35- previewSearchBucket : GetRandomWholePercentage ( ) ) ;
35+ SchemaVersion2 ,
36+ previewSearchBucket : GetRandomWholePercentage ( ) ,
37+ packageDependentBucket : GetRandomWholePercentage ( ) ) ;
3638
3739 _telemetryService . TrackABTestEnrollmentInitialized (
3840 enrollment . SchemaVersion ,
39- enrollment . PreviewSearchBucket ) ;
41+ enrollment . PreviewSearchBucket ,
42+ enrollment . PackageDependentBucket ) ;
4043
4144 return enrollment ;
4245 }
@@ -59,18 +62,19 @@ private static int GetRandomWholePercentage()
5962
6063 public string Serialize ( ABTestEnrollment enrollment )
6164 {
62- if ( enrollment . SchemaVersion != SchemaVersion1 )
65+ if ( enrollment . SchemaVersion != SchemaVersion2 )
6366 {
6467 throw new NotImplementedException ( $ "Serializing schema version { enrollment . SchemaVersion } is not implemented.") ;
6568 }
6669
67- var deserialized = new StateVersion1
70+ var deserialized2 = new StateVersion2
6871 {
69- SchemaVersion = SchemaVersion1 ,
72+ SchemaVersion = SchemaVersion2 ,
7073 PreviewSearchBucket = enrollment . PreviewSearchBucket ,
74+ PackageDependentBucket = enrollment . PackageDependentBucket ,
7175 } ;
7276
73- return JsonConvert . SerializeObject ( deserialized ) ;
77+ return JsonConvert . SerializeObject ( deserialized2 ) ;
7478 }
7579
7680 public bool TryDeserialize ( string serialized , out ABTestEnrollment enrollment )
@@ -81,6 +85,12 @@ public bool TryDeserialize(string serialized, out ABTestEnrollment enrollment)
8185 return false ;
8286 }
8387
88+ return TryDeserializeStateVer2 ( serialized , out enrollment ) || TryDeserializeStateVer1 ( serialized , out enrollment ) ;
89+ }
90+
91+ private bool TryDeserializeStateVer1 ( string serialized , out ABTestEnrollment enrollment )
92+ {
93+ enrollment = null ;
8494 try
8595 {
8696 var v1 = JsonConvert . DeserializeObject < StateVersion1 > ( serialized ) ;
@@ -91,10 +101,44 @@ public bool TryDeserialize(string serialized, out ABTestEnrollment enrollment)
91101 return false ;
92102 }
93103
104+ enrollment = new ABTestEnrollment (
105+ ABTestEnrollmentState . Upgraded ,
106+ SchemaVersion2 ,
107+ v1 . PreviewSearchBucket ,
108+ packageDependentBucket : GetRandomWholePercentage ( ) ) ;
109+
110+ _telemetryService . TrackABTestEnrollmentUpgraded (
111+ enrollment . SchemaVersion ,
112+ enrollment . PreviewSearchBucket ,
113+ enrollment . PackageDependentBucket ) ;
114+
115+ return true ;
116+ }
117+ catch ( JsonException )
118+ {
119+ return false ;
120+ }
121+ }
122+
123+ private bool TryDeserializeStateVer2 ( string serialized , out ABTestEnrollment enrollment )
124+ {
125+ enrollment = null ;
126+ try
127+ {
128+ var v2 = JsonConvert . DeserializeObject < StateVersion2 > ( serialized ) ;
129+ if ( v2 == null
130+ || v2 . SchemaVersion != SchemaVersion2
131+ || IsNotPercentage ( v2 . PreviewSearchBucket )
132+ || IsNotPercentage ( v2 . PackageDependentBucket ) )
133+ {
134+ return false ;
135+ }
136+
94137 enrollment = new ABTestEnrollment (
95138 ABTestEnrollmentState . Active ,
96- v1 . SchemaVersion ,
97- v1 . PreviewSearchBucket ) ;
139+ v2 . SchemaVersion ,
140+ v2 . PreviewSearchBucket ,
141+ v2 . PackageDependentBucket ) ;
98142
99143 return true ;
100144 }
@@ -117,5 +161,17 @@ private class StateVersion1
117161 [ JsonProperty ( "ps" , Required = Required . Always ) ]
118162 public int PreviewSearchBucket { get ; set ; }
119163 }
164+
165+ private class StateVersion2
166+ {
167+ [ JsonProperty ( "v" , Required = Required . Always ) ]
168+ public int SchemaVersion { get ; set ; }
169+
170+ [ JsonProperty ( "ps" , Required = Required . Always ) ]
171+ public int PreviewSearchBucket { get ; set ; }
172+
173+ [ JsonProperty ( "pd" , Required = Required . Always ) ]
174+ public int PackageDependentBucket { get ; set ; }
175+ }
120176 }
121177}
0 commit comments