public override async Task CompleteTaskActivityWorkItemAsync(TaskActivityWorkItem workItem, TaskMessage responseMessage) { using SqlConnection connection = await this.GetAndOpenConnectionAsync(); using SqlCommand command = this.GetSprocCommand(connection, "dt._CompleteTasks"); command.Parameters.AddMessageIdParameter("@CompletedTasks", workItem.TaskMessage); command.Parameters.AddTaskEventsParameter("@Results", responseMessage); OrchestrationInstance instance = workItem.TaskMessage.OrchestrationInstance; try { await SqlUtils.ExecuteNonQueryAsync(command, this.traceHelper, instance.InstanceId); } catch (SqlException e) when(e.Number == 50002) { // 50002 is the error code when we fail to delete the source message. This is expected to mean that // a task activity has executed twice, likely because of an unexpected lock expiration. string taskName = DTUtils.GetName(workItem.TaskMessage.Event) ?? "Unknown"; this.traceHelper.DuplicateExecutionDetected(instance, taskName); return; } // signal the orchestration loop to poll immediately this.orchestrationBackoffHelper.Reset(); }
public override async Task <TaskActivityWorkItem?> LockNextTaskActivityWorkItem(TimeSpan receiveTimeout, CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { using SqlConnection connection = await this.GetAndOpenConnectionAsync(); using SqlCommand command = this.GetSprocCommand(connection, "dt._LockNextTask"); DateTime lockExpiration = DateTime.UtcNow.Add(this.settings.WorkItemLockTimeout); command.Parameters.Add("@LockedBy", SqlDbType.VarChar, size: 100).Value = this.lockedByValue; command.Parameters.Add("@LockExpiration", SqlDbType.DateTime2).Value = lockExpiration; using DbDataReader reader = await SqlUtils.ExecuteReaderAsync( command, this.traceHelper, instanceId : null, cancellationToken); if (!await reader.ReadAsync()) { await this.activityBackoffHelper.WaitAsync(cancellationToken); continue; } this.activityBackoffHelper.Reset(); TaskMessage message = reader.GetTaskMessage(); int dequeueCount = reader.GetInt32("DequeueCount"); // TODO: poison message handling for high dequeue counts return(new TaskActivityWorkItem { Id = $"{message.OrchestrationInstance.InstanceId}:{DTUtils.GetTaskEventId(message.Event):X16}", TaskMessage = message, LockedUntilUtc = lockExpiration, }); } // host is shutting down return(null); }