1

So, I have a scenario in which I periodically call SignalWorkflowExecution() passing in a request for work flow signalling. In the Decider I have coded, I see it then receive on its next poll request, the signal in the history of events (and a decision task started just after it).

My question is, how do I prevent processing that signal a second time? That is, if I get the signal, then submit a new activity for work, won't the signal still be in the history of events? I don't see a way to correlate the signal with any subsequent decision task, and maintaining state in a Decider is not a recommended practice, since that is what the SWF is intended to be.

Is the Decider expected to also poll other tasklists? That is, if my Decider receives a signal to perform action A, and it then creates a new decision to schedule activity A on tasklist X (where workers for action A are polling), then is the Decider expected to poll tasklist X also to see if an activity has already been scheduled for action A? Otherwise, I don't see how you avoid processing signals over and over again each time it gets a new signal, all the previous signals are in the history, so how do I avoid reprocessing them?

I can't find a lot of info on working with signals. I only see one page, and it doesn't explain how to handle signals in the decider.

I just need to know the "right" way to handle signals in the workflow.

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
superqd
  • 333
  • 4
  • 12
  • What client side framework and language do you use? AWS Flow Framework takes care of all this complexity for you. – Maxim Fateev Aug 25 '17 at 02:27
  • I am using the C# AWS SDK. The SDK doesn't process signals, you have to poll for them, and iterate over the history of events yourself in the decider. SWF itself will auto generate a decision task upon receiving a signal so that the decision task will be sent to the decider,I don't what you mean by it takes care of the complexity for you, since I have things implemented and it just cycles forever getting the signals and submitting new activity requests with no way to know it's already processed a given signal. This is what the docs say to do - process the history yourself to get the signals – superqd Aug 25 '17 at 03:45

2 Answers2

1

When you are calling PollForDecisionTask, one of the parameters on the response is previousStartedEventId (emphasis added):

The ID of the DecisionTaskStarted event of the previous decision task of this workflow execution that was processed by the decider. This can be used to determine the events in the history new since the last decision task received by the decider.

Generally, each decision task should handle new events since the previous decision task. This is true for more than just signals - it works the same for completed activity tasks, child workflows, cancel requests, etc.

Kobi
  • 135,331
  • 41
  • 252
  • 292
  • 2
    Ahhhh. So I should only process signals newer than the last decision task received. That seems workable. Thanks. – superqd Aug 28 '17 at 14:54
  • 1
    This is a little late, but if you only plan to look at the last few events (since the last decision task), then you should make sure to load the history in reverse order until you get to the previousStartedEventId. Otherwise, for a workflow with many events, you could end up having to load several thousand history events rather than loading (more or less) only those that are new. – Matthew Pope Aug 02 '18 at 04:27
0

It is quite difficult and error prone to program Amazon SWF directly using its .NET SDK. If you wish to stick to your implementation then Kobi's answer is the right one to follow.

However you might find the Guflow, an open source C#.NET library to program Amazon SWF, quite useful.I'm the author of this library. Here is one example which shows how easily you can pause and signal your workflow:

[WorkflowDescription("1.0")]
public class OrderWorkflow : Workflow
{
    public OrderWorkflow()
    {
        ScheduleActivity<ReserveOrder>().OnFailure(PauseWhenItemIsNotAvailable);

        ScheduleActivity<ChargeCustomer>().AfterActivity<ReserveOrder>();

        ScheduleActivity<ShipOrder>().AfterActivity<ChargeCustomer>();
    }

    private WorkflowAction PauseWhenItemIsNotAvailable(ActivityFailedEvent e)
    {
        return e.Reason == "NotAvailable" ? Ignore : DefaultAction(e);
    }
    [WorkflowEvent(EventName.Signal)]
    public WorkflowAction SignalEvent(WorkflowSignaledEvent @event)
    {
        if (@event.SignalName == "ItemsArrived" && Activity<ReserveOrder>().LastFailedEvent()?.Reason=="NotAvailable")
            return Jump.ToActivity<ReserveOrder>();
        return Ignore;
    }
}
Gurmit Teotia
  • 179
  • 2
  • 7