func (q *Queue) Delete(msg *taskq.Message) error {
	err := retry(func() error {
		return q.q.DeleteMessage(msg.ID, msg.ReservationID)
	})
	if err == nil {
		return nil
	}
	if v, ok := err.(api.HTTPResponseError); ok && v.StatusCode() == 404 {
		return nil
	}
	return err
}
Delete deletes the message from the queue.
package ironmq
import (
	"context"
	"errors"
	"fmt"
	"strings"
	"time"
	"github.com/iron-io/iron_go3/api"
	"github.com/iron-io/iron_go3/mq"
	"github.com/vmihailenco/taskq/v3"
	"github.com/vmihailenco/taskq/v3/internal"
	"github.com/vmihailenco/taskq/v3/internal/base"
	"github.com/vmihailenco/taskq/v3/internal/msgutil"
	"github.com/vmihailenco/taskq/v3/memqueue"
)
type Queue struct {
	opt *taskq.QueueOptions
	q mq.Queue
	addQueue *memqueue.Queue
	addTask  *taskq.Task
	delQueue   *memqueue.Queue
	delTask    *taskq.Task
	delBatcher *base.Batcher
	consumer *taskq.Consumer
}
var _ taskq.Queue = (*Queue)(nil)
func NewQueue(mqueue mq.Queue, opt *taskq.QueueOptions) *Queue {
	if opt.Name == "" {
		opt.Name = mqueue.Name
	}
	opt.Init()
	q := &Queue{
		q:   mqueue,
		opt: opt,
	}
	q.initAddQueue()
	q.initDelQueue()
	return q
}
func (q *Queue) initAddQueue() {
	queueName := "ironmq:" + q.opt.Name + ":add"
	q.addQueue = memqueue.NewQueue(&taskq.QueueOptions{
		Name:       queueName,
		BufferSize: 100,
		Redis:      q.opt.Redis,
	})
	q.addTask = taskq.RegisterTask(&taskq.TaskOptions{
		Name:            queueName + ":add-mesage",
		Handler:         taskq.HandlerFunc(q.add),
		FallbackHandler: msgutil.UnwrapMessageHandler(q.opt.Handler.HandleMessage),
		RetryLimit:      3,
		MinBackoff:      time.Second,
	})
}
func (q *Queue) initDelQueue() {
	queueName := "ironmq:" + q.opt.Name + ":delete"
	q.delQueue = memqueue.NewQueue(&taskq.QueueOptions{
		Name:       queueName,
		BufferSize: 100,
		Redis:      q.opt.Redis,
	})
	q.delTask = taskq.RegisterTask(&taskq.TaskOptions{
		Name:       queueName + ":delete-message",
		Handler:    taskq.HandlerFunc(q.delBatcherAdd),
		RetryLimit: 3,
		MinBackoff: time.Second,
	})
	q.delBatcher = base.NewBatcher(q.delQueue.Consumer(), &base.BatcherOptions{
		Handler:     q.deleteBatch,
		ShouldBatch: q.shouldBatchDelete,
	})
}
func (q *Queue) Name() string {
	return q.q.Name
}
func (q *Queue) String() string {
	return fmt.Sprintf("queue=%q", q.Name())
}
func (q *Queue) Options() *taskq.QueueOptions {
	return q.opt
}
func (q *Queue) Consumer() taskq.QueueConsumer {
	if q.consumer == nil {
		q.consumer = taskq.NewConsumer(q)
	}
	return q.consumer
}
func (q *Queue) createQueue() error {
	_, err := mq.ConfigCreateQueue(mq.QueueInfo{Name: q.q.Name}, &q.q.Settings)
	return err
}
func (q *Queue) Len() (int, error) {
	queueInfo, err := q.q.Info()
	if err != nil {
		return 0, err
	}
	return queueInfo.Size, nil
}
func (q *Queue) Add(msg *taskq.Message) error {
	if msg.TaskName == "" {
		return internal.ErrTaskNameRequired
	}
	if q.isDuplicate(msg) {
		msg.Err = taskq.ErrDuplicate
		return nil
	}
	msg = msgutil.WrapMessage(msg)
	msg.TaskName = q.addTask.Name()
	return q.addQueue.Add(msg)
}
func (q *Queue) ReserveN(
	ctx context.Context, n int, waitTimeout time.Duration,
) ([]taskq.Message, error) {
	if n > 100 {
		n = 100
	}
	reservationSecs := int(q.opt.ReservationTimeout / time.Second)
	waitSecs := int(waitTimeout / time.Second)
	mqMsgs, err := q.q.LongPoll(n, reservationSecs, waitSecs, false)
	if err != nil {
		if v, ok := err.(api.HTTPResponseError); ok && v.StatusCode() == 404 {
			if strings.Contains(v.Error(), "Message not found") {
				return nil, nil
			}
			if strings.Contains(v.Error(), "Queue not found") {
				_ = q.createQueue()
			}
		}
		return nil, err
	}
	msgs := make([]taskq.Message, len(mqMsgs))
	for i, mqMsg := range mqMsgs {
		msg := &msgs[i]
		b, err := internal.DecodeString(mqMsg.Body)
		if err != nil {
			msg.Err = err
		} else {
			err = msg.UnmarshalBinary(b)
			if err != nil {
				msg.Err = err
			}
		}
		msg.ID = mqMsg.Id
		msg.ReservationID = mqMsg.ReservationId
		msg.ReservedCount = mqMsg.ReservedCount
	}
	return msgs, nil
}
func (q *Queue) Release(msg *taskq.Message) error {
	return retry(func() error {
		return q.q.ReleaseMessage(msg.ID, msg.ReservationID, int64(msg.Delay/time.Second))
	})
}