/// <summary> /// Store the fingerprint store directory to the cache /// </summary> public static async Task <Possible <long> > TrySaveFingerprintStoreAsync( this EngineCache cache, LoggingContext loggingContext, AbsolutePath path, PathTable pathTable, string key, string environment) { var fingerprint = ComputeFingerprint(pathTable, key, environment); var pathStr = path.ToString(pathTable); BoxRef <long> size = 0; SemaphoreSlim concurrencyLimiter = new SemaphoreSlim(8); var tasks = new List <Task <Possible <StringKeyedHash, Failure> > >(); FileUtilities.EnumerateDirectoryEntries(pathStr, (name, attr) => { var task = Task.Run(async() => { using (await concurrencyLimiter.AcquireAsync()) { var filePath = path.Combine(pathTable, name); var storeResult = await cache.ArtifactContentCache.TryStoreAsync( FileRealizationMode.Copy, filePath.Expand(pathTable)); if (storeResult.Succeeded) { Interlocked.Add(ref size.Value, new FileInfo(filePath.ToString(pathTable)).Length); } return(storeResult.Then(result => new StringKeyedHash() { Key = path.ExpandRelative(pathTable, filePath), ContentHash = result.ToBondContentHash() })); } }); tasks.Add(task); }); var storedFiles = await Task.WhenAll(tasks); var failure = storedFiles.Where(p => !p.Succeeded).Select(p => p.Failure).FirstOrDefault(); Logger.Log.GettingFingerprintStoreTrace(loggingContext, I($"Saving fingerprint store to cache: Success='{failure == null}', FileCount={storedFiles.Length} Size={size.Value}")); if (failure != null) { return(failure); } PackageDownloadDescriptor descriptor = new PackageDownloadDescriptor() { TraceInfo = loggingContext.Session.Environment, FriendlyName = nameof(FingerprintStore), Contents = storedFiles.Select(p => p.Result).ToList() }; var storeDescriptorResult = await cache.ArtifactContentCache.TrySerializeAndStoreContent(descriptor); Logger.Log.GettingFingerprintStoreTrace(loggingContext, I($"Saving fingerprint store descriptor to cache: Success='{storeDescriptorResult.Succeeded}'")); if (!storeDescriptorResult.Succeeded) { return(storeDescriptorResult.Failure); } var associatedFileHashes = descriptor.Contents.Select(s => s.ContentHash.ToContentHash()).ToArray().ToReadOnlyArray().GetSubView(0); var cacheEntry = new CacheEntry(storeDescriptorResult.Result, null, associatedFileHashes); var publishResult = await cache.TwoPhaseFingerprintStore.TryPublishTemporalCacheEntryAsync(loggingContext, fingerprint, cacheEntry); Logger.Log.GettingFingerprintStoreTrace(loggingContext, I($"Publishing fingerprint store to cache: Fingerprint='{fingerprint}' Hash={storeDescriptorResult.Result}")); return(size.Value); }