//ProcessMessage processes an amqp.Delivery within a context func ProcessMessage(c *ctx.Context, m *amqp.Delivery) { //Decode the payload var payload models.EventTrackingPayload err := json.Unmarshal(m.Body, &payload) if err != nil { c.Logger.Errorf("Impossible to decode payload from message - Error: %s", err.Error()) //We can ignore the err from Nack because auto-ack is false m.Nack(false, true) return } err = c.StorageDb.StoreBatchEvents(&payload) if err != nil { c.Logger.Errorf("Impossible to store payload from message - Error: %s", err.Error()) //We can ignore the err from Nack because auto-ack is false m.Nack(false, true) return } //ACK that the message has been processed sucessfully c.Logger.Infof("Sucessfully processed message: %s", m.MessageId) err = m.Ack(false) if err != nil { c.Logger.Infof("Could not ack message: %s", err.Error()) } return }
// DefaultErrHandler controls the errors, return false if an error occurred func (c *Controller) DefaultErrHandler(delivery amqp.Delivery, err error) bool { if delivery.Redelivered { c.log.Error("Redelivered message gave error again, putting to maintenance queue", err) delivery.Ack(false) return true } c.log.Error("an error occurred while sending email error as %+v ", err.Error()) delivery.Nack(false, true) return false }
func (p *DefaultDeliverer) Deliver(d amqp.Delivery, cfg config.EndpointConfig) { queueName, ok := cfg.QueueConfig["queuename"].(string) if !ok { queueName = "(unknown)" } log.Printf("Received a message on %s", queueName) requeue, err := processMsg(d, cfg) if err != nil { log.Printf("%s: %s", cfg.Name, err) d.Nack(false, requeue) } else { log.Printf("%s: Message Processed", cfg.Name) d.Ack(false) } }
// Consume a single message func (amqpBroker *AMQPBroker) consumeOne(d amqp.Delivery, taskProcessor TaskProcessor, errorsChan chan error) { if len(d.Body) == 0 { d.Nack(false, false) // multiple, requeue errorsChan <- errors.New("Received an empty message.") // RabbitMQ down? return } log.Printf("Received new message: %s", d.Body) signature := signatures.TaskSignature{} if err := json.Unmarshal(d.Body, &signature); err != nil { d.Nack(false, false) // multiple, requeue errorsChan <- err return } // If the task is not registered, we nack it and requeue, // there might be different workers for processing specific tasks if !amqpBroker.IsTaskRegistered(signature.Name) { d.Nack(false, true) // multiple, requeue return } if err := taskProcessor.Process(&signature); err != nil { errorsChan <- err } d.Ack(false) // multiple }
// DefaultErrHandler handles the errors, we dont need to ack a message, // continue to the success func (c *Controller) DefaultErrHandler(delivery amqp.Delivery, err error) bool { c.log.Error("an error occurred putting message back to queue", err) delivery.Nack(false, true) return false }
func parseMessage(msg amqp.Delivery) { debug.Println("Msg:", string(msg.Body)) m := &totemResult{} err := json.Unmarshal(msg.Body, m) if err != nil { warning.Printf("Could not decode msg: %s\n", msg.Body) msg.Nack(false, false) return } /* // This approach has been revised since the data is now // saved as string and not as pure JSON document. // since totem sends the results as json encoded string // (which contains json) we need to unmarshal data // and save it this way. var resData interface{} err = json.Unmarshal([]byte(m.Data), &resData) if err != nil { warning.Printf("Could not decode data: %s\n", m.Data) msg.Nack(false, false) return } */ // TODO: Add validation to received msg //m.Validate() // TODO: Totem needs to send more data // TODO: Totem needs to send hashes lowercase result := &storerGeneric.Result{ Id: "", //will be filled by the storage engine SHA256: strings.ToLower(m.SHA256), //totem currently send the hash all upper case SchemaVersion: "1", UserId: "NotSend", SourceId: []string{"NotSend"}, SourceTag: []string{"NotSend"}, ServiceName: strings.SplitN(msg.RoutingKey, ".", 2)[0], ServiceVersion: "NotSend", ServiceConfig: "NotSend", ObjectCategory: []string{"NotSend"}, ObjectType: "sample", Results: m.Data, Tags: m.Tags, StartedDateTime: time.Now(), FinishedDateTime: time.Now(), WatchguardStatus: "NotImplemented", WatchguardLog: []string{"NotImplemented"}, WatchguardVersion: "NotImplemented", } err = mainStorer.StoreResult(result) if err != nil { if strings.Contains(err.Error(), "Size must be between 0 and 16793600") { warning.Println("Message to large, dropped!", err.Error()) msg.Ack(false) return } warning.Println("Failed to safe result:", err.Error(), "SHA256:", m.SHA256) msg.Nack(false, true) return } debug.Println("Msg saved successfully!") msg.Ack(false) }
// DefaultErrHandler handles the errors for collaboration worker func (t *Controller) DefaultErrHandler(delivery amqp.Delivery, err error) bool { delivery.Nack(false, true) return false }
func (s *Server) handleDelivery(d amqp.Delivery) { defer func() { <-s.parallelMethods s.wg.Done() }() if d.CorrelationId == "" || d.ReplyTo == "" { d.Nack(false, false) // drop message logf("dropped message: %+v", d) return } var ( msg rpcMsg ret []byte err error ) if err = json.Unmarshal(d.Body, &msg); err == nil { f, ok := s.methods[msg.Method] if ok { ret, err = f(d.CorrelationId, msg.Data) } else { err = errors.New("method has not been registered") } } else { err = errors.New("cannot unmarshal message") } errStr := "" if err != nil { errStr = err.Error() } result := &Result{ UUID: d.CorrelationId, Data: ret, Err: errStr, } body, err := json.Marshal(result) if err != nil { d.Nack(false, true) // requeue message logf("requeued message: %+v", d) return } // guarantee that the received ack/nack corresponds with this publishing s.ac.mu.Lock() defer s.ac.mu.Unlock() err = s.ac.channel.Publish( "", // exchange d.ReplyTo, // key false, // mandatory false, // immediate amqp.Publishing{ // msg CorrelationId: d.CorrelationId, ReplyTo: d.ReplyTo, ContentType: "application/json", Body: body, DeliveryMode: uint8(s.DeliveryMode), }, ) if err != nil { d.Nack(false, true) // requeue message return } select { case _, ok := <-s.ac.acks: if ok { d.Ack(false) return } case tag, ok := <-s.ac.nacks: if ok { logf("nack recived (%v)", tag) d.Nack(false, true) // requeue message return } } logf("missing ack/nack") d.Nack(false, true) // requeue message }