Step Functions: apply try-catch to a block of states

Written by theburningmonk | Published 2018/08/12
Tech Story Tags: swift | block-of-states | apply-try-catch | coding | burning-monk

TLDRvia the TL;DR App

In my last post we talked about how we can imple­ment sem­a­phores with Step Func­tions. Anoth­er com­mon sce­nario that many peo­ple have is to han­dle errors from a block of states like we’re used to with a try-catch block.

try {step1()step2()step3()} catch (States.Timeout) {...} catch (States.ALL) {...}

With Step Func­tions, you can use Retry and Catch claus­es to han­dle errors from Task states. There are a num­ber of pre­de­fined sys­tem errors, and you can also han­dle cus­tom errors that are thrown by your Lamb­da func­tions.

You can do this by adding the same Catch clause to each of the Task states.

"Catch": [{"ErrorEquals": [ "States.ALL" ],"Next": "NotifyError"}]

How­ev­er, this approach requires you to add the same boil­er­plate to every Task state. As your error han­dling strat­e­gy, or the state machine itself becomes more com­plex, this becomes a main­te­nance headache.

For­tu­nate­ly, both Retry and Catch can be used on Parallel states too!

Even if you’re not look­ing to per­form tasks in par­al­lel, you can still use it to sim­pli­fy your error han­dling.

In this case, if I wrap Step1, Step2 and Step3 into a sin­gle branch inside a Parallel state, then I can catch unhan­dled errors from any of the steps with one Catch clause.

{"StartAt": "Try","States": {"Try": {"Type": "Parallel","Branches": [{"StartAt": "Step1","States": {"Step1": {"Type": "Task","Resource": "...","Next": "Step2"},"Step2": {"Type": "Task","Resource": "...","Next": "Step3"},"Step3": {"Type": "Task","Resource": "...","End": true}}}],"Catch": [{"ErrorEquals": [ "States.ALL" ],"Next": "NotifyError"}],"Next": "NotifySuccess"},...}

One final caveat with this approach is that, a Parallel state wraps the out­put from its branch­es into an array. So if sub­se­quent states?—?such as the NotifySuccess state in the exam­ple above?—?wants to use the out­put from Step3 then it’ll have to take that into con­sid­er­a­tion.

What you can do instead, is to add a Pass state to unwrap the array, like this:

"UnwrapOutput": {"Type": "Pass","InputPath": "$[0]","Next": "NotifySuccess"}

This tech­nique is use­ful when you want to apply the same error han­dling to block of states with­out hav­ing to resort­ing to boil­er­plates.

You can add Retry clause to the Parallel state to retry the entire block (i.e. from Step1, even if Step3 errored). You can also add Retry and Catch for indi­vid­ual states to mix things up too.

So that’s it, a nice and short post to share with you a sim­ple tech­nique that I have found use­ful with Step Func­tions.

I have been spend­ing a fair bit of time with Step Func­tions and enjoy­ing the ser­vice. Let me know in the com­ments if you have use cas­es that you find dif­fi­cult to imple­ment with Step Func­tions, I would love to hear what oth­ers are doing with it.

Hi, my name is Yan Cui. I’m an AWS Serverless Hero and the author of Production-Ready Serverless. I have run production workload at scale in AWS for nearly 10 years and I have been an architect or principal engineer with a variety of industries ranging from banking, e-commerce, sports streaming to mobile gaming. I currently work as an independent consultant focused on AWS and serverless.

You can contact me via Email, Twitter and LinkedIn.

Check out my new course, Complete Guide to AWS Step Functions.

In this course, we’ll cover everything you need to know to use AWS Step Functions service effectively. Including basic concepts, HTTP and event triggers, activities, design patterns and best practices.

Get your copy here.

Come learn about operational BEST PRACTICES for AWS Lambda: CI/CD, testing & debugging functions locally, logging, monitoring, distributed tracing, canary deployments, config management, authentication & authorization, VPC, security, error handling, and more.

You can also get 40% off the face price with the code ytcui.

Get your copy here.


Written by theburningmonk | AWS Serverless Hero. Independent Consultant. Developer Advocate at Lumigo.
Published by HackerNoon on 2018/08/12