Web UI
Flowrra provides a built-in web dashboard for monitoring and managing tasks, schedules, and system statistics. The UI integrates seamlessly with popular Python web frameworks.
Overview
The Web UI provides:
Dashboard: System statistics, recent failed tasks, and active schedules
Tasks: View registered tasks and execution history with status filtering
Schedules: Manage cron and interval-based task schedules
REST API: JSON endpoints for programmatic access
Framework Integration
Flowrra supports integration with FastAPI, Flask, Quart, and Django. Choose the integration that matches your web framework.
FastAPI Integration
For FastAPI applications, use create_router():
from contextlib import asynccontextmanager
from fastapi import FastAPI
from flowrra import Flowrra
from flowrra.ui.fastapi import create_router
# Create your Flowrra app
flowrra = Flowrra.from_urls(
broker='redis://localhost:6379/0',
backend='redis://localhost:6379/1'
)
# Register tasks
@flowrra.task()
async def send_email(to: str, subject: str):
"""Send an email asynchronously."""
await asyncio.sleep(2) # Simulate email sending
return {"status": "sent", "to": to}
@flowrra.task()
async def daily_report():
"""Generate daily report."""
print("Generating daily report...")
return {"status": "completed"}
# Create scheduler and schedule tasks
scheduler = flowrra.create_scheduler()
# Lifespan context manager for startup/shutdown
@asynccontextmanager
async def lifespan(app: FastAPI):
# Schedule daily report at 9 AM (before starting)
await scheduler.schedule_cron(
task_name="daily_report",
cron="0 9 * * *",
description="Daily report at 9 AM"
)
# Startup
await flowrra.start()
yield
# Shutdown
await flowrra.stop()
# Create FastAPI app with lifespan
app = FastAPI(lifespan=lifespan)
# Include Flowrra UI router
app.include_router(
create_router(flowrra),
prefix="/flowrra",
tags=["flowrra"]
)
# Your other FastAPI routes
@app.get("/")
async def root():
return {"message": "Hello World"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Access the UI at: http://localhost:8000/flowrra
Flask/Quart Integration
For Flask or Quart applications, use create_blueprint().
Quart (Recommended for async support):
from quart import Quart
from flowrra import Flowrra
from flowrra.ui.flask import create_blueprint
# Create your Flowrra app
flowrra = Flowrra.from_urls(
broker='redis://localhost:6379/0',
backend='redis://localhost:6379/1'
)
# Register tasks
@flowrra.task()
async def send_email(to: str, subject: str):
"""Send an email asynchronously."""
await asyncio.sleep(2)
return {"status": "sent", "to": to}
@flowrra.task()
async def cleanup_old_data():
"""Clean up old data."""
print("Cleaning up old data...")
return {"cleaned": 100}
# Create scheduler and schedule tasks
scheduler = flowrra.create_scheduler()
# Create Quart app and register Flowrra blueprint
app = Quart(__name__)
app.register_blueprint(
create_blueprint(flowrra),
url_prefix="/flowrra"
)
# Lifecycle events
@app.before_serving
async def startup():
# Schedule cleanup task to run daily at midnight
await scheduler.schedule_cron(
task_name="cleanup_old_data",
cron="0 0 * * *",
description="Daily cleanup at midnight"
)
await flowrra.start()
@app.after_serving
async def shutdown():
await flowrra.stop()
# Your other Quart routes
@app.route("/")
async def root():
return {"message": "Hello World"}
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)
Flask (Traditional):
from flask import Flask
from flowrra import Flowrra
from flowrra.ui.flask import create_blueprint
import threading
import asyncio
# Create your Flowrra app
flowrra = Flowrra.from_urls(
broker='redis://localhost:6379/0',
backend='redis://localhost:6379/1'
)
# Register tasks
@flowrra.task()
async def send_email(to: str, subject: str):
"""Send an email asynchronously."""
await asyncio.sleep(2)
return {"status": "sent", "to": to}
@flowrra.task()
async def weekly_summary():
"""Generate weekly summary."""
print("Generating weekly summary...")
return {"status": "completed"}
# Create scheduler and schedule tasks
scheduler = flowrra.create_scheduler()
async def setup_schedules():
# Schedule weekly summary every Monday at 9 AM
await scheduler.schedule_cron(
task_name="weekly_summary",
cron="0 9 * * 1",
description="Weekly summary on Monday"
)
# Create Flask app and register Flowrra blueprint
app = Flask(__name__)
app.register_blueprint(
create_blueprint(flowrra),
url_prefix="/flowrra"
)
# Your other Flask routes
@app.route("/")
def root():
return {"message": "Hello World"}
# Start Flowrra in background thread
async def run_flowrra_async():
await setup_schedules()
await flowrra.run()
def run_flowrra():
asyncio.run(run_flowrra_async())
if __name__ == "__main__":
thread = threading.Thread(target=run_flowrra, daemon=True)
thread.start()
app.run(host="0.0.0.0", port=8000)
Access the UI at: http://localhost:8000/flowrra
Django Integration
For Django applications, use get_urls():
1. Create your Flowrra app (e.g., in myapp/flowrra_app.py):
# myapp/flowrra_app.py
from flowrra import Flowrra
# Create Flowrra app
flowrra = Flowrra.from_urls(
broker='redis://localhost:6379/0',
backend='redis://localhost:6379/1'
)
# Register tasks
@flowrra.task()
async def send_email(to: str, subject: str):
"""Send an email asynchronously."""
import asyncio
await asyncio.sleep(2)
return {"status": "sent", "to": to}
@flowrra.task()
async def monthly_backup():
"""Perform monthly backup."""
print("Running monthly backup...")
return {"status": "backup_complete"}
# Create scheduler
scheduler = flowrra.create_scheduler()
2. Add to your Django project’s urls.py:
# myproject/urls.py
from django.contrib import admin
from django.urls import path, include
from flowrra.ui.django import get_urls
from myapp.flowrra_app import flowrra
urlpatterns = [
path('admin/', admin.site.urls),
# Your other Django URLs
path('flowrra/', include(get_urls(flowrra))),
]
3. Start Flowrra in your AppConfig:
# myapp/apps.py
from django.apps import AppConfig
import asyncio
class MyAppConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'myapp'
def ready(self):
from myapp.flowrra_app import flowrra, scheduler
# Schedule tasks before starting
async def setup():
# Schedule monthly backup on 1st day at midnight
await scheduler.schedule_cron(
task_name="monthly_backup",
cron="0 0 1 * *",
description="Monthly backup on 1st"
)
# Start Flowrra when Django starts
await flowrra.start()
asyncio.create_task(setup())
Access the UI at: http://localhost:8000/flowrra/
UI Features
Dashboard Page
The dashboard provides an overview of your Flowrra system:
System Statistics:
Total tasks executed
Success/failure rates
Active workers count
Queue size
Recent Failed Tasks: Quick access to tasks that need attention
Active Schedules: Overview of upcoming scheduled tasks
Tasks Page
View and filter task execution history:
Filter by status: All, Pending, Running, Success, Failed
Registered Tasks: View all tasks with their configuration (type, retries, retry delay)
Execution History: Complete task history with timestamps and duration
Error Details: Expandable error messages for failed tasks
Status Badges: Color-coded status indicators
Schedules Page
Manage scheduled tasks:
View all schedules: Cron and interval-based schedules
Enable/disable schedules: Toggle schedules on/off
Next execution time: See when each schedule will run next
Execution statistics: Track schedule performance
Create new schedules: Via REST API
REST API Endpoints
All integrations expose the following JSON API endpoints:
System Endpoints
GET /flowrra/api/health- Health checkGET /flowrra/api/stats- System statistics
Task Endpoints
GET /flowrra/api/tasks- List registered tasksGET /flowrra/api/tasks/{name}- Get specific task info
Schedule Endpoints
GET /flowrra/api/schedules- List all schedulesGET /flowrra/api/schedules?enabled_only=true- List only enabled schedulesGET /flowrra/api/schedules/{id}- Get specific schedulePOST /flowrra/api/schedules/cron- Create cron schedulePUT /flowrra/api/schedules/{id}/enable- Enable schedulePUT /flowrra/api/schedules/{id}/disable- Disable scheduleDELETE /flowrra/api/schedules/{id}- Delete schedule
Example API Usage
Get system statistics:
import httpx
response = httpx.get("http://localhost:8000/flowrra/api/stats")
stats = response.json()
print(f"Total tasks: {stats['total_tasks']}")
print(f"Success rate: {stats['success_rate']}%")
List registered tasks:
response = httpx.get("http://localhost:8000/flowrra/api/tasks")
tasks = response.json()
for task in tasks:
print(f"{task['name']}: {task['type']}")
Create a cron schedule:
response = httpx.post(
"http://localhost:8000/flowrra/api/schedules/cron",
json={
"task_name": "send_email",
"cron": "0 9 * * 1", # Every Monday at 9 AM
"description": "Weekly email report",
"args": ["admin@example.com", "Weekly Report"],
"enabled": True,
"priority": 5
}
)
schedule = response.json()
print(f"Created schedule: {schedule['schedule_id']}")
Enable/disable a schedule:
# Disable
httpx.put(f"http://localhost:8000/flowrra/api/schedules/{schedule_id}/disable")
# Enable
httpx.put(f"http://localhost:8000/flowrra/api/schedules/{schedule_id}/enable")
Delete a schedule:
httpx.delete(f"http://localhost:8000/flowrra/api/schedules/{schedule_id}")
Customization
Custom Mount Path
You can mount the UI at any path:
# FastAPI
app.include_router(
create_router(flowrra),
prefix="/admin/tasks",
tags=["admin"]
)
# Flask/Quart
app.register_blueprint(
create_blueprint(flowrra),
url_prefix="/admin/tasks"
)
# Django
path('admin/tasks/', include(get_urls(flowrra)))
Then access at: http://localhost:8000/admin/tasks/
Production Deployment
Best Practices
For production deployments:
Use Redis for both broker and backend:
flowrra = Flowrra.from_urls( broker='redis://localhost:6379/0', backend='redis://localhost:6379/1' )
Enable authentication on your web framework
Use reverse proxy (nginx, Traefik) for HTTPS
Monitor resources via the dashboard
Set up alerting based on failed task metrics
Authentication Example (FastAPI)
Protect the Flowrra UI with authentication:
from contextlib import asynccontextmanager
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from flowrra import Flowrra
from flowrra.ui.fastapi import create_router
import secrets
flowrra = Flowrra.from_urls()
security = HTTPBasic()
def verify_credentials(credentials: HTTPBasicCredentials = Depends(security)):
"""Verify username and password."""
correct_username = secrets.compare_digest(credentials.username, "admin")
correct_password = secrets.compare_digest(credentials.password, "secure_password")
if not (correct_username and correct_password):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid credentials",
headers={"WWW-Authenticate": "Basic"},
)
return credentials.username
@asynccontextmanager
async def lifespan(app: FastAPI):
await flowrra.start()
yield
await flowrra.stop()
app = FastAPI(lifespan=lifespan)
flowrra_router = create_router(flowrra)
# Add authentication dependency to all routes
flowrra_router.dependencies = [Depends(verify_credentials)]
app.include_router(
flowrra_router,
prefix="/flowrra"
)
Nginx Reverse Proxy
Example nginx configuration for HTTPS:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location /flowrra {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
}
}
See Also
flowrra.ui package - UI API Reference
Task Scheduling - Task Scheduling Guide
Working with Tasks - Task Configuration Guide
Result Backends - Backend Configuration