//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
}
Пример #2
0
// 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
}
Пример #3
0
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)
	}
}
Пример #4
0
// 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
}
Пример #5
0
// 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
}
Пример #6
0
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)
}
Пример #7
0
// DefaultErrHandler handles the errors for collaboration worker
func (t *Controller) DefaultErrHandler(delivery amqp.Delivery, err error) bool {
	delivery.Nack(false, true)
	return false
}
Пример #8
0
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
}