func (p *Producer) Perform(job Job) (string, error) {
	return p.PerformCtx(context.Background(), job)
}
Perform calls PerformCtx with a default context.
It calls to Redis using a default background context.
It returns the ID of the enqueued job when successful or an error otherwise.
package curlyq
import (
	"context"
	"time"
	"github.com/go-redis/redis/v7"
)
type Producer struct {
	opts *ProducerOpts
	client *redis.Client
	queue  *queue
	pushJobScript     *redis.Script
	scheduleJobScript *redis.Script
}
type ProducerOpts struct {
	Address string
	Client *redis.Client
	Logger Logger
	Queue string
}
func (o *ProducerOpts) withDefaults() *ProducerOpts {
	opts := *o
	if opts.Logger == nil {
		opts.Logger = &DefaultLogger{}
	}
	return &opts
}
func NewProducer(opts *ProducerOpts) *Producer {
	if opts.Address == "" && opts.Client == nil {
		panic("A redis client must be provided.")
	}
	if opts.Queue == "" {
		panic("A queue name must be provided.")
	}
	var client *redis.Client
	if opts.Client != nil {
		client = opts.Client
	} else {
		client = redis.NewClient(&redis.Options{
			Addr: opts.Address,
		})
	}
	queue := newQueue(&queueOpts{
		Name: opts.Queue,
	})
	prepScripts()
	pushJobScript := loadLua("/lua/push_job.lua")
	scheduleJobScript := loadLua("/lua/schedule_job.lua")
	return &Producer{
		opts: opts.withDefaults(),
		client: client,
		queue:  queue,
		pushJobScript:     pushJobScript,
		scheduleJobScript: scheduleJobScript,
	}
}
func (p *Producer) PerformAfter(duration time.Duration, job Job) (string, error) {
	return p.PerformAfterCtx(context.Background(), duration, job)
}
func (p *Producer) PerformAfterCtx(ctx context.Context, duration time.Duration, job Job) (string, error) {
	return p.PerformAtCtx(ctx, time.Now().Add(duration), job)
}
func (p *Producer) PerformAt(at time.Time, job Job) (string, error) {
	return p.PerformAtCtx(context.Background(), at, job)
}
func (p *Producer) PerformAtCtx(ctx context.Context, at time.Time, job Job) (string, error) {
	return p.scheduleJob(ctx, at, job)
}