public async Task UsesProvidedMatchETag() { // Arrange AccessCondition srcAccessCondition = null; AccessCondition destAccessCondition = null; ISimpleCloudBlob srcBlob = null; _destBlobMock .Setup(x => x.StartCopyAsync(It.IsAny <ISimpleCloudBlob>(), It.IsAny <AccessCondition>(), It.IsAny <AccessCondition>())) .Returns(Task.FromResult(0)) .Callback <ISimpleCloudBlob, AccessCondition, AccessCondition>((b, s, d) => { srcBlob = b; srcAccessCondition = s; destAccessCondition = d; SetDestCopyStatus(CopyStatus.Success); }); // Act await _target.CopyFileAsync( _srcFolderName, _srcFileName, _destFolderName, _destFileName, AccessConditionWrapper.GenerateIfMatchCondition("etag!")); // Assert _destBlobMock.Verify( x => x.StartCopyAsync(It.IsAny <ISimpleCloudBlob>(), It.IsAny <AccessCondition>(), It.IsAny <AccessCondition>()), Times.Once); Assert.Equal("etag!", destAccessCondition.IfMatchETag); Assert.Null(destAccessCondition.IfNoneMatchETag); }
public async Task <RevalidationState> MaybeUpdateStateAsync(Func <RevalidationState, bool> updateAction) { var internalState = await GetInternalStateAsync(); var fileReference = internalState.FileReference; var state = internalState.State; // Only update the state if the update action returns true. var originalState = new RevalidationState { IsInitialized = state.IsInitialized, IsKillswitchActive = state.IsKillswitchActive, DesiredPackageEventRate = state.DesiredPackageEventRate, }; if (!updateAction(state)) { return(originalState); } try { var accessCondition = AccessConditionWrapper.GenerateIfMatchCondition(fileReference.ContentId); using (var stream = new MemoryStream()) using (var writer = new StreamWriter(stream)) using (var jsonWriter = new JsonTextWriter(writer)) { _serializer.Serialize(jsonWriter, state); jsonWriter.Flush(); stream.Position = 0; await _storage.SaveFileAsync(CoreConstants.Folders.RevalidationFolderName, StateFileName, stream, accessCondition); } return(state); } catch (StorageException e) when(e.IsPreconditionFailedException()) { throw new InvalidOperationException("Failed to update the state blob since the access condition failed", e); } }
/// <summary> /// Asynchronously sets blob metadata. /// </summary> /// <param name="folderName">The folder (container) name.</param> /// <param name="fileName">The blob file name.</param> /// <param name="updateMetadataAsync">A function which updates a metadata dictionary and returns <c>true</c> /// for changes to be persisted or <c>false</c> for changes to be discarded.</param> /// <returns>A task that represents the asynchronous operation.</returns> public async Task SetMetadataAsync( string folderName, string fileName, Func <Lazy <Task <Stream> >, IDictionary <string, string>, Task <bool> > updateMetadataAsync) { if (folderName == null) { throw new ArgumentNullException(nameof(folderName)); } if (fileName == null) { throw new ArgumentNullException(nameof(fileName)); } if (updateMetadataAsync == null) { throw new ArgumentNullException(nameof(updateMetadataAsync)); } var container = await GetContainerAsync(folderName); var blob = container.GetBlobReference(fileName); await blob.FetchAttributesAsync(); var lazyStream = new Lazy <Task <Stream> >(() => GetFileAsync(folderName, fileName)); var wasUpdated = await updateMetadataAsync(lazyStream, blob.Metadata); if (wasUpdated) { var accessCondition = AccessConditionWrapper.GenerateIfMatchCondition(blob.ETag); var mappedAccessCondition = new AccessCondition { IfNoneMatchETag = accessCondition.IfNoneMatchETag, IfMatchETag = accessCondition.IfMatchETag }; await blob.SetMetadataAsync(mappedAccessCondition); } }