mirror of
				https://github.com/oarkflow/mq.git
				synced 2025-11-01 02:12:32 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			170 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package main
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 
 | |
| 	"github.com/oarkflow/json"
 | |
| 
 | |
| 	"github.com/oarkflow/mq"
 | |
| 	"github.com/oarkflow/mq/dag"
 | |
| 	"github.com/oarkflow/mq/examples/tasks"
 | |
| )
 | |
| 
 | |
| // subDAG1 creates a SubDAG
 | |
| func subDAG1() *dag.DAG {
 | |
| 	f := dag.NewDAG("Sub DAG 1", "sub-dag-1", func(taskID string, result mq.Result) {
 | |
| 		fmt.Printf("Sub DAG 1 Final result for task %s: %s\n", taskID, string(result.Payload))
 | |
| 	}, mq.WithSyncMode(true))
 | |
| 	f.
 | |
| 		AddNode(dag.Function, "Store Data", "store", &tasks.StoreData{Operation: dag.Operation{Type: dag.Function}}, true).
 | |
| 		AddNode(dag.Function, "Send SMS", "sms", &tasks.SendSms{Operation: dag.Operation{Type: dag.Function}}).
 | |
| 		AddEdge(dag.Simple, "Store to SMS", "store", "sms")
 | |
| 	return f
 | |
| }
 | |
| 
 | |
| // subDAG2 creates another SubDAG
 | |
| func subDAG2() *dag.DAG {
 | |
| 	f := dag.NewDAG("Sub DAG 2", "sub-dag-2", func(taskID string, result mq.Result) {
 | |
| 		fmt.Printf("Sub DAG 2 Final result for task %s: %s\n", taskID, string(result.Payload))
 | |
| 	}, mq.WithSyncMode(true))
 | |
| 	f.
 | |
| 		AddNode(dag.Function, "Prepare Email", "prepare", &tasks.PrepareEmail{Operation: dag.Operation{Type: dag.Function}}, true).
 | |
| 		AddNode(dag.Function, "Email Delivery", "email", &tasks.EmailDelivery{Operation: dag.Operation{Type: dag.Function}}).
 | |
| 		AddEdge(dag.Simple, "Prepare to Email", "prepare", "email")
 | |
| 	return f
 | |
| }
 | |
| 
 | |
| func main() {
 | |
| 	flow := dag.NewDAG("Complex Sample DAG", "complex-sample-dag", func(taskID string, result mq.Result) {
 | |
| 		fmt.Printf("Complex DAG Final result for task %s: %s\n", taskID, string(result.Payload))
 | |
| 	})
 | |
| 	flow.ConfigureMemoryStorage()
 | |
| 
 | |
| 	// Main nodes
 | |
| 	flow.AddNode(dag.Function, "Get Data", "GetData", &GetData{}, true)
 | |
| 	flow.AddNode(dag.Function, "Main Loop", "MainLoop", &MainLoop{})
 | |
| 	flow.AddNode(dag.Function, "Validate", "Validate", &Validate{})
 | |
| 	flow.AddNode(dag.Function, "Process Valid", "ProcessValid", &ProcessValid{})
 | |
| 	flow.AddNode(dag.Function, "Process Invalid", "ProcessInvalid", &ProcessInvalid{})
 | |
| 	flow.AddDAGNode(dag.Function, "Sub DAG 1", "Sub1", subDAG1())
 | |
| 	flow.AddDAGNode(dag.Function, "Sub DAG 2", "Sub2", subDAG2())
 | |
| 	flow.AddNode(dag.Function, "Aggregate", "Aggregate", &Aggregate{})
 | |
| 	flow.AddNode(dag.Function, "Final", "Final", &Final{})
 | |
| 
 | |
| 	// Edges
 | |
| 	flow.AddEdge(dag.Simple, "Start", "GetData", "MainLoop")
 | |
| 	flow.AddEdge(dag.Iterator, "Loop over data", "MainLoop", "Validate")
 | |
| 	flow.AddCondition("Validate", map[string]string{"valid": "ProcessValid", "invalid": "ProcessInvalid"})
 | |
| 	flow.AddEdge(dag.Simple, "Valid to Sub1", "ProcessValid", "Sub1")
 | |
| 	flow.AddEdge(dag.Simple, "Invalid to Sub2", "ProcessInvalid", "Sub2")
 | |
| 	flow.AddEdge(dag.Simple, "Sub1 to Aggregate", "Sub1", "Aggregate")
 | |
| 	flow.AddEdge(dag.Simple, "Sub2 to Aggregate", "Sub2", "Aggregate")
 | |
| 	flow.AddEdge(dag.Simple, "Main Loop to Final", "MainLoop", "Final")
 | |
| 
 | |
| 	data := []byte(`[
 | |
| 		{"name": "Alice", "age": "25", "valid": true},
 | |
| 		{"name": "Bob", "age": "17", "valid": false},
 | |
| 		{"name": "Charlie", "age": "30", "valid": true}
 | |
| 	]`)
 | |
| 	if flow.Error != nil {
 | |
| 		panic(flow.Error)
 | |
| 	}
 | |
| 
 | |
| 	rs := flow.Process(context.Background(), data)
 | |
| 	if rs.Error != nil {
 | |
| 		panic(rs.Error)
 | |
| 	}
 | |
| 	fmt.Println("Complex DAG Status:", rs.Status, "Topic:", rs.Topic)
 | |
| 	fmt.Println("Final Payload:", string(rs.Payload))
 | |
| }
 | |
