// StartConsuming enters a loop and waits for incoming messages func (amqpBroker *AMQPBroker) StartConsuming(consumerTag string, taskProcessor TaskProcessor) (bool, error) { if amqpBroker.retryFunc == nil { amqpBroker.retryFunc = utils.RetryClosure() } conn, channel, queue, _, err := amqpBroker.open() if err != nil { amqpBroker.retryFunc() return amqpBroker.retry, err // retry true } defer amqpBroker.close(channel, conn) amqpBroker.retryFunc = utils.RetryClosure() amqpBroker.stopChan = make(chan int) if err := channel.Qos( 3, // prefetch count 0, // prefetch size false, // global ); err != nil { return amqpBroker.retry, fmt.Errorf("Channel Qos: %s", err) } deliveries, err := channel.Consume( queue.Name, // queue consumerTag, // consumer tag false, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // arguments ) if err != nil { return amqpBroker.retry, fmt.Errorf("Queue Consume: %s", err) } log.Print("[*] Waiting for messages. To exit press CTRL+C") if err := amqpBroker.consume(deliveries, taskProcessor); err != nil { return amqpBroker.retry, err // retry true } return amqpBroker.retry, nil }
// StartConsuming enters a loop and waits for incoming messages func (redisBroker *RedisBroker) StartConsuming(consumerTag string, taskProcessor TaskProcessor) (bool, error) { if redisBroker.retryFunc == nil { redisBroker.retryFunc = utils.RetryClosure() } redisBroker.pool = redisBroker.newPool() defer redisBroker.pool.Close() _, err := redisBroker.pool.Get().Do("PING") if err != nil { redisBroker.retryFunc() return redisBroker.retry, err // retry true } redisBroker.retryFunc = utils.RetryClosure() redisBroker.stopChan = make(chan int) redisBroker.stopReceivingChan = make(chan int) redisBroker.errorsChan = make(chan error) deliveries := make(chan []byte) redisBroker.wg.Add(1) go func() { defer redisBroker.wg.Done() log.Print("[*] Waiting for messages. To exit press CTRL+C") conn := redisBroker.pool.Get() for { select { // A way to stop this goroutine from redisBroker.StopConsuming case <-redisBroker.stopReceivingChan: return default: itemBytes, err := conn.Do("BLPOP", redisBroker.config.DefaultQueue, "1") if err != nil { redisBroker.errorsChan <- err return } // Unline BLPOP, LPOP is non blocking so nil means we can keep iterating if itemBytes == nil { continue } items, err := redis.ByteSlices(itemBytes, nil) if err != nil { redisBroker.errorsChan <- err return } if len(items) != 2 { log.Println("Got unexpected amount of byte arrays, ignoring") continue } // items[0] - queue name (key), items[1] - value item := items[1] signature := new(signatures.TaskSignature) if err := json.Unmarshal(item, signature); err != nil { redisBroker.errorsChan <- err return } // If the task is not registered, we requeue it, // there might be different workers for processing specific tasks if !redisBroker.IsTaskRegistered(signature.Name) { _, err := conn.Do("RPUSH", redisBroker.config.DefaultQueue, item) if err != nil { redisBroker.errorsChan <- err return } continue } deliveries <- item } } }() if err := redisBroker.consume(deliveries, taskProcessor); err != nil { return redisBroker.retry, err // retry true } return redisBroker.retry, nil }