package main import ( "context" "log" "time" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/cors" "github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/fiber/v2/middleware/recover" "github.com/oarkflow/mq/workflow" ) // SMS Demo server with comprehensive workflow pipeline func main() { // Initialize workflow engine config := &workflow.Config{ MaxWorkers: 10, ExecutionTimeout: 30 * time.Minute, EnableMetrics: true, EnableAudit: true, EnableTracing: true, } engine := workflow.NewWorkflowEngine(config) ctx := context.Background() engine.Start(ctx) defer engine.Stop(ctx) // Initialize user manager and middleware userManager := workflow.NewUserManager() middlewareManager := workflow.NewMiddlewareManager() // Create demo users createDemoUsers(userManager) // Setup middleware setupMiddleware(middlewareManager) // Register SMS workflow pipeline registerSMSWorkflows(engine) // Start HTTP server app := fiber.New(fiber.Config{ AppName: "Advanced SMS Workflow Engine", }) // Add fiber middleware app.Use(cors.New()) app.Use(logger.New()) app.Use(recover.New()) // Setup routes setupRoutes(app, engine, userManager, middlewareManager) log.Println("🚀 Advanced SMS Workflow Engine started on http://localhost:3000") log.Println("📱 SMS Pipeline Demo: http://localhost:3000/sms") log.Println("👤 User Auth Demo: http://localhost:3000/auth") log.Println("📊 Admin Dashboard: http://localhost:3000/admin") log.Println("📝 API Documentation: http://localhost:3000/docs") log.Fatal(app.Listen(":3000")) } func createDemoUsers(userManager *workflow.UserManager) { users := []*workflow.User{ { ID: "admin", Username: "admin", Email: "admin@company.com", Role: workflow.UserRoleAdmin, Permissions: []string{"admin"}, }, { ID: "manager", Username: "manager", Email: "manager@company.com", Role: workflow.UserRoleManager, Permissions: []string{"read", "write", "execute"}, }, { ID: "operator", Username: "operator", Email: "operator@company.com", Role: workflow.UserRoleOperator, Permissions: []string{"read", "execute"}, }, } for _, user := range users { if err := userManager.CreateUser(user); err != nil { log.Printf("Error creating user %s: %v", user.Username, err) } } log.Println("✅ Demo users created: admin/password, manager/password, operator/password") } func setupMiddleware(middlewareManager *workflow.MiddlewareManager) { // Add logging middleware loggingMiddleware := workflow.Middleware{ ID: "logging", Name: "Request Logging", Type: workflow.MiddlewareLogging, Priority: 1, Enabled: true, Config: map[string]interface{}{}, } middlewareManager.AddMiddleware(loggingMiddleware) // Add rate limiting middleware rateLimitMiddleware := workflow.Middleware{ ID: "rate_limit", Name: "Rate Limiting", Type: workflow.MiddlewareRateLimit, Priority: 2, Enabled: true, Config: map[string]interface{}{ "requests_per_minute": 100, }, } middlewareManager.AddMiddleware(rateLimitMiddleware) // Add auth middleware authMiddleware := workflow.Middleware{ ID: "auth", Name: "Authentication", Type: workflow.MiddlewareAuth, Priority: 3, Enabled: true, Config: map[string]interface{}{}, } middlewareManager.AddMiddleware(authMiddleware) log.Println("✅ Middleware configured: logging, rate limiting, authentication") } func registerSMSWorkflows(engine *workflow.WorkflowEngine) { ctx := context.Background() // 1. User Authentication Sub-DAG authWorkflow := createAuthSubDAG() if err := engine.RegisterWorkflow(ctx, authWorkflow); err != nil { log.Printf("Error registering auth workflow: %v", err) } // 2. Main SMS Pipeline Workflow smsWorkflow := createSMSPipelineWorkflow() if err := engine.RegisterWorkflow(ctx, smsWorkflow); err != nil { log.Printf("Error registering SMS workflow: %v", err) } // 3. Webhook Handler Workflow webhookWorkflow := createWebhookHandlerWorkflow() if err := engine.RegisterWorkflow(ctx, webhookWorkflow); err != nil { log.Printf("Error registering webhook workflow: %v", err) } log.Println("✅ SMS workflow pipeline registered successfully") } func createAuthSubDAG() *workflow.WorkflowDefinition { return &workflow.WorkflowDefinition{ ID: "user-auth-subdag", Name: "User Authentication Sub-DAG", Description: "Handles user login and token validation", Version: "1.0.0", Status: workflow.WorkflowStatusActive, Nodes: []workflow.WorkflowNode{ { ID: "validate-credentials", Name: "Validate User Credentials", Type: workflow.NodeTypeAuth, Description: "Authenticate user with credentials", Config: workflow.NodeConfig{ AuthType: "login", Credentials: map[string]string{ "admin": "password", "manager": "password", "operator": "password", }, TokenExpiry: 24 * time.Hour, }, }, { ID: "check-permissions", Name: "Check SMS Permissions", Type: workflow.NodeTypeValidator, Description: "Validate user has SMS sending permissions", Config: workflow.NodeConfig{ ValidationType: "strict", ValidationRules: []workflow.ValidationRule{ { Field: "permissions", Type: "required", Message: "User permissions required", }, { Field: "role", Type: "required", Message: "User role required", }, }, }, }, }, Edges: []workflow.WorkflowEdge{ { ID: "auth-to-permissions", FromNode: "validate-credentials", ToNode: "check-permissions", }, }, } } func createSMSPipelineWorkflow() *workflow.WorkflowDefinition { return &workflow.WorkflowDefinition{ ID: "sms-pipeline", Name: "Comprehensive SMS Pipeline", Description: "Complete SMS workflow with authentication, validation, routing, and reporting", Version: "1.0.0", Status: workflow.WorkflowStatusActive, Nodes: []workflow.WorkflowNode{ // Step 1: User Authentication (Sub-DAG) { ID: "user-authentication", Name: "User Authentication", Type: workflow.NodeTypeSubDAG, Description: "Authenticate user and validate permissions", Config: workflow.NodeConfig{ SubWorkflowID: "user-auth-subdag", InputMapping: map[string]string{ "username": "username", "password": "password", }, OutputMapping: map[string]string{ "auth_token": "token", "user_info": "user", }, }, }, // Step 2: SMS HTML Page Generation { ID: "generate-sms-page", Name: "Generate SMS HTML Page", Type: workflow.NodeTypeHTML, Description: "Create dynamic HTML page for SMS composition", Config: workflow.NodeConfig{ Template: ` SMS Composer

Welcome, {{.user.username}}!

Role: {{.user.role}} | Permissions: {{.user.permissions}}

SMS Composer

`, TemplateData: map[string]string{ "timestamp": "{{.timestamp}}", }, OutputPath: "/tmp/sms-composer.html", }, }, // Step 3: SMS Validation { ID: "validate-sms-data", Name: "Validate SMS Data", Type: workflow.NodeTypeValidator, Description: "Validate phone numbers and message content", Config: workflow.NodeConfig{ ValidationType: "strict", ValidationRules: []workflow.ValidationRule{ { Field: "recipients", Type: "required", Message: "Recipients are required", }, { Field: "message", Type: "required", Message: "Message content is required", }, { Field: "message", Type: "length", Value: map[string]interface{}{ "min": 1, "max": 160, }, Message: "Message must be 1-160 characters", }, }, }, }, // Step 4: Provider Selection & Routing { ID: "route-sms-provider", Name: "Route SMS Provider", Type: workflow.NodeTypeRouter, Description: "Select SMS provider based on routing rules", Config: workflow.NodeConfig{ RoutingRules: []workflow.RoutingRule{ { Condition: "recipient_count > 100", Destination: "bulk_provider", Priority: 1, Weight: 100, }, { Condition: "country == 'US'", Destination: "twilio", Priority: 2, Weight: 80, }, { Condition: "country == 'UK'", Destination: "nexmo", Priority: 2, Weight: 80, }, }, DefaultRoute: "standard_provider", }, }, // Step 5: Phone & Message Validation { ID: "validate-phones-spam", Name: "Phone & Spam Validation", Type: workflow.NodeTypeValidator, Description: "Validate phone numbers and check for spam", Config: workflow.NodeConfig{ ValidationType: "strict", ValidationRules: []workflow.ValidationRule{ { Field: "recipients", Type: "pattern", Value: `^\+?[1-9]\d{1,14}$`, Message: "Invalid phone number format", }, }, }, }, // Step 6: SMS Dispatch { ID: "dispatch-sms", Name: "Dispatch SMS", Type: workflow.NodeTypeSMS, Description: "Send SMS through selected provider", Config: workflow.NodeConfig{ Provider: "auto", // Will be set by router From: "+1234567890", MessageType: "transactional", }, }, // Step 7: Send User Notification { ID: "notify-user", Name: "Send User Notification", Type: workflow.NodeTypeNotify, Description: "Notify user about SMS status", Config: workflow.NodeConfig{ NotifyType: "email", Channel: "smtp", }, }, // Step 8: Store SMS Report { ID: "store-sms-report", Name: "Store SMS Report", Type: workflow.NodeTypeStorage, Description: "Store SMS delivery report", Config: workflow.NodeConfig{ StorageType: "database", StoragePath: "sms_reports", StorageConfig: map[string]string{ "table": "sms_reports", "connection": "main_db", }, }, }, // Step 9: Webhook Receiver for Provider Callbacks { ID: "webhook-receiver", Name: "SMS Provider Webhook", Type: workflow.NodeTypeWebhookRx, Description: "Receive delivery status from SMS provider", Config: workflow.NodeConfig{ ListenPath: "/webhook/sms/status", Secret: "webhook_secret_key", Timeout: 30 * time.Second, }, }, }, Edges: []workflow.WorkflowEdge{ { ID: "auth-to-html", FromNode: "user-authentication", ToNode: "generate-sms-page", }, { ID: "html-to-validate", FromNode: "generate-sms-page", ToNode: "validate-sms-data", }, { ID: "validate-to-route", FromNode: "validate-sms-data", ToNode: "route-sms-provider", }, { ID: "route-to-phone-validate", FromNode: "route-sms-provider", ToNode: "validate-phones-spam", }, { ID: "phone-validate-to-dispatch", FromNode: "validate-phones-spam", ToNode: "dispatch-sms", }, { ID: "dispatch-to-notify", FromNode: "dispatch-sms", ToNode: "notify-user", }, { ID: "notify-to-store", FromNode: "notify-user", ToNode: "store-sms-report", }, { ID: "store-to-webhook", FromNode: "store-sms-report", ToNode: "webhook-receiver", }, }, Variables: map[string]workflow.Variable{ "username": { Name: "username", Type: "string", Required: true, Description: "User username for authentication", }, "password": { Name: "password", Type: "string", Required: true, Description: "User password for authentication", }, "recipients": { Name: "recipients", Type: "array", Required: true, Description: "List of SMS recipients", }, "message": { Name: "message", Type: "string", Required: true, Description: "SMS message content", }, }, } } func createWebhookHandlerWorkflow() *workflow.WorkflowDefinition { return &workflow.WorkflowDefinition{ ID: "sms-webhook-handler", Name: "SMS Webhook Handler", Description: "Processes SMS delivery status webhooks from providers", Version: "1.0.0", Status: workflow.WorkflowStatusActive, Nodes: []workflow.WorkflowNode{ { ID: "parse-webhook", Name: "Parse Webhook Data", Type: workflow.NodeTypeTransform, Description: "Parse incoming webhook payload", Config: workflow.NodeConfig{ TransformType: "json_parse", Expression: "$.webhook_data", }, }, { ID: "validate-webhook", Name: "Validate Webhook", Type: workflow.NodeTypeValidator, Description: "Validate webhook signature and data", Config: workflow.NodeConfig{ ValidationType: "strict", ValidationRules: []workflow.ValidationRule{ { Field: "message_id", Type: "required", Message: "Message ID required", }, { Field: "status", Type: "required", Message: "Delivery status required", }, }, }, }, { ID: "update-report", Name: "Update SMS Report", Type: workflow.NodeTypeStorage, Description: "Update SMS report with delivery status", Config: workflow.NodeConfig{ StorageType: "database", StoragePath: "sms_reports", StorageConfig: map[string]string{ "operation": "update", "table": "sms_reports", }, }, }, { ID: "send-final-notification", Name: "Send Final Notification", Type: workflow.NodeTypeNotify, Description: "Send final delivery notification to user", Config: workflow.NodeConfig{ NotifyType: "email", Channel: "smtp", }, }, }, Edges: []workflow.WorkflowEdge{ { ID: "parse-to-validate", FromNode: "parse-webhook", ToNode: "validate-webhook", }, { ID: "validate-to-update", FromNode: "validate-webhook", ToNode: "update-report", }, { ID: "update-to-notify", FromNode: "update-report", ToNode: "send-final-notification", }, }, } } func setupRoutes(app *fiber.App, engine *workflow.WorkflowEngine, userManager *workflow.UserManager, middlewareManager *workflow.MiddlewareManager) { // Main page app.Get("/", func(c *fiber.Ctx) error { return c.JSON(fiber.Map{ "message": "🚀 Advanced SMS Workflow Engine", "version": "2.0.0", "features": []string{ "Sub-DAG Support", "HTML Page Generation", "SMS Pipeline with Provider Routing", "User Authentication & Authorization", "Middleware System", "Webhook Receivers", "Real-time Reporting", }, "endpoints": map[string]string{ "sms": "/sms - SMS Pipeline Demo", "auth": "/auth - Authentication Demo", "admin": "/admin - Admin Dashboard", "docs": "/docs - API Documentation", "webhook": "/webhook/sms/status - SMS Status Webhook", }, }) }) // SMS Pipeline routes app.Post("/sms/send", func(c *fiber.Ctx) error { var request map[string]interface{} if err := c.BodyParser(&request); err != nil { return c.Status(400).JSON(fiber.Map{"error": "Invalid request body"}) } // Execute middleware chain result := middlewareManager.Execute(c.Context(), request) if !result.Continue { return c.Status(401).JSON(fiber.Map{"error": result.Error.Error()}) } // Execute SMS workflow execution, err := engine.ExecuteWorkflow(c.Context(), "sms-pipeline", request, &workflow.ExecutionOptions{ Priority: workflow.PriorityHigh, Owner: "sms-api", }) if err != nil { return c.Status(500).JSON(fiber.Map{"error": err.Error()}) } return c.JSON(fiber.Map{ "success": true, "execution_id": execution.ID, "status": execution.Status, "message": "SMS workflow started successfully", }) }) // Authentication routes app.Post("/auth/login", func(c *fiber.Ctx) error { var credentials struct { Username string `json:"username"` Password string `json:"password"` } if err := c.BodyParser(&credentials); err != nil { return c.Status(400).JSON(fiber.Map{"error": "Invalid credentials format"}) } authContext, err := userManager.AuthenticateUser(credentials.Username, credentials.Password) if err != nil { return c.Status(401).JSON(fiber.Map{"error": "Invalid credentials"}) } return c.JSON(fiber.Map{ "success": true, "token": authContext.Token, "user": authContext.User, "expires_at": time.Now().Add(24 * time.Hour), }) }) app.Post("/auth/validate", func(c *fiber.Ctx) error { token := c.Get("Authorization") if token == "" { return c.Status(400).JSON(fiber.Map{"error": "Authorization header required"}) } authContext, err := userManager.ValidateSession(token) if err != nil { return c.Status(401).JSON(fiber.Map{"error": "Invalid token"}) } return c.JSON(fiber.Map{ "valid": true, "user": authContext.User, }) }) // Admin routes app.Get("/admin/workflows", func(c *fiber.Ctx) error { workflows, err := engine.ListWorkflows(c.Context(), &workflow.WorkflowFilter{}) if err != nil { return c.Status(500).JSON(fiber.Map{"error": err.Error()}) } return c.JSON(fiber.Map{ "workflows": workflows, "total": len(workflows), }) }) app.Get("/admin/executions", func(c *fiber.Ctx) error { executions, err := engine.ListExecutions(c.Context(), &workflow.ExecutionFilter{}) if err != nil { return c.Status(500).JSON(fiber.Map{"error": err.Error()}) } return c.JSON(fiber.Map{ "executions": executions, "total": len(executions), }) }) // SMS status webhook endpoint app.Post("/webhook/sms/status", func(c *fiber.Ctx) error { var webhookData map[string]interface{} if err := c.BodyParser(&webhookData); err != nil { return c.Status(400).JSON(fiber.Map{"error": "Invalid webhook data"}) } // Execute webhook handler workflow execution, err := engine.ExecuteWorkflow(c.Context(), "sms-webhook-handler", webhookData, &workflow.ExecutionOptions{ Priority: workflow.PriorityHigh, Owner: "webhook-handler", }) if err != nil { log.Printf("Webhook handler error: %v", err) return c.Status(500).JSON(fiber.Map{"error": "Webhook processing failed"}) } log.Printf("SMS webhook processed: execution_id=%s", execution.ID) return c.JSON(fiber.Map{"status": "processed", "execution_id": execution.ID}) }) // Demo pages with proper authentication flow app.Get("/login", func(c *fiber.Ctx) error { html := ` SMS Workflow - Login

🔐 SMS Workflow Login

Demo Users:

admin / password (Full access)

manager / password (Write access)

operator / password (Read access)

` return c.Type("html").Send([]byte(html)) }) app.Get("/sms", func(c *fiber.Ctx) error { // For /sms page, we'll check authentication on the client side // since we store the token in sessionStorage // The server will serve the page and let JavaScript handle auth check html := ` SMS Workflow Pipeline

🚀 SMS Workflow Pipeline

1

Enter SMS Details

2

Choose SMS Provider

🤖 Auto-Select (Recommended)

Let the system choose the best provider based on cost and delivery rates

📱 Twilio

Premium provider with high delivery rates - $0.0075/SMS

🌍 Vonage (Nexmo)

Global coverage with competitive pricing - $0.0065/SMS

☁️ AWS SNS

Reliable cloud-based SMS service - $0.0055/SMS

3

Send SMS & Wait for Delivery Status

📋 SMS Preview:

Sending SMS...

Please wait while we process your SMS through the workflow pipeline

` return c.Type("html").Send([]byte(html)) }) // API Documentation app.Get("/docs", func(c *fiber.Ctx) error { return c.JSON(fiber.Map{ "title": "Advanced SMS Workflow Engine API", "version": "2.0.0", "endpoints": map[string]interface{}{ "POST /auth/login": map[string]interface{}{ "description": "Authenticate user and get token", "body": map[string]string{ "username": "string", "password": "string", }, }, "POST /sms/send": map[string]interface{}{ "description": "Send SMS through workflow pipeline", "headers": map[string]string{ "Authorization": "Bearer token", }, "body": map[string]interface{}{ "recipients": []string{"+1234567890"}, "message": "string", "provider": "auto|twilio|nexmo", }, }, "POST /webhook/sms/status": map[string]interface{}{ "description": "Receive SMS delivery status webhook", "body": map[string]interface{}{ "message_id": "string", "status": "delivered|failed|pending", "timestamp": "ISO 8601 string", }, }, }, "workflows": []string{ "user-auth-subdag - User authentication sub-workflow", "sms-pipeline - Complete SMS sending pipeline", "sms-webhook-handler - SMS delivery status handler", }, }) }) log.Println("✅ All routes configured successfully") }