/// <summary> /// Update all chunks if they exist. Returns success only if all chunks are found and extended. /// </summary> private async Task <PinResult> TryPinChunksAsync(Context context, IEnumerable <VstsDedupIdentifier> dedupIdentifiers, CancellationToken cts) { if (!dedupIdentifiers.Any()) { return(PinResult.Success); } // TODO: Support batched TryKeepUntilReferenceChunkAsync in Artifact. (bug 1428612) var tryReferenceBlock = new TransformBlock <VstsDedupIdentifier, PinResult>( async dedupId => await TryPinChunkAsync(context, dedupId, cts), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = DefaultMaxParallelism }); tryReferenceBlock.PostAll(dedupIdentifiers); var pinResults = await Task.WhenAll(Enumerable.Range(0, dedupIdentifiers.ToList().Count).Select(i => tryReferenceBlock.ReceiveAsync())); tryReferenceBlock.Complete(); foreach (var result in pinResults) { if (!result.Succeeded) { return(result); // An error updating one of the chunks occured. Fail fast. } } return(PinResult.Success); }
private async Task <IEnumerable <Task <Indexed <PinResult> > > > UpdateDedupStoreAsync( Context context, IReadOnlyList <ContentHash> contentHashes, CancellationToken cts) { if (!contentHashes.Any()) { return((new List <Task <Indexed <PinResult> > >()).AsEnumerable()); } var dedupIdentifiers = contentHashes.Select(c => ToVstsBlobIdentifier(c.ToBlobIdentifier()).ToDedupIdentifier()); var tryReferenceBlock = new TransformBlock <Indexed <VstsDedupIdentifier>, Indexed <PinResult> >( async i => { PinResult pinResult; if (i.Item.AlgorithmId == Hashing.ChunkDedupIdentifier.ChunkAlgorithmId) { pinResult = await TryPinChunkAsync(context, i.Item, cts); } else { pinResult = await TryPinNodeAsync(context, i.Item, cts); } if (pinResult.Succeeded) { BackingContentStoreExpiryCache.Instance.AddExpiry(new ContentHash(HashType.DedupNodeOrChunk, i.Item.Value), EndDateTime); } return(pinResult.WithIndex(i.Index)); }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = DefaultMaxParallelism }); tryReferenceBlock.PostAll(dedupIdentifiers.AsIndexed()); var results = await Task.WhenAll(Enumerable.Range(0, dedupIdentifiers.ToList().Count).Select(i => tryReferenceBlock.ReceiveAsync())); tryReferenceBlock.Complete(); return(results.AsTasks().ToList()); }
public async Task <IEnumerable <Task <Indexed <PlaceFileResult> > > > FetchThenPutBulkAsync(OperationContext context, IReadOnlyList <ContentHashWithPath> args, IContentSession contentSession) { var putFilesBlock = new TransformBlock <Indexed <ContentHashWithPath>, Indexed <PlaceFileResult> >( async indexed => { return(new Indexed <PlaceFileResult>(await CreateTempAndPutAsync(context, indexed.Item.Hash, contentSession), indexed.Index)); }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = _maxParallelPlaces }); putFilesBlock.PostAll(args.AsIndexed()); var copyFilesLocally = await Task.WhenAll( Enumerable.Range(0, args.Count).Select(i => putFilesBlock.ReceiveAsync(context.Token))); putFilesBlock.Complete(); return(copyFilesLocally.AsTasks()); }