public static void EnableSynonyms() { try { int MaxNumTries = 3; for (int i = 0; i < MaxNumTries; ++i) { try { //connect to Azure Search SearchServiceClient serviceClient = CreateSearchServiceClient(); Index index = serviceClient.Indexes.Get("eecip"); index = AddSynonymMapsToFields(index); // The IfNotChanged condition ensures that the index is updated only if the ETags match. serviceClient.Indexes.CreateOrUpdate(index, accessCondition: AccessCondition.IfNotChanged(index)); Console.WriteLine("Updated the index successfully.\n"); break; } catch (CloudException e) when(e.IsAccessConditionFailed()) { Console.WriteLine($"Index update failed : {e.Message}. Attempt({i}/{MaxNumTries}).\n"); } } } catch (Exception ex) { throw ex; } }
public void IfNotChangedThrowsOnEmptyETag() { IResourceWithETag aResourceWithETag = new AResourceWithETag() { ETag = string.Empty }; Assert.Throws <ArgumentException>(() => AccessCondition.IfNotChanged(aResourceWithETag)); }
public void IfNotChangedReturnsIfMatchAccessCondition() { IResourceWithETag aResourceWithETag = new AResourceWithETag() { ETag = "IHazETag" }; AccessCondition result = AccessCondition.IfNotChanged(aResourceWithETag); Assert.Equal(aResourceWithETag.ETag, result.IfMatch); Assert.Null(result.IfNoneMatch); }
internal static void DeleteIfNotChangedWorksOnlyOnCurrentResource <T>( Action <string, SearchRequestOptions, AccessCondition> deleteAction, Func <T> createResource, Func <T, T> updateResource, string resourceName) where T : IResourceWithETag { Action <string, AccessCondition> delete = (a, b) => deleteAction(a, null, b); var staleResource = createResource(); var currentResource = updateResource(staleResource); SearchAssert.ThrowsCloudException( () => delete(resourceName, AccessCondition.IfNotChanged(staleResource)), e => e.IsAccessConditionFailed()); delete(resourceName, AccessCondition.IfNotChanged(currentResource)); }
internal static void UpdateIfNotChangedSucceedsWhenResourceUnchanged <T>( Func <T, SearchRequestOptions, AccessCondition, T> createOrUpdateFunc, Func <T> newResourceDefinition, Func <T, T> mutateResourceDefinition) where T : IResourceWithETag { Func <T, AccessCondition, T> createOrUpdate = (a, b) => createOrUpdateFunc(a, null, b); var createdResource = createOrUpdate(newResourceDefinition(), AccessCondition.GenerateEmptyCondition()); var mutatedResource = mutateResourceDefinition(createdResource); var updatedResource = createOrUpdate(mutatedResource, AccessCondition.IfNotChanged(createdResource)); Assert.NotEmpty(createdResource.ETag); Assert.NotEmpty(updatedResource.ETag); Assert.NotEqual(createdResource.ETag, updatedResource.ETag); }
public static void UpdateIfNotChangedFailsWhenResourceChanged <T>( Func <T, SearchRequestOptions, AccessCondition, T> createOrUpdateFunc, Func <T> newResourceDefinition, Func <T, T> mutateResourceDefinition) where T : IResourceWithETag { Func <T, AccessCondition, T> createOrUpdate = (a, b) => createOrUpdateFunc(a, null, b); var createdResource = createOrUpdate(newResourceDefinition(), AccessCondition.GenerateEmptyCondition()); var mutatedResource = mutateResourceDefinition(createdResource); var updatedResource = createOrUpdate(mutatedResource, AccessCondition.GenerateEmptyCondition()); SearchAssert.ThrowsCloudException( () => createOrUpdate(updatedResource, AccessCondition.IfNotChanged(createdResource)), e => e.IsAccessConditionFailed()); Assert.NotEmpty(createdResource.ETag); Assert.NotEmpty(updatedResource.ETag); Assert.NotEqual(createdResource.ETag, updatedResource.ETag); }
public void IfNotChangedThrowsOnNullETag() { IResourceWithETag aResourceWithETag = new AResourceWithETag(); Assert.Throws <ArgumentNullException>(() => AccessCondition.IfNotChanged(aResourceWithETag)); }
public void IfNotChangedThrowsOnNullResource() { Assert.Throws <ArgumentNullException>(() => AccessCondition.IfNotChanged(null)); }
private async Task EnableSynonymsInCombinedIndex(ISearchServiceClient serviceClient) { const int maxTries = 3; for (var i = 0; i < maxTries; ++i) { try { var index = await serviceClient.Indexes.GetAsync(SearchConstants.CombinedIndexName); index.Fields.First(f => f.Name == "courseName").SynonymMaps = new[] { SearchConstants.CourseSynonymMapName }; index.Fields.First(f => f.Name == "courseDescription").SynonymMaps = new[] { SearchConstants.CourseSynonymMapName }; // The IfNotChanged condition ensures that the index is updated only if the ETags match. await serviceClient.Indexes.CreateOrUpdateAsync(index, accessCondition : AccessCondition.IfNotChanged(index)); break; } catch (CloudException e) when(e.IsAccessConditionFailed()) { Console.WriteLine($"Index update failed : {e.Message}. Attempt({i}/{maxTries}).\n"); } } }
// This sample shows how ETags work by performing conditional updates and deletes // on an Azure Search index. static void Main(string[] args) { IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile("appsettings.json"); IConfigurationRoot configuration = builder.Build(); SearchServiceClient serviceClient = CreateSearchServiceClient(configuration); Console.WriteLine("Deleting index...\n"); DeleteTestIndexIfExists(serviceClient); // Every top-level resource in Azure Search has an associated ETag that keeps track of which version // of the resource you're working on. When you first create a resource such as an index, its ETag is // empty. Index index = DefineTestIndex(); Console.WriteLine( $"Test index hasn't been created yet, so its ETag should be blank. ETag: '{index.ETag}'"); // Once the resource exists in Azure Search, its ETag will be populated. Make sure to use the object // returned by the SearchServiceClient! Otherwise, you will still have the old object with the // blank ETag. Console.WriteLine("Creating index...\n"); index = serviceClient.Indexes.Create(index); Console.WriteLine($"Test index created; Its ETag should be populated. ETag: '{index.ETag}'"); // ETags let you do some useful things you couldn't do otherwise. For example, by using an If-Match // condition, we can update an index using CreateOrUpdate and be guaranteed that the update will only // succeed if the index already exists. index.Fields.Add(new Field("name", AnalyzerName.EnMicrosoft)); index = serviceClient.Indexes.CreateOrUpdate( index, accessCondition: AccessCondition.GenerateIfExistsCondition()); Console.WriteLine( $"Test index updated; Its ETag should have changed since it was created. ETag: '{index.ETag}'"); // More importantly, ETags protect you from concurrent updates to the same resource. If another // client tries to update the resource, it will fail as long as all clients are using the right // access conditions. Index indexForClient1 = index; Index indexForClient2 = serviceClient.Indexes.Get("test"); Console.WriteLine("Simulating concurrent update. To start, both clients see the same ETag."); Console.WriteLine($"Client 1 ETag: '{indexForClient1.ETag}' Client 2 ETag: '{indexForClient2.ETag}'"); // Client 1 successfully updates the index. indexForClient1.Fields.Add(new Field("a", DataType.Int32)); indexForClient1 = serviceClient.Indexes.CreateOrUpdate( indexForClient1, accessCondition: AccessCondition.IfNotChanged(indexForClient1)); Console.WriteLine($"Test index updated by client 1; ETag: '{indexForClient1.ETag}'"); // Client 2 tries to update the index, but fails, thanks to the ETag check. try { indexForClient2.Fields.Add(new Field("b", DataType.Boolean)); serviceClient.Indexes.CreateOrUpdate( indexForClient2, accessCondition: AccessCondition.IfNotChanged(indexForClient2)); Console.WriteLine("Whoops; This shouldn't happen"); Environment.Exit(1); } catch (CloudException e) when(e.IsAccessConditionFailed()) { Console.WriteLine("Client 2 failed to update the index, as expected."); } // You can also use access conditions with Delete operations. For example, you can implement an // atomic version of the DeleteTestIndexIfExists method from this sample like this: Console.WriteLine("Deleting index...\n"); serviceClient.Indexes.Delete("test", accessCondition: AccessCondition.GenerateIfExistsCondition()); // This is slightly better than using the Exists method since it makes only one round trip to // Azure Search instead of potentially two. It also avoids an extra Delete request in cases where // the resource is deleted concurrently, but this doesn't matter much since resource deletion in // Azure Search is idempotent. // And we're done! Bye! Console.WriteLine("Complete. Press any key to end application...\n"); Console.ReadKey(); }