Example #1
0
        List <BrokeredMessage> CreateTrackingMessages(OrchestrationRuntimeState runtimeState)
        {
            var trackingMessages = new List <BrokeredMessage>();

            // We cannot create tracking messages if runtime state does not have Orchestration InstanceId
            // This situation can happen due to corruption of service bus session state or if somehow first message of orchestration is not execution started
            if (runtimeState == null || runtimeState.OrchestrationInstance == null ||
                string.IsNullOrWhiteSpace(runtimeState.OrchestrationInstance.InstanceId))
            {
                return(trackingMessages);
            }

            // this is to stamp the tracking events with a sequence number so they can be ordered even if
            // writing to a store like azure table
            int historyEventIndex = runtimeState.Events.Count - runtimeState.NewEvents.Count;

            foreach (HistoryEvent he in runtimeState.NewEvents)
            {
                var taskMessage = new TaskMessage
                {
                    Event = he,
                    OrchestrationInstance = runtimeState.OrchestrationInstance
                };

                BrokeredMessage trackingMessage = Utils.GetBrokeredMessageFromObject(
                    taskMessage, settings.MessageCompressionSettings, runtimeState.OrchestrationInstance,
                    "History Tracking Message");
                trackingMessage.ContentType = FrameworkConstants.TaskMessageContentType;
                trackingMessage.SessionId   = runtimeState.OrchestrationInstance.InstanceId;
                trackingMessage.Properties[FrameworkConstants.HistoryEventIndexPropertyName] = historyEventIndex++;
                trackingMessages.Add(trackingMessage);
            }

            var stateMessage = new StateMessage {
                State = BuildOrchestrationState(runtimeState)
            };

            BrokeredMessage brokeredStateMessage = Utils.GetBrokeredMessageFromObject(
                stateMessage, settings.MessageCompressionSettings, runtimeState.OrchestrationInstance,
                "State Tracking Message");

            brokeredStateMessage.SessionId   = runtimeState.OrchestrationInstance.InstanceId;
            brokeredStateMessage.ContentType = FrameworkConstants.StateMessageContentType;
            trackingMessages.Add(brokeredStateMessage);
            return(trackingMessages);
        }
Example #2
0
        protected override async Task OnProcessWorkItem(SessionWorkItem sessionWorkItem)
        {
            MessageSession session = sessionWorkItem.Session;
            IEnumerable <BrokeredMessage> newMessages = sessionWorkItem.Messages;

            var historyEntities = new List <OrchestrationHistoryEventEntity>();
            var stateEntities   = new List <OrchestrationStateEntity>();

            foreach (BrokeredMessage message in newMessages)
            {
                Utils.CheckAndLogDeliveryCount(message, taskHubDescription.MaxTrackingDeliveryCount);

                if (message.ContentType.Equals(FrameworkConstants.TaskMessageContentType,
                                               StringComparison.OrdinalIgnoreCase))
                {
                    object historyEventIndexObj;

                    if (!message.Properties.TryGetValue(FrameworkConstants.HistoryEventIndexPropertyName,
                                                        out historyEventIndexObj) ||
                        historyEventIndexObj == null)
                    {
                        throw new InvalidOperationException(
                                  "Could not find a valid history event index property on tracking message " +
                                  message.MessageId);
                    }

                    var historyEventIndex = (int)historyEventIndexObj;

                    TaskMessage taskMessage = await Utils.GetObjectFromBrokeredMessageAsync <TaskMessage>(message);

                    historyEntities.Add(new OrchestrationHistoryEventEntity(
                                            taskMessage.OrchestrationInstance.InstanceId,
                                            taskMessage.OrchestrationInstance.ExecutionId,
                                            historyEventIndex,
                                            DateTime.UtcNow,
                                            taskMessage.Event));
                }
                else if (message.ContentType.Equals(FrameworkConstants.StateMessageContentType,
                                                    StringComparison.OrdinalIgnoreCase))
                {
                    StateMessage stateMessage = await Utils.GetObjectFromBrokeredMessageAsync <StateMessage>(message);

                    stateEntities.Add(new OrchestrationStateEntity(stateMessage.State));
                }
                else
                {
                    throw new InvalidOperationException("Invalid tracking message content type: " +
                                                        message.ContentType);
                }
            }

            TraceEntities(TraceEventType.Verbose, "Writing tracking history event", historyEntities,
                          GetNormalizedHistoryEventEntityTrace);
            TraceEntities(TraceEventType.Verbose, "Writing tracking state event", stateEntities,
                          GetNormalizedStateEntityTrace);

            try
            {
                await Utils.ExecuteWithRetries(() => tableClient.WriteEntitesAsync(historyEntities),
                                               session.SessionId, string.Format("WriteHistoryEntities:{0}", session.SessionId),
                                               MaxRetriesTableStore,
                                               IntervalBetweenRetriesSecs);
            }
            catch (Exception)
            {
                TraceEntities(TraceEventType.Critical, "Failed to write history entity", historyEntities,
                              GetNormalizedHistoryEventEntityTrace);
                throw;
            }

            try
            {
                foreach (OrchestrationStateEntity stateEntity in stateEntities)
                {
                    await Utils.ExecuteWithRetries(
                        () => tableClient.WriteEntitesAsync(new List <OrchestrationStateEntity> {
                        stateEntity
                    }),
                        session.SessionId, string.Format("WriteStateEntities:{0}", session.SessionId),
                        MaxRetriesTableStore,
                        IntervalBetweenRetriesSecs);
                }
            }
            catch (Exception)
            {
                TraceEntities(TraceEventType.Critical, "Failed to write state entity", stateEntities,
                              GetNormalizedStateEntityTrace);
                throw;
            }

            IEnumerable <Guid> lockTokens = newMessages.Select(m => m.LockToken);

            Utils.SyncExecuteWithRetries <object>(() =>
            {
                session.CompleteBatch(lockTokens);
                return(null);
            },
                                                  session.SessionId,
                                                  "Complete New Tracking Messages",
                                                  MaxRetriesServiceBus,
                                                  IntervalBetweenRetriesSecs);
        }