mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 14:25:02 +00:00
15 KiB
15 KiB
WorkflowUI Architecture
Complete technical architecture for the WorkflowUI visual workflow editor.
System Overview
┌─────────────────────────────────────────────────────────────┐
│ Browser Environment │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ React Application (Next.js) │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ │ │
│ │ ┌────────────────────────────────────────────┐ │ │
│ │ │ Pages & Components (FakeMUI) │ │ │
│ │ │ - Dashboard │ │ │
│ │ │ - Editor (Canvas + Panels) │ │ │
│ │ │ - Properties Panel │ │ │
│ │ │ - Node Library │ │ │
│ │ └────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌────────────────────────────────────────────┐ │ │
│ │ │ React Flow (DAG Visualization) │ │ │
│ │ │ - Canvas with nodes & edges │ │ │
│ │ │ - Zoom & pan controls │ │ │
│ │ │ - Minimap │ │ │
│ │ └────────────────────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Redux Store │ │ IndexedDB │ │
│ │ - Workflow │ │ - Workflows │ │
│ │ - Editor │ │ - Executions │ │
│ │ - Nodes │ │ - Node Types │ │
│ │ - Connections │ │ - Drafts │ │
│ │ - UI State │ │ - Sync Queue │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
│ │
│ HTTP/WS │ HTTP
│ │
┌───────────────────▼───────────────────▼─────────────────────┐
│ Flask Backend │
├─────────────────────────────────────────────────────────────┤
│ - Workflow CRUD │
│ - Execution management │
│ - Node registry │
│ - Workflow validation │
└───────────────────┬───────────────────────────────────────┬─┘
│ │
▼ ▼
┌──────────────────────┐ ┌─────────────────────┐
│ PostgreSQL/MongoDB │ │ MetaBuilder DAG │
│ - Persistence │ │ - Execution │
│ - History │ │ - Error Recovery │
└──────────────────────┘ │ - Multi-tenant │
└─────────────────────┘
Component Architecture
Frontend Layer
1. Pages (Next.js App Directory)
app/
├── layout.tsx # Root layout with Redux provider
├── page.tsx # Dashboard (list workflows)
├── editor/[id]/
│ └── page.tsx # Workflow editor with React Flow
└── api/
├── workflows/ # Proxy API endpoints
├── nodes/
└── executions/
2. React Components
Layout Components:
MainLayout: Root layout with header, sidebar, contentHeader: Top navigation, user menuSidebar: Workflow list, recent items
Editor Components:
Editor/Canvas: React Flow canvas with nodes/edgesEditor/Toolbar: Save, execute, undo/redo, settingsEditor/NodePanel: Add nodes to canvasEditor/Properties: Edit selected node parameters
UI Components (FakeMUI):
Button,Input,Modal,DialogSidebar,Tabs,TooltipCard,List,Grid
3. Custom Node Components
Each node type has a custom React component:
// PlaywrightNode.tsx
<div className="node-container">
<Header title="Playwright" icon="test" />
<Parameters>
<Select name="browser" options={['chromium', 'firefox', 'webkit']} />
<Input name="baseUrl" type="text" />
<Checkbox name="headless" />
</Parameters>
<Handles top bottom /> {/* React Flow handles */}
</div>
State Management (Redux)
store/
├── store.ts # Store configuration
└── slices/
├── workflowSlice.ts # Workflow CRUD + execution
├── editorSlice.ts # Canvas state (zoom, pan, selection)
├── nodesSlice.ts # Node registry, templates
├── connectionSlice.ts # Edge drawing state
└── uiSlice.ts # Modals, notifications, UI state
Redux State Tree
{
workflow: {
current: Workflow, // Active workflow
nodes: WorkflowNode[], // Canvas nodes
connections: Edge[], // Canvas edges
isDirty: boolean, // Unsaved changes
isSaving: boolean, // Save in progress
executionHistory: [], // Past executions
currentExecution: null // Active execution
},
editor: {
zoom: number, // Canvas zoom level
pan: { x, y }, // Canvas position
selectedNodes: Set<string>, // Selected node IDs
selectedEdges: Set<string>, // Selected edge IDs
isDrawing: boolean // Drawing edge state
},
nodes: {
registry: NodeType[], // Available node types
templates: NodeTemplate[], // Saved node templates
categories: string[] // Node categories
},
connection: {
isActive: boolean, // Drawing edge
source: string, // Source node ID
target: string // Target node ID
},
ui: {
modals: {
createWorkflow: boolean,
settings: boolean,
nodeHelp: boolean
},
notifications: Notification[],
theme: 'light' | 'dark',
sidebarOpen: boolean
}
}
Storage Layer (IndexedDB)
Dexie Schema:
db.version(1).stores({
workflows: 'id, tenantId, [tenantId+name]',
executions: 'id, workflowId, [tenantId+workflowId]',
nodeTypes: 'id, [tenantId+category]',
drafts: 'id, tenantId',
syncQueue: '++id, [tenantId+action]'
});
Offline-First Strategy:
- All operations write to IndexedDB first
- Changes added to sync queue
- Background sync when online
- Conflict resolution on server
Backend Layer (Flask)
API Endpoints:
GET /api/workflows # List workflows
POST /api/workflows # Create workflow
GET /api/workflows/<id> # Get workflow
PUT /api/workflows/<id> # Update workflow
DELETE /api/workflows/<id> # Delete workflow
POST /api/workflows/<id>/execute # Execute workflow
GET /api/workflows/<id>/executions # Execution history
GET /api/executions/<id> # Get execution
POST /api/workflows/<id>/validate # Validate workflow
GET /api/nodes # List node types
GET /api/nodes/<id> # Get node type
GET /api/nodes/categories # Get categories
GET /api/health # Health check
Data Models:
class Workflow:
id: str
name: str
description: str
version: str
tenantId: str
nodes: List[Node]
connections: List[Connection]
createdAt: datetime
updatedAt: datetime
class Node:
id: str
type: str # e.g., 'testing.playwright'
name: str
position: {x, y}
parameters: Dict
class Execution:
id: str
workflowId: str
status: 'running' | 'success' | 'error'
nodes: List[NodeExecution]
duration: int
error: Optional[Error]
Data Flow
Workflow Creation
User Input
│
▼
React Component (dispatch action)
│
▼
Redux Action (workflowSlice.createWorkflow)
│
├─ Update Redux state
│
├─ IndexedDB write (workflowDB.create)
│
└─ Add to sync queue (optional)
│
▼
Background sync to server (when online)
│
▼
Flask POST /api/workflows
Workflow Execution
User clicks "Execute"
│
▼
Dispatch executionSlice.startExecution
│
▼
Frontend creates ExecutionResult object
│
├─ IndexedDB write (executionDB.create)
│
▼
HTTP POST /api/workflows/<id>/execute
│
▼
Flask receives execution request
│
├─ Validation
│
├─ Call DAG Executor
│
└─ WebSocket updates to client
│
▼
Redux update (execution progress)
│
▼
UI renders execution results
Node Parameter Editing
User edits parameter in Properties panel
│
▼
React onChange event
│
▼
Dispatch updateNode action
│
▼
Redux updates node in state
│
├─ Mark workflow as dirty
│
├─ Update React Flow node
│
└─ Auto-save to IndexedDB
Performance Optimizations
1. Code Splitting
// Components loaded on-demand
const Editor = dynamic(() => import('@/components/Editor'), { ssr: false });
const Storybook = dynamic(() => import('@/components/Storybook'), { ssr: false });
2. Redux Selectors with Reselect
// Memoized selectors prevent unnecessary re-renders
const selectWorkflowNodes = createSelector(
(state) => state.workflow.nodes,
(state) => state.editor.selectedNodes,
(nodes, selected) => nodes.filter(n => selected.has(n.id))
);
3. IndexedDB Indexing
workflows: 'id, tenantId, [tenantId+name]'
└─ Fast lookup by tenantId + name
4. React Flow Optimization
// Use memo to prevent unnecessary node re-renders
const PlaywrightNode = memo(({ data }) => (...));
// Handle connections efficiently
const onConnect = useCallback((connection) => {
dispatch(addConnection(connection));
}, [dispatch]);
5. Lazy Loading Images/Icons
<Image
src="/icons/playwright.svg"
loading="lazy"
width={24}
height={24}
/>
Error Handling
Frontend Error Handling
Try-Catch Wrapper
│
├─ User-friendly error message
│
├─ Log to console (dev)
│
├─ Send to error tracking (prod)
│
└─ Redux notification (ui.notifications)
Backend Error Handling
@app.errorhandler(Exception)
def handle_error(error):
return jsonify({
'error': str(error),
'code': 'INTERNAL_ERROR',
'timestamp': datetime.now().isoformat()
}), 500
Security
Multi-Tenant Isolation
// All requests include tenantId
const response = await api.get(`/workflows`, {
params: { tenantId: user.tenantId }
});
Input Validation
// Validate on frontend
const schema = Yup.object({
name: Yup.string().required().max(255),
nodes: Yup.array().min(1).required()
});
// Validate on backend
def validate_workflow(data):
# Check nodes exist
# Check connections valid
# Check types registered
CORS & CSRF Protection
CORS(app, resources={
r"/api/*": {
"origins": os.getenv('ALLOWED_ORIGINS', '*').split(','),
"methods": ["GET", "POST", "PUT", "DELETE"],
"allow_headers": ["Content-Type", "X-CSRF-Token"]
}
})
Deployment Architecture
Frontend Deployment
Source Code
│
▼
npm run build
│
├─ TypeScript compilation
├─ SCSS compilation
├─ Code splitting
│
▼
.next/
│
▼
Vercel (or similar)
│
▼
CDN (cached assets)
Backend Deployment
Source Code
│
▼
Docker build
│
├─ Python 3.11 base
├─ Install dependencies
├─ Copy code
│
▼
Docker image
│
▼
Deploy to Heroku/Railway/K8s
Monitoring & Observability
Frontend Monitoring
- Redux DevTools for state inspection
- React DevTools for component profiling
- Error tracking (Sentry)
- Performance monitoring (Web Vitals)
Backend Monitoring
- Log aggregation (ELK stack)
- APM (Application Performance Monitoring)
- Error tracking (Sentry)
- Database monitoring
Future Enhancements
- WebSocket Real-Time Collaboration: Multi-user editing
- Workflow Templates: Pre-built workflow templates
- Advanced Debugging: Step-through execution
- Performance Profiling: Execution performance analysis
- Workflow Scheduling: Cron-like scheduling
- Custom Nodes: User-defined node types
- Workflow Sharing: Share workflows between teams
- API-First: GraphQL API layer