func (channel *Channel) ackBelow(tag uint64, commitTx bool) *amqp.AMQPError { if channel.txMode && !commitTx { channel.txLock.Lock() defer channel.txLock.Unlock() channel.txAcks = append(channel.txAcks, amqp.NewTxAck(tag, false, false, true)) return nil } channel.ackLock.Lock() defer channel.ackLock.Unlock() for k, unacked := range channel.awaitingAcks { if k <= tag || tag == 0 { consumer, cFound := channel.consumers[unacked.ConsumerTag] // Initialize resource holders array var rhs = []amqp.MessageResourceHolder{channel} if cFound { rhs = append(rhs, consumer) } err := channel.server.msgStore.RemoveRef(unacked.Msg, unacked.QueueName, rhs) // TODO: if this was an error do I still delete the ack we're waiting for? // The resources probably haven't been released. if err != nil { return amqp.NewSoftError(500, err.Error(), 60, 80) } delete(channel.awaitingAcks, k) if cFound { consumer.Ping() } } } // TODO: should this be an error if nothing was actually deleted and tag != 0? return nil }
func (channel *Channel) nackBelow(tag uint64, requeue bool, commitTx bool) *amqp.AMQPError { channel.ackLock.Lock() defer channel.ackLock.Unlock() // Transaction mode if channel.txMode && !commitTx { channel.txLock.Lock() defer channel.txLock.Unlock() channel.txAcks = append(channel.txAcks, amqp.NewTxAck(tag, true, requeue, true)) return nil } // Non-transaction mode var count = 0 for k, unacked := range channel.awaitingAcks { if k <= tag || tag == 0 { count += 1 // Init consumer, cFound := channel.consumers[unacked.ConsumerTag] queue, qFound := channel.server.queues[unacked.QueueName] // Initialize resource holders array var rhs = []amqp.MessageResourceHolder{channel} if cFound { rhs = append(rhs, consumer) } // requeue and release the approriate resources if requeue && qFound { // If we're requeueing we release the resources but don't remove the // reference. queue.Readd(unacked.QueueName, unacked.Msg) for _, rh := range rhs { rh.ReleaseResources(unacked.Msg) } } else { // If we aren't re-adding, remove the ref and all associated // resources err := channel.server.msgStore.RemoveRef(unacked.Msg, unacked.QueueName, rhs) if err != nil { return amqp.NewSoftError(500, err.Error(), 60, 120) } } // Remove this unacked message from the ones // we're waiting for acks on and ping the consumer // since there might be a message available now delete(channel.awaitingAcks, k) if cFound { consumer.Ping() } } } return nil }
func (channel *Channel) ackOne(tag uint64, commitTx bool) *amqp.AMQPError { channel.ackLock.Lock() defer channel.ackLock.Unlock() var unacked, found = channel.awaitingAcks[tag] if !found { var msg = fmt.Sprintf("Precondition Failed: Delivery Tag not found: %d", tag) return amqp.NewSoftError(406, msg, 60, 80) } // Tx mode if channel.txMode && !commitTx { channel.txLock.Lock() defer channel.txLock.Unlock() channel.txAcks = append(channel.txAcks, amqp.NewTxAck(tag, false, false, false)) return nil } // Normal mode // Init consumer, cFound := channel.consumers[unacked.ConsumerTag] // Initialize resource holders array var rhs = []amqp.MessageResourceHolder{channel} if cFound { rhs = append(rhs, consumer) } err := channel.server.msgStore.RemoveRef(unacked.Msg, unacked.QueueName, rhs) // TODO: if this is an error, do I still delete the tag? the resources // probably haven't been freed if err != nil { return amqp.NewSoftError(500, err.Error(), 60, 80) } delete(channel.awaitingAcks, tag) if cFound { consumer.Ping() } return nil }