Skip to main content

A lightweight, async-first Python workflow engine with dynamic branching and rich visual dashboarding.

Project description

⚡ pyrelay

PyPI Version Python versions License

pyrelay is a lightweight, high-performance, async-first Python workflow engine. It allows developers to model, execute, and monitor complex task pipelines with native pythonic flows (if/else branching), zero complex DSLs, live terminal dashboards, and interactive web visualizers.


✨ Features

  • 🐍 Native Python Branching: Use standard Python if/else and loops. The execution graph is discovered dynamically at runtime.
  • ⚡ Async-First Architecture: Built natively on top of Python asyncio. Executes independent tasks concurrently.
  • 🧵 Auto-Offloading for Sync Tasks: Run blocking synchronous functions without stalling the async event loop (automatically offloaded to thread executors).
  • ⏱️ Fault Tolerance: Custom task-level retry policies, exponential backoff, and timeouts out-of-the-box.
  • 🖥️ Live Console Dashboard: Animated status trees, progress bars, and log streams in your terminal powered by rich.
  • 🌐 Draggable HTML/JS Visualizer: Compile any workflow run into a standalone dark-mode HTML file containing a responsive network chart powered by Vis-Network.

📦 Installation

Initialize your project and install pyrelay:

pip install pyrelay-workflow

(Requires Python 3.9+)


🚀 Quickstart

Create a workflow by wrapping functions with @task and @workflow. Awaited tasks automatically map dependencies based on their execution order!

import asyncio
from pyrelay import task, workflow, WorkflowRun
from pyrelay.dashboard import ConsoleDashboard

@task(retries=2, retry_delay=0.5)
async def fetch_user_data(user_id: int):
    await asyncio.sleep(0.5)
    return {"id": user_id, "name": "Alice", "status": "active"}

@task()
async def process_account(user: dict):
    await asyncio.sleep(0.3)
    return f"Account processed for {user['name']}"

@workflow(name="Account Pipeline")
async def account_flow(user_id: int):
    user = await fetch_user_data(user_id)
    result = await process_account(user)
    return result

if __name__ == "__main__":
    run = WorkflowRun(account_flow)
    
    # Attach the live CLI dashboard
    ConsoleDashboard(run)
    
    # Run the workflow blocking/sync
    run.run_sync(user_id=101)

🌿 Dynamic Branching (Option B)

In pyrelay, branching is simply Python. The engine tracks exactly which path was taken and marks skipped branches appropriately in reports.

@task()
async def process_premium_user(user: dict):
    return "VIP treatment applied"

@task()
async def process_standard_user(user: dict):
    return "Standard access configured"

@workflow(name="User Routing")
async def user_routing_flow(user: dict):
    # Branching happens at runtime based on real data values
    if user["is_premium"]:
        result = await process_premium_user(user)
    else:
        result = await process_standard_user(user)
    return result

🎨 Visualization Telemetry

Generating an interactive, visual representation of your executed workflow is a single method call:

# Save interactive HTML dashboard
run.visualize("workflow_run.html")

Open workflow_run.html in any browser to get a premium dark-mode interface where you can:

  1. Pan and zoom around the execution DAG.
  2. Review node colors indicating statuses: Green (Success), Red (Failed), Blue (Running), Grey (Pending).
  3. Click any node to slide open a telemetry inspect panel containing:
    • Inputs and outputs
    • Time elapsed, start/end timestamps
    • Retry counts and exceptions

⚙️ Configuration Properties

The @task decorator accepts the following metadata options:

Property Type Default Description
name str Function Name Identifier for the task (used in dashboard and graphs).
retries int 0 Number of attempts to retry if the function raises an exception.
retry_delay float 1.0 Initial delay (seconds) before attempting a retry.
backoff_factor float 2.0 Exponential multiplier for consecutive retries (delay * backoff_factor^attempt).
timeout float None Max seconds before cancelling execution and marking the task as failed.

🧪 Running Tests

To run the unit and integration test suite, install development dependencies and run pytest:

pip install -e ".[dev]"
pytest tests/

📄 License

Distributed under the MIT License. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyrelay_workflow-0.1.1.tar.gz (18.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyrelay_workflow-0.1.1-py3-none-any.whl (16.4 kB view details)

Uploaded Python 3

File details

Details for the file pyrelay_workflow-0.1.1.tar.gz.

File metadata

  • Download URL: pyrelay_workflow-0.1.1.tar.gz
  • Upload date:
  • Size: 18.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for pyrelay_workflow-0.1.1.tar.gz
Algorithm Hash digest
SHA256 de5d651ab815bbae4f03f3737fdcf228692aa4ea15bc7563198ce31c451da2d5
MD5 fe5ef7e2aeb1550505477c41df3dc9fa
BLAKE2b-256 6e8ddb101be2b21e77d3ad7bd4ee83ab58a760d7e6c6a015f505136abbc8fa65

See more details on using hashes here.

File details

Details for the file pyrelay_workflow-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for pyrelay_workflow-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1b77122371165c29fe2c1fae402853fe64200657d31e6eee6ebe6b14a441e1fc
MD5 18df6aaccdb9378b9cac35848173305e
BLAKE2b-256 180a6fbb3cef7c8c98c78ebacc4c67bc3a1f34869f75e0f546df01d3f82da4ee

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page