in src/WebJobs.Extensions.DurableTask/ContextImplementations/DurableEntityContext.cs [647:720]
internal void SendOutbox(OrchestrationContext innerContext, bool writeBackSuccessful, ResponseMessage serializationErrorMessage)
{
lock (this.outbox)
{
foreach (var message in this.outbox)
{
if (message is LockMessage lockMessage)
{
this.Config.TraceHelper.SendingEntityMessage(
this.InstanceId,
this.ExecutionId,
lockMessage.Target.InstanceId,
lockMessage.EventName,
lockMessage.EventContent);
innerContext.SendEvent(lockMessage.Target, lockMessage.EventName, lockMessage.EventContent);
}
else if (message is ResultMessage resultMessage)
{
// Since for all of the operations in the batch, their effect on the entity state
// is lost, we don't want the calling orchestrations to think everything is o.k.
// They should be notified, so we replace all non-error operation results
// with an exception result.
if (!writeBackSuccessful && !resultMessage.IsError)
{
resultMessage.EventContent = serializationErrorMessage;
}
this.Config.TraceHelper.SendingEntityMessage(
this.InstanceId,
this.ExecutionId,
resultMessage.Target.InstanceId,
resultMessage.EventName,
resultMessage.EventContent);
innerContext.SendEvent(resultMessage.Target, resultMessage.EventName, resultMessage.EventContent);
}
else if (!writeBackSuccessful)
{
// all other messages (signals and fire-and-forget) are suppressed if the writeback failed
// this helps to keep the observer pattern correct, for example.
}
else if (message is OperationMessage operationMessage)
{
if (!operationMessage.EventContent.ScheduledTime.HasValue)
{
this.State.MessageSorter.LabelOutgoingMessage(operationMessage.EventContent, operationMessage.Target.InstanceId, DateTime.UtcNow, this.Config.MessageReorderWindow);
}
this.Config.TraceHelper.SendingEntityMessage(
this.InstanceId,
this.ExecutionId,
operationMessage.Target.InstanceId,
operationMessage.EventName,
operationMessage.EventContent);
innerContext.SendEvent(operationMessage.Target, operationMessage.EventName, operationMessage.EventContent);
}
else if (message is FireAndForgetMessage fireAndForgetMessage)
{
var dummyTask = innerContext.CreateSubOrchestrationInstance<object>(
fireAndForgetMessage.FunctionName,
this.Config.Options.DefaultVersion,
fireAndForgetMessage.InstanceId,
fireAndForgetMessage.Input,
new Dictionary<string, string>() { { OrchestrationTags.FireAndForget, "" } });
System.Diagnostics.Debug.Assert(dummyTask.IsCompleted, "task should be fire-and-forget");
}
}
this.outbox.Clear();
}
}