private async Task ChangeStatusOfNumericRangeExecutionAsync(BlockExecutionChangeStatusRequest changeStatusRequest) { try { using (var connection = await CreateNewConnectionAsync(changeStatusRequest.TaskId).ConfigureAwait(false)) { var command = connection.CreateCommand(); command.CommandTimeout = ConnectionStore.Instance.GetConnection(changeStatusRequest.TaskId).QueryTimeoutSeconds; command.CommandText = GetNumericRangeUpdateQuery(changeStatusRequest.BlockExecutionStatus); command.Parameters.Add("@BlockExecutionId", SqlDbType.BigInt).Value = long.Parse(changeStatusRequest.BlockExecutionId); command.Parameters.Add("@BlockExecutionStatus", SqlDbType.TinyInt).Value = (byte)changeStatusRequest.BlockExecutionStatus; command.Parameters.Add("@ItemsCount", SqlDbType.Int).Value = changeStatusRequest.ItemsProcessed; await command.ExecuteNonQueryAsync().ConfigureAwait(false); } } catch (SqlException sqlEx) { if (TransientErrorDetector.IsTransient(sqlEx)) { throw new TransientException("A transient exception has occurred", sqlEx); } throw; } }
public async Task UpdateListBlockItemAsync(SingleUpdateRequest singeUpdateRequest) { try { using (var connection = await CreateNewConnectionAsync(singeUpdateRequest.TaskId).ConfigureAwait(false)) { var command = connection.CreateCommand(); command.CommandTimeout = ConnectionStore.Instance.GetConnection(singeUpdateRequest.TaskId).QueryTimeoutSeconds; command.CommandText = ListBlockQueryBuilder.UpdateSingleBlockListItemStatus; command.Parameters.Add("@BlockId", SqlDbType.BigInt).Value = long.Parse(singeUpdateRequest.ListBlockId); command.Parameters.Add("@ListBlockItemId", SqlDbType.BigInt).Value = long.Parse(singeUpdateRequest.ListBlockItem.ListBlockItemId); command.Parameters.Add("@Status", SqlDbType.TinyInt).Value = (byte)singeUpdateRequest.ListBlockItem.Status; if (singeUpdateRequest.ListBlockItem.StatusReason == null) { command.Parameters.Add("@StatusReason", SqlDbType.NVarChar, -1).Value = DBNull.Value; } else { command.Parameters.Add("@StatusReason", SqlDbType.NVarChar, -1).Value = singeUpdateRequest.ListBlockItem.StatusReason; } if (!singeUpdateRequest.ListBlockItem.Step.HasValue) { command.Parameters.Add("@Step", SqlDbType.TinyInt).Value = DBNull.Value; } else { command.Parameters.Add("@Step", SqlDbType.TinyInt).Value = singeUpdateRequest.ListBlockItem.Step; } await command.ExecuteNonQueryAsync().ConfigureAwait(false); } } catch (SqlException sqlEx) { if (TransientErrorDetector.IsTransient(sqlEx)) { throw new TransientException("A transient exception has occurred", sqlEx); } throw; } }
public ObjectBlock <T> GetLastObjectBlock <T>(LastBlockRequest lastRangeBlockRequest) { var taskDefinition = _taskRepository.EnsureTaskDefinition(lastRangeBlockRequest.TaskId); try { using (var connection = CreateNewConnection(lastRangeBlockRequest.TaskId)) { var command = connection.CreateCommand(); command.CommandText = ObjectBlockQueryBuilder.GetLastObjectBlock; command.CommandTimeout = ConnectionStore.Instance.GetConnection(lastRangeBlockRequest.TaskId).QueryTimeoutSeconds; command.Parameters.Add("@TaskDefinitionId", SqlDbType.Int).Value = taskDefinition.TaskDefinitionId; using (var reader = command.ExecuteReader()) { while (reader.Read()) { var blockId = reader["BlockId"].ToString(); var objectDataXml = reader["ObjectData"].ToString(); T objectData = SerializedValueReader.ReadValue <T>(reader, "ObjectData", "CompressedObjectData"); return(new ObjectBlock <T>() { Object = objectData, ObjectBlockId = blockId }); } } } } catch (SqlException sqlEx) { if (TransientErrorDetector.IsTransient(sqlEx)) { throw new TransientException("A transient exception has occurred", sqlEx); } throw; } return(null); }
public async Task <ProtoListBlock> GetLastListBlockAsync(LastBlockRequest lastRangeBlockRequest) { var taskDefinition = await _taskRepository.EnsureTaskDefinitionAsync(lastRangeBlockRequest.TaskId).ConfigureAwait(false); try { using (var connection = await CreateNewConnectionAsync(lastRangeBlockRequest.TaskId).ConfigureAwait(false)) { var command = connection.CreateCommand(); command.CommandText = ListBlockQueryBuilder.GetLastListBlock; command.CommandTimeout = ConnectionStore.Instance.GetConnection(lastRangeBlockRequest.TaskId).QueryTimeoutSeconds; command.Parameters.Add("@TaskDefinitionId", SqlDbType.Int).Value = taskDefinition.TaskDefinitionId; using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) { while (await reader.ReadAsync().ConfigureAwait(false)) { var listBlock = new ProtoListBlock(); listBlock.ListBlockId = reader["BlockId"].ToString(); listBlock.Items = await GetListBlockItemsAsync(lastRangeBlockRequest.TaskId, listBlock.ListBlockId).ConfigureAwait(false); listBlock.Header = SerializedValueReader.ReadValueAsString(reader, "ObjectData", "CompressedObjectData"); return(listBlock); } } } } catch (SqlException sqlEx) { if (TransientErrorDetector.IsTransient(sqlEx)) { throw new TransientException("A transient exception has occurred", sqlEx); } throw; } return(null); }
public void ChangeStatus(BlockExecutionChangeStatusRequest changeStatusRequest) { try { using (var connection = CreateNewConnection(changeStatusRequest.TaskId)) { var command = connection.CreateCommand(); command.CommandTimeout = ConnectionStore.Instance.GetConnection(changeStatusRequest.TaskId).QueryTimeoutSeconds; command.CommandText = GetListUpdateQuery(changeStatusRequest.BlockExecutionStatus); command.Parameters.Add("@BlockExecutionId", SqlDbType.BigInt).Value = long.Parse(changeStatusRequest.BlockExecutionId); command.Parameters.Add("@BlockExecutionStatus", SqlDbType.TinyInt).Value = (byte)changeStatusRequest.BlockExecutionStatus; command.ExecuteNonQuery(); } } catch (SqlException sqlEx) { if (TransientErrorDetector.IsTransient(sqlEx)) { throw new TransientException("A transient exception has occurred", sqlEx); } throw; } }
public async Task <RangeBlock> GetLastRangeBlockAsync(LastBlockRequest lastRangeBlockRequest) { var taskDefinition = await _taskRepository.EnsureTaskDefinitionAsync(lastRangeBlockRequest.TaskId).ConfigureAwait(false); var query = string.Empty; if (lastRangeBlockRequest.BlockType == BlockType.DateRange) { query = RangeBlockQueryBuilder.GetLastDateRangeBlock(lastRangeBlockRequest.LastBlockOrder); } else if (lastRangeBlockRequest.BlockType == BlockType.NumericRange) { query = RangeBlockQueryBuilder.GetLastNumericRangeBlock(lastRangeBlockRequest.LastBlockOrder); } else { throw new ArgumentException("An invalid BlockType was supplied: " + lastRangeBlockRequest.BlockType); } try { using (var connection = await CreateNewConnectionAsync(lastRangeBlockRequest.TaskId).ConfigureAwait(false)) { var command = connection.CreateCommand(); command.CommandText = query; command.CommandTimeout = ConnectionStore.Instance.GetConnection(lastRangeBlockRequest.TaskId).QueryTimeoutSeconds; command.Parameters.Add("@TaskDefinitionId", SqlDbType.Int).Value = taskDefinition.TaskDefinitionId; using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) { while (await reader.ReadAsync().ConfigureAwait(false)) { var rangeBlockId = reader["BlockId"].ToString(); long rangeBegin; long rangeEnd; if (lastRangeBlockRequest.BlockType == BlockType.DateRange) { rangeBegin = reader.GetDateTime(2).Ticks; //DateTime.Parse(reader["FromDate"].ToString()).Ticks; rangeEnd = reader.GetDateTime(3).Ticks; //DateTime.Parse(reader["ToDate"].ToString()).Ticks; } else { rangeBegin = long.Parse(reader["FromNumber"].ToString()); rangeEnd = long.Parse(reader["ToNumber"].ToString()); } return(new RangeBlock(rangeBlockId, 0, rangeBegin, rangeEnd, lastRangeBlockRequest.BlockType)); } } } } catch (SqlException sqlEx) { if (TransientErrorDetector.IsTransient(sqlEx)) { throw new TransientException("A transient exception has occurred", sqlEx); } throw; } return(null); }
public async Task <LeaseResponse> TryAcquireLeaseAsync(AcquireLeaseRequest acquireLeaseRequest) { using (SqlConnection conn = await ConnectionHelper.GetOpenConnectionAsync(connectionString)) { SqlTransaction transaction = conn.BeginTransaction(IsolationLevel.Serializable); SqlCommand command = conn.CreateCommand(); command.Transaction = transaction; try { // obtain lock on the record blocking other nodes until the transaction is committed command.CommandText = "UPDATE [RBR].[ResourceGroups] SET LockedByClient = @ClientId WHERE ResourceGroup = @ResourceGroup"; command.Parameters.AddWithValue("@ClientId", acquireLeaseRequest.ClientId); command.Parameters.Add("@ResourceGroup", SqlDbType.VarChar, 100).Value = acquireLeaseRequest.ResourceGroup; await command.ExecuteNonQueryAsync(); // get the resource group (TODO, use OUTPUT on UPDATE query instead of another query) command.Parameters.Clear(); command.CommandText = @"SELECT [ResourceGroup] ,[CoordinatorId] ,[LastCoordinatorRenewal] ,[CoordinatorServer] ,[LockedByClient] ,[FencingToken] ,[LeaseExpirySeconds] ,[HeartbeatSeconds] ,GETUTCDATE() AS [TimeNow] FROM [RBR].[ResourceGroups] WHERE ResourceGroup = @ResourceGroup"; command.Parameters.Add("@ResourceGroup", SqlDbType.VarChar, 100).Value = acquireLeaseRequest.ResourceGroup; ResourceGroup rg = null; using (SqlDataReader reader = await command.ExecuteReaderAsync()) { if (await reader.ReadAsync()) { rg = new ResourceGroup { Name = acquireLeaseRequest.ResourceGroup, CoordinatorId = GetGuidFromNullableGuid(reader, "CoordinatorId"), CoordinatorServer = GetStringFromNullableGuid(reader, "CoordinatorServer"), LastCoordinatorRenewal = GetDateTimeFromNullable(reader, "LastCoordinatorRenewal"), TimeNow = (DateTime)reader["TimeNow"], LockedByClientId = GetGuidFromNullableGuid(reader, "LockedByClient"), FencingToken = (int)reader["FencingToken"], LeaseExpirySeconds = (int)reader["LeaseExpirySeconds"], HeartbeatSeconds = (int)reader["HeartbeatSeconds"] }; } } if (rg == null) { return(new LeaseResponse { Result = LeaseResult.NoLease, Lease = new Lease { ExpiryPeriod = TimeSpan.FromMinutes(1), HeartbeatPeriod = TimeSpan.FromSeconds(25) } }); } // determine the response, if the CoordinatorId is empty or expired then grant, else deny LeaseResponse response = new() { Lease = new Lease() }; if (rg.CoordinatorId == Guid.Empty || (rg.TimeNow - rg.LastCoordinatorRenewal).TotalSeconds > rg.LeaseExpirySeconds) { response.Lease.ResourceGroup = acquireLeaseRequest.ResourceGroup; response.Lease.ClientId = acquireLeaseRequest.ClientId; response.Lease.ExpiryPeriod = TimeSpan.FromSeconds(rg.LeaseExpirySeconds); response.Lease.HeartbeatPeriod = TimeSpan.FromSeconds(rg.HeartbeatSeconds); response.Lease.FencingToken = ++rg.FencingToken; response.Result = LeaseResult.Granted; command.Parameters.Clear(); command.CommandText = @"UPDATE [RBR].[ResourceGroups] SET [CoordinatorId] = @ClientId ,[LastCoordinatorRenewal] = GETUTCDATE() ,[CoordinatorServer] = @Server ,[FencingToken] = @FencingToken WHERE ResourceGroup = @ResourceGroup"; command.Parameters.AddWithValue("@ClientId", acquireLeaseRequest.ClientId); command.Parameters.AddWithValue("@FencingToken", response.Lease.FencingToken); command.Parameters.Add("@Server", SqlDbType.NVarChar, 500).Value = Environment.MachineName; command.Parameters.Add("@ResourceGroup", SqlDbType.VarChar, 100).Value = acquireLeaseRequest.ResourceGroup; await command.ExecuteNonQueryAsync(); } else { response.Lease.ExpiryPeriod = TimeSpan.FromSeconds(rg.LeaseExpirySeconds); response.Lease.HeartbeatPeriod = TimeSpan.FromSeconds(rg.HeartbeatSeconds); response.Result = LeaseResult.Denied; } transaction.Commit(); return(response); } catch (Exception ex) { try { logger.Error("Rolling back lease acquisition: ", ex); transaction.Rollback(); } catch (Exception rex) { logger.Error("Rollback of lease acquisition failed: ", rex); } return(new LeaseResponse { Result = TransientErrorDetector.IsTransient(ex) ? LeaseResult.TransientError : LeaseResult.Error, Message = "Lease acquisition failure", Exception = ex }); } } }
public async Task <IList <ProtoListBlockItem> > GetListBlockItemsAsync(TaskId taskId, string listBlockId) { var results = new List <ProtoListBlockItem>(); try { using (var connection = await CreateNewConnectionAsync(taskId).ConfigureAwait(false)) { var command = connection.CreateCommand(); command.CommandText = ListBlockQueryBuilder.GetListBlockItems; command.CommandTimeout = ConnectionStore.Instance.GetConnection(taskId).QueryTimeoutSeconds; command.Parameters.Add("@BlockId", SqlDbType.BigInt).Value = long.Parse(listBlockId); using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) { while (await reader.ReadAsync().ConfigureAwait(false)) { var listBlock = new ProtoListBlockItem(); listBlock.ListBlockItemId = reader["ListBlockItemId"].ToString(); listBlock.Value = SerializedValueReader.ReadValueAsString(reader, "Value", "CompressedValue"); listBlock.Status = (ItemStatus)int.Parse(reader["Status"].ToString()); if (reader["LastUpdated"] == DBNull.Value) { listBlock.LastUpdated = DateTime.MinValue; } else { listBlock.LastUpdated = reader.GetDateTime(5); } if (reader["StatusReason"] == DBNull.Value) { listBlock.StatusReason = null; } else { listBlock.StatusReason = reader.GetString(6); } if (reader["Step"] == DBNull.Value) { listBlock.Step = null; } else { listBlock.Step = reader.GetByte(7); } results.Add(listBlock); } } } } catch (SqlException sqlEx) { if (TransientErrorDetector.IsTransient(sqlEx)) { throw new TransientException("A transient exception has occurred", sqlEx); } throw; } return(results); }