During this exercise, you will:
- raise and handle exceptions in Temporal Workflows and Activities
- Use non-retryable errors to fail an Activity
- Locate the details of a failure in Temporal Workflows and Activities in the Event History
Make your changes to the code in the practice
subdirectory (look for TODO
comments that will guide you to where you should make changes to the code). If
you need a hint or want to verify your changes, look at the complete version in
the solution
subdirectory.
You'll need two terminal windows for this exercise.
- In all terminals, change to the
exercises/handling-errors/practice
directory using the following command:cd exercises/handling-errors/practice
In this part of the exercise, you will raise a non-retryable Application Failure
(represented in Python as ApplicationError
) that will fail your Activities.
Application Failures are used to communicate application-specific failures in
Workflows and Activities. In Activities, raising an ApplicationError
will
cause the Activity to fail. However, this unless this Activity is specified as
non-retryable, it will retry according to the Retry Policy. To have an Activity
fail when an ApplicationError
is raised, set it as non-retryable. Any other
exception that is raised in a Python activity is automatically converted to an ApplicationError
upon being raised.
- Open the
shared.py
file and familiarize yourself with the dataclasses you will be using during the exercise. Pay particular attention to the custom error definitions. - Open the
activities.py
file in your text editor. - In the
send_bill
Activity, notice how an error is raised if thechargeAmount
is less than 0. If the calculated amount to charge the customer is negative, a non-retryableApplicationError
is raised. It is important to use a non-retryable failure here, as you want to fail the Activity if the amount was calculated to be negative. In this error, we pass a reason for the failure and the type of error that is being converted to anApplicationError
. - Go to
process_credit_card
Activity, where you will raise anApplicationError
if the credit card fails its validation step. In this Activity, you will raise an error if the entered credit card number does not have 16 digits. Use theApplicationError
code from the previous step as a reference. You should set the type asCreditCardProcessingError
. - Save your file.
In this part of the exercise, you will catch the ApplicationError
that was
raised from the processCreditCard
Activity and handle it.
- Open the
workflow.py
in your text editor. - Locate the line with that beings with:
credit_card_confirmation = await workflow.execute_activity_method
.- This code calls the
process_credit_card
Activity, and if a non-retryableApplicationError
is raised, the Workflow will fail. However, it is possible to catch this failure and either handle it, or continue to propagate it up. - Wrap this line in a
try/catch
block. However, you will not catchApplicationError
. Since theApplicationError
in the Activity is designated as non-retryable, by the time it reaches the Workflow it is converted to anActvityError
. - Within the
catch
block, add a logging statement stating that the Activity has failed. - After the logging statement, raise another
ApplicationError
passing in a message and settingCreditCardProcessingError
as the type. This will cause the Workflow to fail, as you were unable to bill the customer.
- This code calls the
- Save your file.
In this part of the exercise, you will run your Workflow and see both your Workflow and Activity succeed and fail.
In the starter.py
file, a valid credit card number as part of an order has
been provided to run this Workflow.
First, run the Workflow successfully:
- In the same terminal, start the Worker by running:
python worker.py
- In another terminal, start the Workflow by executing
starter.py
:python starter.py
- In the Web UI, verify that the Workflow ran successfully to completion.
Next, you'll modify the starter data to cause the Workflow to fail:
- Open
shared.py
and modify the codeby deleting a digit from the String. Save this file.credit_card_info = CreditCardInfo( holderName="Lisa Anderson", number="2424242424242424" )
- Stop the worker using CMD-C on Mac or Ctrl-C on Windows/Linux
- Restart the Worker by running:
python worker.py
- In another terminal, start the Workflow by executing
starter.py
:python starter.py
- You should see the Workflow fail in the terminal where you executed
starter.py
. Also check the WebUI and view the failure there.