protected override void IndexCore(string partitionName, IEnumerable <TIndexed> items) { var batch = new TableBatchOperation(); foreach (var item in items) { batch.Add(TableOperation.InsertOrReplace(ToTableEntity(item))); } var table = GetCloudTable(); var options = new TableRequestOptions() { PayloadFormat = TablePayloadFormat.Json, MaximumExecutionTime = _Timeout, ServerTimeout = _Timeout, }; var context = new OperationContext(); Queue <TableBatchOperation> batches = new Queue <TableBatchOperation>(); batches.Enqueue(batch); while (batches.Count > 0) { batch = batches.Dequeue(); try { Stopwatch watch = new Stopwatch(); watch.Start(); if (batch.Count > 1) { table.ExecuteBatchAsync(batch, options, context).GetAwaiter().GetResult(); } else { if (batch.Count == 1) { table.ExecuteAsync(batch[0], options, context).GetAwaiter().GetResult(); } } Interlocked.Add(ref _IndexedEntities, batch.Count); } catch (Exception ex) { if (IsError413(ex)) { var split = batch.Count / 2; var batch1 = batch.Take(split).ToList(); var batch2 = batch.Skip(split).Take(batch.Count - split).ToList(); batches.Enqueue(ToBatch(batch1)); batches.Enqueue(ToBatch(batch2)); } else if (Helper.IsError(ex, "EntityTooLarge")) { var op = GetFaultyOperation(ex, batch); var entity = (DynamicTableEntity)GetEntity(op); var serialized = entity.Serialize(); Configuration .GetBlocksContainer() .GetBlockBlobReference(entity.GetFatBlobName()) .UploadFromByteArrayAsync(serialized, 0, serialized.Length).GetAwaiter().GetResult(); entity.MakeFat(serialized.Length); batches.Enqueue(batch); } else { IndexerTrace.ErrorWhileImportingEntitiesToAzure(batch.Select(b => GetEntity(b)).ToArray(), ex); batches.Enqueue(batch); throw; } } } }
protected override void IndexCore(string partitionName, IEnumerable <TIndexed> items) { var batch = new TableBatchOperation(); foreach (var item in items) { batch.Add(TableOperation.InsertOrReplace(ToTableEntity(item))); } var table = GetCloudTable(); var options = new TableRequestOptions() { PayloadFormat = TablePayloadFormat.Json, MaximumExecutionTime = _Timeout, ServerTimeout = _Timeout, }; var context = new OperationContext(); Queue <TableBatchOperation> batches = new Queue <TableBatchOperation>(); batches.Enqueue(batch); while (batches.Count > 0) { batch = batches.Dequeue(); try { Stopwatch watch = new Stopwatch(); watch.Start(); if (batch.Count > 1) { table.ExecuteBatchAsync(batch, options, context).GetAwaiter().GetResult(); } else { if (batch.Count == 1) { table.ExecuteAsync(batch[0], options, context).GetAwaiter().GetResult(); } } Interlocked.Add(ref _IndexedEntities, batch.Count); } catch (Exception ex) { if (IsError413(ex) /* Request too large */ || Helper.IsError(ex, "OperationTimedOut")) { // Reduce the size of all batches to half the size of the offending batch. int maxSize = Math.Max(1, batch.Count / 2); bool workDone = false; Queue <TableBatchOperation> newBatches = new Queue <TableBatchOperation>(); for (/* starting with the current batch */; ; batch = batches.Dequeue()) { for (; batch.Count > maxSize;) { newBatches.Enqueue(ToBatch(batch.Take(maxSize).ToList())); batch = ToBatch(batch.Skip(maxSize).ToList()); workDone = true; } if (batch.Count > 0) { newBatches.Enqueue(batch); } if (batches.Count == 0) { break; } } batches = newBatches; // Nothing could be done? if (!workDone) { throw; } } else if (Helper.IsError(ex, "EntityTooLarge")) { var op = GetFaultyOperation(ex, batch); var entity = (DynamicTableEntity)GetEntity(op); var serialized = entity.Serialize(); Configuration .GetBlocksContainer() .GetBlockBlobReference(entity.GetFatBlobName()) .UploadFromByteArrayAsync(serialized, 0, serialized.Length).GetAwaiter().GetResult(); entity.MakeFat(serialized.Length); batches.Enqueue(batch); } else { IndexerTrace.ErrorWhileImportingEntitiesToAzure(batch.Select(b => GetEntity(b)).ToArray(), ex); batches.Enqueue(batch); throw; } } } }