Durable Workflows for Reliable Automation

Build Durable Workflows to Orchestrate Microservices and APIs with External Services. 

Durable workflows enable you to build reliable distributed applications easily. Instead of relying on complex event-driven, queue-based architectures, you can write simple, sequential code that orchestrates microservices and APIs.

Supported languages: Python, TypeScript (coming soon)

On-prem, private cloud or use hosted solution.

Integrations

gRPC

HTTP

Wenhooks

Cron

Twilio

Slack

GCP

Google Apps

and almost any API …

Example: Durable Task Chain

A workflow that is resilient to errors in each step (with the ability to retry each failing step on-demand via Slack), as well as server-side failures (thanks to AutoKitteh’s durable execution).

Integrations: Slack, HTTP

Prerequisites: Slack connection setup

Trigger: Slack Slash command 

Flow: 

  1. Start workflow on a slash command
  2. Run each of the steps:
    1. If the task was not complete (only if the user terminated it): exit 

The function retun_reliable_task() will make sure to retry a failed step if the user asks to.

 

Link to project.


from pathlib import Path
import random

import autokitteh
from autokitteh.slack import slack_client


slack = slack_client("slack_conn")

def on_slack_slash_command(event):
    """Use a Slack slash command from a user to start a chain of tasks."""
    user_id = event.data.user_id

    if not run_retriable_task(step1, user_id):
        return
    if not run_retriable_task(step2, user_id):
        return
    if not run_retriable_task(step3, user_id):
        return

    message = "Workflow completed successfully :smiley_cat:"
    slack.chat_postMessage(channel=user_id, text=message)


def run_retriable_task(task, user_id) -> bool:
    result = True
    while result:
        try:
            task()
            break
        except Exception as e:
            result = ask_user_retry_or_abort(task.__name__, e, user_id)

    if result:
        message = f"Task `{task.__name__}` completed"
        slack.chat_postMessage(channel=user_id, text=message)

    return result


def ask_user_retry_or_abort(task_name, error, user_id) -> bool:
    sub = autokitteh.subscribe("slack_conn", 'event_type == "interaction"')

    blocks = Path("interactive_message.json.txt").read_text()
    blocks = blocks.replace("MESSAGE", f"The task `{task_name}` failed: `{error}`")
    slack.chat_postMessage(channel=user_id, text="Workflow error", blocks=blocks)

    # Wait for and handle the user's response in this workflow.
    event = autokitteh.next_event(sub)
    autokitteh.unsubscribe(sub)
    return event.actions[0]["value"] == "retry"

Benefits

Even More

Contact Us

"*" indicates required fields

Please let us know what's on your mind. Have a question for us? Ask away.