예제 #1
0
파일: consumer.go 프로젝트: nabeken/delayd2
// ConsumeMessages consumes messages in SQS queue.
// It returns the number of consumed message in success.
func (c *Consumer) ConsumeMessages() (int64, error) {
	messages, err := c.queue.ReceiveMessage(
		option.MaxNumberOfMessages(10),
		option.UseAllAttribute(),
	)
	if err != nil {
		return 0, err
	}

	var n int64

	succeededReceiptHandles := make([]*string, 0, len(messages))
	for _, m := range messages {
		duration, relayTo, err := extractDelayd2MessageAttributes(m)
		if err != nil {
			log.Printf("consumer: %s: unable to extract attributes. skipping.", *m.MessageId)
			continue
		}

		err = c.driver.Enqueue(*m.MessageId, duration, relayTo, *m.Body)
		if err != nil && err != ErrMessageDuplicated {
			log.Printf("consumer: %s: %s: unable to enqueue this message. skipping", *m.MessageId, err)
			continue
		}
		if err == ErrMessageDuplicated {
			// delete immediately if duplicated
			log.Printf("consumer: %s: %s", *m.MessageId, err)
		}
		succeededReceiptHandles = append(succeededReceiptHandles, m.ReceiptHandle)
		n++
	}

	if len(succeededReceiptHandles) > 0 {
		if err := c.queue.DeleteMessageBatch(succeededReceiptHandles...); err != nil {
			log.Printf("consumer: unable to delete messages in batch but continuing since messages will appear again: %s", err)
		}
	}
	return n, nil
}
예제 #2
0
파일: bench.go 프로젝트: nabeken/delayd2
func (c *BenchCommand) Recv(args []string) int {
	var config BenchRecvConfig

	if err := envconfig.Process("delayd2", &config); err != nil {
		c.Ui.Error(fmt.Sprintf("Unable to get configuration from envvars: %s", err))
		return 1
	}

	cmdFlags := flag.NewFlagSet("batch recv", flag.ContinueOnError)
	cmdFlags.IntVar(&config.NumberOfMessages, "n", 1000, "number of messages")

	if err := cmdFlags.Parse(args); err != nil {
		c.Ui.Error(c.Help())
		return 1
	}

	sqsSvc := sqs.New(session.New())
	q, err := queue.New(sqsSvc, config.QueueName)
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Unable to initialize SQS connection: %s", err))
		return 1
	}

	log.Print("bench: --- Configuration ---")
	log.Printf("bench: Number of messages to receive: %d", config.NumberOfMessages)
	log.Printf("bench: DELAYD2_QUEUE_NAME=%s", config.QueueName)

	errCh := make(chan error)

	log.Print("bench: starting")
	go func() {
		payloads := map[string]struct{}{}
		for {
			log.Printf("%d messages processed", len(payloads))
			if len(payloads) >= config.NumberOfMessages {
				break
			}

			messages, err := q.ReceiveMessage(
				option.MaxNumberOfMessages(10),
				option.UseAllAttribute(),
			)
			// continue even if we get an error
			if err != nil {
				log.Printf("unable to receive messages but continuing...: %s", err)
				continue
			}

			recipientHandles := make([]*string, 0, 10)
			for _, m := range messages {
				payloads[*m.Body] = struct{}{}
				recipientHandles = append(recipientHandles, m.ReceiptHandle)
			}

			if err := q.DeleteMessageBatch(recipientHandles...); err != nil {
				log.Printf("unable to delete message but continuing...: %s", err)
			}
		}

		log.Printf("%d messages received", config.NumberOfMessages)
		errCh <- nil
	}()

	select {
	case <-errCh:
		if err != nil {
			c.Ui.Error(fmt.Sprintf("Unable to receive messages: %s", err))
			return 1
		}
		log.Print("bench: done.")
	case <-c.ShutdownCh:
		log.Fatal("signal received.")
	}

	return 0
}