public async void ReverseLocalTransaction(Guid shardId, string type, int pos) { var operation = await _shardRepository.GetShardWriteOperationAsync(shardId, pos); if (operation != null) { await _shardRepository.AddDataReversionRecordAsync(new DataReversionRecord() { OriginalOperation = operation, NewData = operation.Data, OriginalData = await _dataRouter.GetDataAsync(type, operation.Data.Id), RevertedTime = DateTime.Now }); ShardData data = operation.Data; SortedDictionary <int, ShardWriteOperation> allOperations; ShardWriteOperation lastObjectOperation = null; if (operation.Operation == ShardOperationOptions.Update || operation.Operation == ShardOperationOptions.Delete) { allOperations = await _shardRepository.GetAllObjectShardWriteOperationAsync(data.ShardId.Value, data.Id); lastObjectOperation = allOperations.Where(ao => ao.Key < operation.Pos).Last().Value; } switch (operation.Operation) { case ShardOperationOptions.Create: data = await _dataRouter.GetDataAsync(type, operation.Data.Id); if (data != null) { _logger.LogInformation(_nodeStateService.GetNodeLogId() + "Reverting create with deletion of " + data); await _dataRouter.DeleteDataAsync(data); } break; // Put the data back in the right position case ShardOperationOptions.Delete: await _dataRouter.InsertDataAsync(lastObjectOperation.Data); break; case ShardOperationOptions.Update: await _dataRouter.UpdateDataAsync(lastObjectOperation.Data); break; } await _shardRepository.RemoveShardWriteOperationAsync(shardId, operation.Pos); } //Update the cache _shardLastOperationCache.Remove(operation.Data.ShardId.Value, out _); }
public async Task <ShardData> GetData(Guid objectId, string type, int timeoutMs, Guid?shardId = null) { Guid?FoundShard = null; Guid?FoundOnNode = null; var currentTime = DateTime.Now; if (shardId == null) { var shards = _stateMachine.GetAllPrimaryShards(type); bool foundResult = false; ShardData finalObject = null; var totalRespondedShards = 0; var tasks = shards.Select(async shard => { if (shard.Value != _nodeStateService.Id) { try { var result = await _clusterClient.Send(shard.Value, new RequestDataShard() { ObjectId = objectId, ShardId = shard.Key, //Set the shard Type = type }); if (result.IsSuccessful) { foundResult = true; finalObject = result.Data; FoundShard = result.ShardId; FoundOnNode = result.NodeId; } Interlocked.Increment(ref totalRespondedShards); } catch (Exception e) { _logger.LogError(_nodeStateService.GetNodeLogId() + "Error thrown while getting " + e.Message); } } else { finalObject = await _dataRouter.GetDataAsync(type, objectId); foundResult = finalObject != null ? true : false; FoundShard = shard.Key; FoundShard = shard.Value; Interlocked.Increment(ref totalRespondedShards); } }); //Don't await, this will trigger the tasks Task.WhenAll(tasks); while (!foundResult && totalRespondedShards < shards.Count) { if ((DateTime.Now - currentTime).TotalMilliseconds > timeoutMs) { throw new ClusterOperationTimeoutException("Get data request for object " + objectId + " from shard " + shardId + " timed out."); } await Task.Delay(10); } return(finalObject); } else { return(await _dataRouter.GetDataAsync(type, objectId)); } }