A simple framework for building composable, asynchronous workflows
Project description
Flux - Tiny Pipeline Framework
A minimal, composable pipeline framework for building async workflows with persistence, parallel execution, and pause/resume capabilities.
🚀 Quick Start
Installation
# Create and activate virtual environment
python3 -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Install package in development mode
pip install -e .
Basic Example
import asyncio
from flux import Node
@Node
def step1(input):
return f"processed: {input}"
@Node
def step2(input):
return f"{input} -> complete"
# Chain nodes with pipe operator
pipeline = step1 | step2
# Execute
result = await pipeline("hello")
# Output: "processed: hello -> complete"
📁 Core Concepts
1. Nodes - Building Blocks
Decorate any function to make it a pipeline node:
@Node
def my_function(input):
return input.upper()
Nodes can be sync or async, and automatically handle persistence and shared state.
2. Pipelines - Composition with |
Chain nodes sequentially using the pipe operator:
pipeline = node1 | node2 | node3
result = await pipeline(input_data)
3. Parallel Execution
Run multiple nodes in parallel:
from flux import Parallel
parallel = Parallel(node1, node2, node3)
results = await parallel(input) # Returns list of results
4. Conditional Branching
Route execution based on conditions:
from flux import Conditional
@Node
def check_type(input):
return "number" if isinstance(input, int) else "text"
pipeline = Conditional(
check_type,
{
"number": number_handler,
"text": text_handler,
"": default_handler # Default branch
}
)
5. Persistence & State
Track execution state and share data between nodes:
@Node
def save_data(input, persistence=None):
if persistence:
persistence.save("key", "value")
return input
@Node
def load_data(input, persistence=None):
if persistence:
value = persistence.get("key")
return input
6. Pause/Resume
Pause and resume pipeline execution:
@Node
def pausable_step(input, persistence=None, node=None):
if should_pause:
node.pause(persistence)
return input
# Execution pauses, can be resumed later
🛠️ Framework Features
Node Capabilities
- Auto-detection: Automatically detects sync/async functions
- Dependency injection: Supports
shared,persistence,storage,observability - Composable: Chain with
|operator or use inParallel/Conditional
Persistence API
persistence.save(key, value) # Save state
persistence.get(key, default) # Get state
persistence.delete(key) # Delete state
persistence.get_history() # Get execution history
persistence.set_status(status) # Mark run status
persistence.pause() # Pause execution
Run Management
Persistence.list_runs() # List all tracked runs
Persistence.get_run(run_id) # Get specific run data
Persistence.cleanup_run(run_id) # Clean up run data
📝 Complete Example
import asyncio
from flux import Node, Parallel
@Node
def fetch_data(input):
return f"data-{input}"
@Node
def process_data(input, persistence=None):
if persistence:
persistence.save("processed", input)
return input.upper()
@Node
def transform(input):
return f"transformed-{input}"
@Node
def combine(inputs: list):
return " + ".join(inputs)
# Build pipeline: parallel processing then combine
parallel = Parallel(
fetch_data | process_data,
transform
)
pipeline = parallel | combine
# Execute
result = await pipeline("start")
# Output: "DATA-DATA-START + transformed-start"
🔧 Advanced Features
Custom Storage Backend
class CustomStorage:
def save(self, key: str, value: Any) -> None: ...
def get(self, key: str) -> Any: ...
def delete(self, key: str) -> bool: ...
pipeline = my_pipeline(input, storage=CustomStorage())
Observability
def logger(action: str, key: str, value: Any) -> None:
print(f"{action}: {key} = {value}")
pipeline = my_pipeline(input, observability=logger)
Execution History
result = await pipeline(input)
history = persistence.get_history()
for entry in history:
print(f"{entry['node_name']}: {entry['duration']:.4f}s")
📁 Project Structure
flux/
├── __init__.py # Tiny framework (~400 lines)
├── requirements.txt # Dependencies
├── setup.py # Package setup
└── tests/ # Test suite
🎯 Design Philosophy
- Tiny: ~400 lines of core framework code
- Composable: Build complex workflows from simple functions
- Flexible: Sync/async, parallel, conditional execution
- Observable: Built-in persistence and execution tracking
- Zero Dependencies: Only Python standard library (asyncio)
🧪 Testing
# Run tests
python -m pytest
# Run quick test
python __init__.py
📄 License
This project is licensed under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flux_pipeline-0.1.1.tar.gz.
File metadata
- Download URL: flux_pipeline-0.1.1.tar.gz
- Upload date:
- Size: 37.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5edf1cefce539614fab16ea7bf406a7291d26d7c412867335b54c8bf9b440bb2
|
|
| MD5 |
43918bc47d9b8f00190583ff1fdf8a34
|
|
| BLAKE2b-256 |
63aa058b5e4133ce65997596858417300032344b93322d94a70028c09cbcca70
|
File details
Details for the file flux_pipeline-0.1.1-py3-none-any.whl.
File metadata
- Download URL: flux_pipeline-0.1.1-py3-none-any.whl
- Upload date:
- Size: 4.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
84eff2b20668a2c0f0d2bf26fb6ad9db4908d72a52affc38fc1d29e6c963a3a8
|
|
| MD5 |
09aa7823d3ba27d4f57175d2308aa32c
|
|
| BLAKE2b-256 |
854fcb353e45a9ebf8c1f984caf89c4556fb7956bba22b91694faec8c127adf1
|