Run a Single Asynchronous Action
An asynchronous action allows you to run a single method asynchronously.
Scheduling a method to run asynchronously allows you to:
- Provide a better user experience - You can schedule long-running tasks to run in the background, so users do not have to wait for them to complete.
- Schedule tasks to run on a worker node with a specific hardware profile - This is useful when training machine learning (ML) models.
- Avoid overloading manager nodes - By scheduling CPU and memory intensive tasks to run on worker nodes, you make sure manager nodes have resources to continue serving API and UI requests for your applications.
There are two steps to create an asynchronous action:
- Find a Type that implements the logic you want to execute, or create a new Type to implement that logic.
- Create the asynchronous action by specifying which method to invoke.
In this example, an asynchronous task is created that sums all digits from 1 to 123456789.
Define and implement the logic
The method below computes the sum of a range of digits, so start by creating a new Type:
type Sum {
addDigits: function(start: int, end: int): int py-jep-resolved
}Implement the method in Python, in file Sum.py:
# cls is required as addDigits is a static method
def addDigits(cls, start, end):
return sum(range(start, end))Create the asynchronous action
After implementing the logic and deploying the Sum type, you can invoke the addDigits method, Sum.addDigits(0, 5) in the console. addDigits is evaluated synchronously.
To run the method asynchronously on a task node, create a new AsyncAction instance. You can do this as part of your application logic, from the web console, or a JupyterLab notebook.
To create an asynchronous action from a JupyterLab notebook:
# Describe the Type, method, and arguments to run.
spec = c3.AsyncActionSpec(typeName="Sum", action="addDigits", args={"start":1, "end": 123456789})
# Schedule the method to run asynchronously
action = c3.AsyncAction.submit(spec)
# Make sure to get the auto-generated ID for the action
action.idIn this example, you are running the sum method asynchronously, but you can do the same for any method available in your application. As an example you can use the same approach to make (ML) training, data integration, or any other long-running job run asynchronously.
Monitor the asynchronous action
You can check for the status of an asynchronous job:
# Get the action
action = c3.AsyncAction(id='<action id>').get()
# Check if the async action has finished running
action.hasCompleted()
# Get the result once the action finishes
action.resultTroubleshoot errors
When troubleshooting for errors, start by looking at the error associated with the asynchronous action:
# Get the action
action = c3.AsyncAction(id='<action id>').get()
# Check if there are any errors
action.formatError()One way to troubleshoot the logic is to invoke directly the method the asynchronous action is running. This allows you to run the method synchronously and troubleshoot errors.
When you find the root cause of the problem, update the logic in your implementation, deploy the updated implementation and re-submit the failed action for execution:
# Get the action
action = c3.AsyncAction(id='<action id>').get()
# Re-try the action that failed
action.reSubmit()Monitor from the console
Asynchronous actions are added to the ActionQueue for asynchronous processing. You can monitor the status of the queue from Console or JupyterLab. For example:
// Get a list of entries in the ActionQueue grouped by stage
ActionQueue.count();
// Get a list of failed actions and failure details
ActionQueue.errors();The system retries actions in every queue that fail due to DbRetryable errors. The system does not record these retry attempts, but does record the failure if the retry fails.