package runner import ( "context" "fmt" "log/slog" "queryorchestration/internal/serviceconfig/queue" ) type Server struct { cleanup func() error cfg ListenerConfig } func (c *Server) Listen(ctx context.Context) { slog.Info("Listening to queue") defer func() { if err := c.cleanup(); err != nil { fmt.Printf("Error during cleanup: %v", err) } }() // TODO need to slow down the polling so we are not spinning the cpu or burning up API calls. for { select { case <-ctx.Done(): return default: err := c.pollMessage(ctx) if err != nil { slog.Error(err.Error()) } } } } // Alternative without go func if no pool is needed. // Just for comment for the next function which needs to be made safe. //func (c *Server) pollMessage(ctx context.Context) error { // cfg := &queue.Config{ // URL: c.queueURL, // Client: c.client, // } // result, err := queue.Receive(ctx, cfg, []string{"type"}) // if err != nil { // return fmt.Errorf("message fetch fail: %v", err) // } // // for _, message := range result.Messages { // if err := c.controller.Process(ctx, &message); err != nil { // return fmt.Errorf("message process fail: %v", err) // } // // if err := queue.Delete(ctx, cfg, &message); err != nil { // return fmt.Errorf("message delete fail: %v", err) // } // } // // return nil //} func (c *Server) pollMessage(ctx context.Context) error { result, err := c.cfg.ReceiveFromQueue(ctx, &queue.ReceiveParams{ QueueURL: c.cfg.GetQueueURL(), }) if err != nil { return fmt.Errorf("message fetch fail: %v", err) } for _, message := range result.Messages { // TODO Need to remove this go func() !! // Must not have uncontrolled go routine creation. See commented example above if // simple case. // if process takes too long to complete then we need to use a thread pool. go func() { err := c.cfg.GetController().Process(ctx, &message) if err != nil { slog.Error("message process fail", "err", err) } err = c.cfg.DeleteFromQueue(ctx, &queue.DeleteParams{ QueueURL: c.cfg.GetQueueURL(), ReceiptHandle: message.ReceiptHandle, }) if err != nil { slog.Error("message delete fail", "err", err) } }() } return nil }