private async Task <List <ResultData> > GenerateInsertConflicts(ILogger logger, Uri collectionUri, string test) { List <ResultData> results = new List <ResultData>(); try { bool isConflicts = false; logger.LogInformation($"{test}"); while (!isConflicts) { List <Task <SampleCustomer> > tasks = new List <Task <SampleCustomer> >(); SampleCustomer customer = customerGenerator.Generate(); foreach (DocumentClient client in clients) { tasks.Add(InsertItemAsync(logger, client, collectionUri, customer)); } SampleCustomer[] insertedItems = await Task.WhenAll(tasks); isConflicts = IsConflicts(logger, insertedItems); if (isConflicts) { foreach (var conflict in insertedItems) { try { results.Add(new ResultData() { Test = $"Generated Conflict in container {collectionUri} - Name: {conflict.Name}, City: {conflict.City}, UserDefId: {conflict.UserDefinedId}, Region: {conflict.Region}" }); } catch (Exception ex) { logger.LogError(ex, "test"); } } } } } catch (DocumentClientException dcx) { logger.LogInformation(dcx.Message); } return(results); }
private async Task <List <ResultData> > WriteBenchmark(ILogger logger, DocumentClient client, string distance) { List <ResultData> results = new List <ResultData>(); Stopwatch stopwatch = new Stopwatch(); int i = 0; int total = 100; long lt = 0; double ru = 0; //Write tests for account with Eventual consistency string region = Helpers.ParseEndpoint(client.WriteEndpoint); string consistency = client.ConsistencyLevel.ToString(); logger.LogInformation($"Test {total} writes account in {region} with {consistency} consistency level, and replica {distance} away."); for (i = 0; i < total; i++) { SampleCustomer customer = customerGenerator.Generate(); stopwatch.Start(); ResourceResponse <Document> response = await client.CreateDocumentAsync(containerUri, customer); stopwatch.Stop(); logger.LogInformation($"Write: Item {i} of {total}, Region: {region}, Latency: {stopwatch.ElapsedMilliseconds} ms, Request Charge: {response.RequestCharge} RUs"); lt += stopwatch.ElapsedMilliseconds; ru += response.RequestCharge; stopwatch.Reset(); } results.Add(new ResultData { Test = $"Test with {consistency} Consistency", AvgLatency = (lt / total).ToString(), AvgRU = Math.Round(ru / total).ToString() }); logger.LogInformation("Summary"); logger.LogInformation($"Test 100 writes against account in {region} with {consistency} consistency level, with replica {distance} away"); logger.LogInformation($"Average Latency:\t{(lt / total)} ms"); logger.LogInformation($"Average Request Units:\t{Math.Round(ru / total)} RUs"); return(results); }
private async Task <List <ResultData> > WriteBenchmarkCustomSync(ILogger logger, DocumentClient writeClient, DocumentClient readClient) { List <ResultData> results = new List <ResultData>(); Stopwatch stopwatch = new Stopwatch(); int i = 0; int total = 100; long lt = 0; double ru = 0; long ltAgg = 0; double ruAgg = 0; string writeRegion = Helpers.ParseEndpoint(writeClient.WriteEndpoint); string readRegion = Helpers.ParseEndpoint(readClient.ReadEndpoint); string consistency = writeClient.ConsistencyLevel.ToString(); logger.LogInformation($"Test {total} writes in {writeRegion} with {consistency} consistency between all replicas except {readRegion} with Strong consistency."); PartitionKey partitionKeyValue = new PartitionKey(PartitionKeyValue); for (i = 0; i < total; i++) { SampleCustomer customer = customerGenerator.Generate(); stopwatch.Start(); ResourceResponse <Document> writeResponse = await writeClient.CreateDocumentAsync(containerUri, customer); stopwatch.Stop(); lt += stopwatch.ElapsedMilliseconds; ru += writeResponse.RequestCharge; stopwatch.Reset(); stopwatch.Start(); ResourceResponse <Document> readResponse = await readClient.ReadDocumentAsync(writeResponse.Resource.SelfLink, new RequestOptions { PartitionKey = partitionKeyValue, SessionToken = writeResponse.SessionToken }); stopwatch.Stop(); lt += stopwatch.ElapsedMilliseconds; ru += readResponse.RequestCharge; stopwatch.Reset(); logger.LogInformation($"Write/Read: Item {i} of {total}, Region: {writeRegion}, Latency: {lt} ms, Request Charge: {ru} RUs"); ltAgg += lt; ruAgg += ru; lt = 0; ru = 0; } results.Add(new ResultData { Test = $"Test {total} writes in {writeRegion} with {consistency} consistency between all replicas except {readRegion} with Strong consistency", AvgLatency = (ltAgg / total).ToString(), AvgRU = Math.Round(ruAgg / total).ToString() }); logger.LogInformation("Test Summary"); logger.LogInformation($"Test {total} writes in {writeRegion} with {consistency} consistency between all replicas except {readRegion} with Strong consistency"); logger.LogInformation($"Average Latency:\t{(ltAgg / total)} ms"); logger.LogInformation($"Average Request Units:\t{Math.Round(ruAgg / total)} RUs"); return(results); }
private async Task <SampleCustomer> UpdateItemAsync(ILogger logger, DocumentClient client, Uri collectionUri, SampleCustomer item) { //DeepCopy the item item = Helpers.Clone(item); //Make a change to the item to update. item.Region = Helpers.ParseEndpoint(client.WriteEndpoint); item.UserDefinedId = Helpers.RandomNext(0, 1000); logger.LogInformation($"Update - Name: {item.Name}, City: {item.City}, UserDefId: {item.UserDefinedId}, Region: {item.Region}"); try { var response = await client.ReplaceDocumentAsync(item.SelfLink, item, new RequestOptions { AccessCondition = new AccessCondition { Type = AccessConditionType.IfMatch, Condition = item.ETag } }); return((SampleCustomer)(dynamic)response.Resource); } catch (DocumentClientException ex) { if (ex.StatusCode == HttpStatusCode.PreconditionFailed || ex.StatusCode == HttpStatusCode.NotFound) { //No conflict is induced. return(null); } throw; } }
private async Task <List <ResultData> > GenerateUpdateConflicts(ILogger logger, Uri collectionUri, string test) { List <ResultData> results = new List <ResultData>(); try { bool isConflicts = false; logger.LogInformation($"{test}"); logger.LogInformation($"Inserting an item to create an update conflict on."); //Generate a new customer, set the region property SampleCustomer customer = customerGenerator.Generate(); SampleCustomer insertedItem = await InsertItemAsync(logger, clients[0], collectionUri, customer); logger.LogInformation($"Wait 2 seconds to allow item to replicate."); await Task.Delay(2000); RequestOptions requestOptions = new RequestOptions { PartitionKey = new PartitionKey(PartitionKeyValue) }; while (!isConflicts) { IList <Task <SampleCustomer> > tasks = new List <Task <SampleCustomer> >(); SampleCustomer item = await clients[0].ReadDocumentAsync <SampleCustomer>(insertedItem.SelfLink, requestOptions); logger.LogInformation($"Original - Name: {item.Name}, City: {item.City}, UserDefId: {item.UserDefinedId}, Region: {item.Region}"); foreach (DocumentClient client in clients) { tasks.Add(UpdateItemAsync(logger, client, collectionUri, item)); } SampleCustomer[] updatedItems = await Task.WhenAll(tasks); //Delay to allow data to replicate await Task.Delay(2000); isConflicts = IsConflicts(logger, updatedItems); if (isConflicts) { foreach (var conflict in updatedItems) { try { results.Add(new ResultData() { Test = $"Generated Conflict in container {collectionUri} - Name: {conflict.Name}, City: {conflict.City}, UserDefId: {conflict.UserDefinedId}, Region: {conflict.Region}" }); } catch (Exception ex) { logger.LogError(ex, "test"); } } } } } catch (DocumentClientException dcx) { logger.LogInformation(dcx.Message); } return(results); }
private async Task <SampleCustomer> InsertItemAsync(ILogger logger, DocumentClient client, Uri collectionUri, SampleCustomer item) { //DeepCopy the item item = Helpers.Clone(item); //Update UserDefinedId for each item to random number for Conflict Resolution item.UserDefinedId = Helpers.RandomNext(0, 1000); //Update the write region to the client regions so we know which client wrote the item item.Region = Helpers.ParseEndpoint(client.WriteEndpoint); logger.LogInformation($"Attempting insert - Name: {item.Name}, City: {item.City}, UserDefId: {item.UserDefinedId}, Region: {item.Region}"); try { var response = await client.CreateDocumentAsync(collectionUri, item); return((SampleCustomer)(dynamic)response.Resource); } catch (DocumentClientException ex) { if (ex.StatusCode == System.Net.HttpStatusCode.Conflict) { //Item has already replicated so return null return(null); } if (ex.StatusCode == System.Net.HttpStatusCode.Gone) { return(await InsertItemAsync(logger, client, collectionUri, item)); } throw; } }
//Deep copy Document object public static SampleCustomer Clone(SampleCustomer source) { return(JsonConvert.DeserializeObject <SampleCustomer>(JsonConvert.SerializeObject(source))); }