66using System . ComponentModel ;
77using System . Diagnostics . CodeAnalysis ;
88using System . Diagnostics . ContractsLight ;
9+ using System . Linq ;
910using System . Threading . Tasks ;
1011using BuildXL . Cache . ContentStore . Distributed . Blob ;
12+ using BuildXL . Cache . ContentStore . Interfaces . Auth ;
1113using BuildXL . Cache . Interfaces ;
1214using BuildXL . Cache . MemoizationStore . Distributed . Stores ;
13- using BuildXL . Utilities . Core ;
15+ using BuildXL . Utilities . Collections ;
1416using BuildXL . Utilities . Configuration ;
17+ using BuildXL . Utilities . Core ;
1518using AbsolutePath = BuildXL . Cache . ContentStore . Interfaces . FileSystem . AbsolutePath ;
16- using System . Security . Principal ;
17- using BuildXL . Cache . ContentStore . Interfaces . Auth ;
1819
1920namespace BuildXL . Cache . MemoizationStoreAdapter
2021{
@@ -28,7 +29,7 @@ namespace BuildXL.Cache.MemoizationStoreAdapter
2829 /// Current limitations while we flesh things out:
2930 /// 1) APIs around tracking named sessions are not implemented
3031 /// </remarks>
31- public partial class BlobCacheFactory : ICacheFactory
32+ public class BlobCacheFactory : ICacheFactory
3233 {
3334 /// <summary>
3435 /// Inheritable configuration settings for cache factories that wish to configure a connection to a blob cache
@@ -76,6 +77,15 @@ public abstract class BlobCacheConfig
7677 /// </remarks>
7778 [ DefaultValue ( 0 ) ]
7879 public int RetentionPolicyInDays { get ; set ; }
80+
81+ /// <nodoc />
82+ [ DefaultValue ( "default" ) ]
83+ public string Universe { get ; set ; }
84+
85+ /// <nodoc />
86+ [ DefaultValue ( "default" ) ]
87+ public string Namespace { get ; set ; }
88+
7989 }
8090
8191 /// <summary>
@@ -89,14 +99,6 @@ public sealed class Config : BlobCacheConfig
8999 [ DefaultValue ( typeof ( CacheId ) ) ]
90100 public CacheId CacheId { get ; set ; }
91101
92- /// <nodoc />
93- [ DefaultValue ( "default" ) ]
94- public string Universe { get ; set ; }
95-
96- /// <nodoc />
97- [ DefaultValue ( "default" ) ]
98- public string Namespace { get ; set ; }
99-
100102 /// <summary>
101103 /// Path to the log file for the cache.
102104 /// </summary>
@@ -157,7 +159,7 @@ public async Task<Possible<ICache, Failure>> InitializeCacheAsync(Config configu
157159 logger : new DisposeLogger ( ( ) => new EtwFileLog ( logPath . Path , configuration . CacheId ) , configuration . LogFlushIntervalSeconds ) ,
158160 statsFile : new AbsolutePath ( logPath . Path + ".stats" ) ,
159161 precedingStateDegradationFailures : failures ) ;
160-
162+
161163 var startupResult = await cache . StartupAsync ( ) ;
162164 if ( ! startupResult . Succeeded )
163165 {
@@ -172,14 +174,12 @@ public async Task<Possible<ICache, Failure>> InitializeCacheAsync(Config configu
172174 }
173175 }
174176
175- private static MemoizationStore . Interfaces . Caches . ICache CreateCache ( Config configuration )
177+ internal static MemoizationStore . Interfaces . Caches . IFullCache CreateCache ( BlobCacheConfig configuration )
176178 {
177- IAzureStorageCredentials credentials = GetAzureCredentialsFromBlobFactoryConfig ( configuration ) ;
178-
179- var accountName = BlobCacheStorageAccountName . Parse ( credentials . GetAccountName ( ) ) ;
179+ var credentials = LoadAzureCredentials ( configuration ) ;
180180
181181 var factoryConfiguration = new AzureBlobStorageCacheFactory . Configuration (
182- ShardingScheme : new ShardingScheme ( ShardingAlgorithm . SingleShard , new List < BlobCacheStorageAccountName > { accountName } ) ,
182+ ShardingScheme : new ShardingScheme ( ShardingAlgorithm . JumpHash , credentials . Keys . ToList ( ) ) ,
183183 Universe : configuration . Universe ,
184184 Namespace : configuration . Namespace ,
185185 RetentionPolicyInDays : configuration . RetentionPolicyInDays ) ;
@@ -188,14 +188,22 @@ private static MemoizationStore.Interfaces.Caches.ICache CreateCache(Config conf
188188 }
189189
190190 /// <nodoc />
191- internal static IAzureStorageCredentials GetAzureCredentialsFromBlobFactoryConfig ( BlobCacheConfig configuration )
191+ internal static Dictionary < BlobCacheStorageAccountName , IAzureStorageCredentials > LoadAzureCredentials ( BlobCacheConfig configuration )
192192 {
193- IAzureStorageCredentials credentials ;
193+ var credentials = new Dictionary < BlobCacheStorageAccountName , IAzureStorageCredentials > ( ) ;
194194 var connectionString = Environment . GetEnvironmentVariable ( configuration . ConnectionStringEnvironmentVariableName ) ;
195195
196196 if ( ! string . IsNullOrEmpty ( connectionString ) )
197197 {
198- credentials = new SecretBasedAzureStorageCredentials ( connectionString ) ;
198+ credentials . AddRange (
199+ connectionString . Split ( ' ' )
200+ . Select (
201+ secret =>
202+ {
203+ var credential = new SecretBasedAzureStorageCredentials ( secret . Trim ( ) ) ;
204+ var accountName = BlobCacheStorageAccountName . Parse ( credential . GetAccountName ( ) ) ;
205+ return new KeyValuePair < BlobCacheStorageAccountName , IAzureStorageCredentials > ( accountName , credential ) ;
206+ } ) ) ;
199207 }
200208 else if ( configuration . ManagedIdentityId is not null && configuration . StorageAccountEndpoint is not null )
201209 {
@@ -207,7 +215,8 @@ internal static IAzureStorageCredentials GetAzureCredentialsFromBlobFactoryConfi
207215 throw new InvalidOperationException ( $ "'{ configuration . StorageAccountEndpoint } ' does not represent a valid URI.") ;
208216 }
209217
210- credentials = new ManagedIdentityAzureStorageCredentials ( configuration . ManagedIdentityId , uri ) ;
218+ var credential = new ManagedIdentityAzureStorageCredentials ( configuration . ManagedIdentityId , uri ) ;
219+ credentials . Add ( BlobCacheStorageAccountName . Parse ( credential . GetAccountName ( ) ) , credential ) ;
211220 }
212221 else
213222 {
0 commit comments