| 
 | |
| // Task implementations
 | |
| 
 | |
| type GetData struct {
 | |
| 	dag.Operation
 | |
| }
 | |
| 
 | |
| func (p *GetData) ProcessTask(ctx context.Context, task *mq.Task) mq.Result {
 | |
| 	return mq.Result{Ctx: ctx, Payload: task.Payload}
 | |
| }
 | |
| 
 | |
| type MainLoop struct {
 | |
| 	dag.Operation
 | |
| }
 | |
| 
 | |
| func (p *MainLoop) ProcessTask(ctx context.Context, task *mq.Task) mq.Result {
 | |
| 	return mq.Result{Ctx: ctx, Payload: task.Payload}
 | |
| }
 | |
| 
 | |
| type Validate struct {
 | |
| 	dag.Operation
 | |
| }
 | |
| 
 | |
| func (p *Validate) ProcessTask(ctx context.Context, task *mq.Task) mq.Result {
 | |
| 	var data map[string]any
 | |
| 	if err := json.Unmarshal(task.Payload, &data); err != nil {
 | |
| 		return mq.Result{Error: fmt.Errorf("Validate Error: %s", err.Error()), Ctx: ctx}
 | |
| 	}
 | |
| 	status := "invalid"
 | |
| 	if valid, ok := data["valid"].(bool); ok && valid {
 | |
| 		status = "valid"
 | |
| 	}
 | |
| 	data["validated"] = true
 | |
| 	updatedPayload, _ := json.Marshal(data)
 | |
| 	return mq.Result{Payload: updatedPayload, Ctx: ctx, ConditionStatus: status}
 | |
| }
 | |
| 
 | |
| type ProcessValid struct {
 | |
| 	dag.Operation
 | |
| }
 | |
| 
 | |
| func (p *ProcessValid) ProcessTask(ctx context.Context, task *mq.Task) mq.Result {
 | |
| 	var data map[string]any
 | |
| 	if err := json.Unmarshal(task.Payload, &data); err != nil {
 | |
| 		return mq.Result{Error: fmt.Errorf("ProcessValid Error: %s", err.Error()), Ctx: ctx}
 | |
| 	}
 | |
| 	data["processed_valid"] = true
 | |
| 	updatedPayload, _ := json.Marshal(data)
 | |
| 	return mq.Result{Payload: updatedPayload, Ctx: ctx}
 | |
| }
 | |
| 
 | |
| type ProcessInvalid struct {
 | |
| 	dag.Operation
 | |
| }
 | |
| 
 | |
| func (p *ProcessInvalid) ProcessTask(ctx context.Context, task *mq.Task) mq.Result {
 | |
| 	var data map[string]any
 | |
| 	if err := json.Unmarshal(task.Payload, &data); err != nil {
 | |
| 		return mq.Result{Error: fmt.Errorf("ProcessInvalid Error: %s", err.Error()), Ctx: ctx}
 | |
| 	}
 | |
| 	data["processed_invalid"] = true
 | |
| 	updatedPayload, _ := json.Marshal(data)
 | |
| 	return mq.Result{Payload: updatedPayload, Ctx: ctx}
 | |
| }
 | |
| 
 | |
| type Aggregate struct {
 | |
| 	dag.Operation
 | |
| }
 | |
| 
 | |
| func (p *Aggregate) ProcessTask(ctx context.Context, task *mq.Task) mq.Result {
 | |
| 	return mq.Result{Payload: task.Payload, Ctx: ctx}
 | |
| }
 | |
| 
 | |
| type Final struct {
 | |
| 	dag.Operation
 | |
| }
 | |
| 
 | |
| func (p *Final) ProcessTask(ctx context.Context, task *mq.Task) mq.Result {
 | |
| 	var data []map[string]any
 | |
| 	if err := json.Unmarshal(task.Payload, &data); err != nil {
 | |
| 		return mq.Result{Error: fmt.Errorf("Final Error: %s", err.Error()), Ctx: ctx}
 | |
| 	}
 | |
| 	for i, row := range data {
 | |
| 		row["finalized"] = true
 | |
| 		data[i] = row
 | |
| 	}
 | |
| 	updatedPayload, _ := json.Marshal(data)
 | |
| 	return mq.Result{Payload: updatedPayload, Ctx: ctx}
 | |
| }
 | 
