init: publisher

This commit is contained in:
sujit
2024-09-29 01:47:54 +05:45
parent 22140885b8
commit c4e93c31e4

View File

@@ -3,6 +3,7 @@ package main
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"log" "log"
"sync" "sync"
"time" "time"
@@ -14,25 +15,33 @@ func main() {
dag := NewDAG() dag := NewDAG()
dag.AddNode("queue1", func(ctx context.Context, task mq.Task) mq.Result { dag.AddNode("queue1", func(ctx context.Context, task mq.Task) mq.Result {
log.Printf("Handling task for queue1: %s", string(task.Payload)) log.Printf("Handling task for queue1: %s", string(task.Payload))
return mq.Result{Payload: []byte(`[{"user_id": 1}, {"user_id": 2}]`), MessageID: task.ID} return mq.Result{Payload: task.Payload, MessageID: task.ID}
}) })
dag.AddNode("queue2", func(ctx context.Context, task mq.Task) mq.Result { dag.AddNode("queue2", func(ctx context.Context, task mq.Task) mq.Result {
var item map[string]interface{} log.Printf("Handling task for queue2: %s", string(task.Payload))
if err := json.Unmarshal(task.Payload, &item); err != nil { return mq.Result{Payload: task.Payload, MessageID: task.ID}
return mq.Result{Payload: nil, Error: err, MessageID: task.ID} })
} dag.AddNode("queue3", func(ctx context.Context, task mq.Task) mq.Result {
item["salary"] = 12000 // Simulating task logic by adding "salary" var data map[string]any
result, _ := json.Marshal(item) err := json.Unmarshal(task.Payload, &data)
log.Printf("Handling task for queue2: %s", string(result)) if err != nil {
return mq.Result{Payload: result, MessageID: task.ID} return mq.Result{Error: err}
}
data["salary"] = fmt.Sprintf("12000%v", data["user_id"])
bt, _ := json.Marshal(data)
log.Printf("Handling task for queue3: %s", string(task.Payload))
return mq.Result{Payload: bt, MessageID: task.ID}
})
dag.AddNode("queue4", func(ctx context.Context, task mq.Task) mq.Result {
log.Printf("Handling task for queue4: %s", string(task.Payload))
return mq.Result{Payload: task.Payload, MessageID: task.ID}
}) })
dag.AddEdge("queue1", "queue2") dag.AddEdge("queue1", "queue2")
dag.AddLoop("queue1", "queue2") // This adds a loop between queue1 and queue2 dag.AddLoop("queue2", "queue3") // Add loop to handle array
go func() { go func() {
time.Sleep(2 * time.Second) time.Sleep(2 * time.Second)
finalResult := dag.Send([]byte(`{}`)) // sending empty payload to initiate finalResult := dag.Send([]byte(`[{"user_id": 1}, {"user_id": 2}]`))
log.Printf("Final result received: %s", string(finalResult.Payload)) log.Printf("Final result received: %s", string(finalResult.Payload))
}() }()
@@ -110,46 +119,32 @@ func (d *DAG) PublishTask(ctx context.Context, payload []byte, queueName string,
// TaskCallback is called when a task completes and decides the next step // TaskCallback is called when a task completes and decides the next step
func (d *DAG) TaskCallback(ctx context.Context, task *mq.Task) error { func (d *DAG) TaskCallback(ctx context.Context, task *mq.Task) error {
log.Printf("Callback from queue %s with result: %s", task.CurrentQueue, string(task.Result)) log.Printf("Callback from queue %s with result: %s", task.CurrentQueue, string(task.Result))
// Check if this task belongs to a loop
d.mu.Lock() d.mu.Lock()
loopCtx, isLoopTask := d.loopTaskMap[task.ID] loopCtx, isLoopTask := d.loopTaskMap[task.ID]
d.mu.Unlock() d.mu.Unlock()
if isLoopTask { if isLoopTask {
// Send the sub-task result to the loop's result channel
loopCtx.subResultCh <- mq.Result{Payload: task.Result, MessageID: task.ID} loopCtx.subResultCh <- mq.Result{Payload: task.Result, MessageID: task.ID}
} }
// Handle loopEdges first, if applicable
if loopNode, exists := d.loopEdges[task.CurrentQueue]; exists { if loopNode, exists := d.loopEdges[task.CurrentQueue]; exists {
// This is a loop node, and we need to handle array processing
var items []json.RawMessage var items []json.RawMessage
if err := json.Unmarshal(task.Result, &items); err != nil { if err := json.Unmarshal(task.Result, &items); err != nil {
return err return err
} }
// Create a loop task context to track the state of this loop
loopCtx := &loopTaskContext{ loopCtx := &loopTaskContext{
subResultCh: make(chan mq.Result, len(items)), // A channel to collect sub-task results subResultCh: make(chan mq.Result, len(items)), // A channel to collect sub-task results
totalItems: len(items), totalItems: len(items),
results: make([]json.RawMessage, 0, len(items)), results: make([]json.RawMessage, 0, len(items)),
} }
// Register the loop context for this task
d.mu.Lock() d.mu.Lock()
d.loopTaskMap[task.ID] = loopCtx d.loopTaskMap[task.ID] = loopCtx
d.mu.Unlock() d.mu.Unlock()
// Publish a sub-task for each item in the array
for _, item := range items { for _, item := range items {
_, err := d.PublishTask(ctx, item, loopNode, task.ID) _, err := d.PublishTask(ctx, item, loopNode, task.ID)
if err != nil { if err != nil {
return err return err
} }
} }
go d.waitForLoopCompletion(ctx, task.ID, task.CurrentQueue) go d.waitForLoopCompletion(ctx, task.ID, task.CurrentQueue)
return nil return nil
} }