func (b *bucket) GetMaxFetchNum() uint64 {
	return b.maxFetchNum
}
GetMaxFetchNum return the max number of job to fetch each time
package bucket
import (
	"errors"
	"fmt"
	"github.com/changsongl/delay-queue/job"
	"github.com/changsongl/delay-queue/pkg/lock"
	"github.com/changsongl/delay-queue/pkg/log"
	"github.com/changsongl/delay-queue/store"
	"github.com/prometheus/client_golang/prometheus"
	"sync"
	"sync/atomic"
	"time"
)
const (
	DefaultMaxFetchNum uint64 = 20
)
var (
	metricOnce sync.Once
)
type Bucket interface {
	CreateJob(j *job.Job, isTTR bool) error
	GetBuckets() []uint64
	GetBucketJobs(bid uint64) ([]job.NameVersion, error)
	GetMaxFetchNum() uint64
	SetMaxFetchNum(num uint64)
}
type bucket struct {
	s                store.Store           
	size             uint64                
	name             string                
	count            *uint64               
	locks            []lock.Locker         
	maxFetchNum      uint64                
	l                log.Logger            
	onFlightJobGauge *prometheus.GaugeVec  
}
func New(s store.Store, l log.Logger, size uint64, name string) Bucket {
	var c uint64 = 0
	b := &bucket{
		s:           s,
		size:        size,
		name:        name,
		count:       &c,
		l:           l,
		maxFetchNum: DefaultMaxFetchNum,
	}
	b.locks = make([]lock.Locker, 0, size)
	var i uint64 = 0
	for i < size {
		b.locks = append(b.locks, s.GetLock(b.getBucketNameByID(i)))
		i++
	}
	b.CollectMetrics()
	return b
}
func (b *bucket) CreateJob(j *job.Job, isTTR bool) error {
	currentBucket := b.getNextBucket()
	err := b.s.CreateJobInBucket(currentBucket, j, isTTR)
	return err
}
func (b *bucket) getNextBucket() string {
	current := atomic.AddUint64(b.count, 1)
	return b.getBucketNameByID(current % b.size)
}
func (b *bucket) getBucketNameByID(id uint64) string {
	return fmt.Sprintf("%s_%d", b.name, id)
}
func (b *bucket) GetBuckets() []uint64 {
	buckets := make([]uint64, 0, b.size)
	var i uint64 = 0
	for i < b.size {
		buckets = append(buckets, i)
		i++
	}
	return buckets
}
func (b *bucket) GetBucketJobs(bid uint64) ([]job.NameVersion, error) {
	bucketName := b.getBucketNameByID(bid)
	nameVersions, err := b.s.GetReadyJobsInBucket(bucketName, uint(b.maxFetchNum))
	if err != nil {
		return nil, err
	}
	return nameVersions, nil
}
func (b *bucket) GetLock(bid uint64) (lock.Locker, error) {
	if bid >= b.size {
		return nil, errors.New("invalid bucket id to get lock")
	}
	return b.locks[bid], nil
}