调整部分options
This commit is contained in:
+18
-4
@@ -55,9 +55,12 @@ type Cluster struct {
|
|||||||
|
|
||||||
// 初始化定时器
|
// 初始化定时器
|
||||||
// 全局只需要初始化一次
|
// 全局只需要初始化一次
|
||||||
func InitCluster(ctx context.Context, red redis.UniversalClient, keyPrefix string, opts ...Option) *Cluster {
|
func InitCluster(ctx context.Context, red redis.UniversalClient, keyPrefix string, opts ...Option) (*Cluster, error) {
|
||||||
|
|
||||||
|
if red == nil {
|
||||||
|
return nil, errors.New("redis is nil")
|
||||||
|
}
|
||||||
|
|
||||||
// clusterOnceLimit.Do(func() {
|
|
||||||
op := newOptions(opts...)
|
op := newOptions(opts...)
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
@@ -90,7 +93,13 @@ func InitCluster(ctx context.Context, red redis.UniversalClient, keyPrefix strin
|
|||||||
// 初始化优先级
|
// 初始化优先级
|
||||||
|
|
||||||
if clu.usePriority {
|
if clu.usePriority {
|
||||||
clu.priority = priority.InitPriority(ctx, red, clu.priorityKey, op.priorityVal, priority.SetLogger(clu.logger))
|
|
||||||
|
pri, err := priority.InitPriority(ctx, red, clu.priorityKey, op.priorityVal, priority.WithLogger(clu.logger))
|
||||||
|
if err != nil {
|
||||||
|
clu.logger.Errorf(ctx, "InitPriority err:%v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
clu.priority = pri
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启动守护进程
|
// 启动守护进程
|
||||||
@@ -98,7 +107,7 @@ func InitCluster(ctx context.Context, red redis.UniversalClient, keyPrefix strin
|
|||||||
|
|
||||||
clu.logger.Infof(ctx, "InitCluster success keyPrefix:%s instanceId:%s", clu.keyPrefix, clu.instanceId)
|
clu.logger.Infof(ctx, "InitCluster success keyPrefix:%s instanceId:%s", clu.keyPrefix, clu.instanceId)
|
||||||
|
|
||||||
return clu
|
return clu, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop 停止集群定时器
|
// Stop 停止集群定时器
|
||||||
@@ -270,6 +279,10 @@ func (l *Cluster) getLeaderLock() error {
|
|||||||
l.logger.Infof(l.ctx, "getLeaderLock Instance %s became leader", lock.GetValue())
|
l.logger.Infof(l.ctx, "getLeaderLock Instance %s became leader", lock.GetValue())
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
if !l.usePriority || l.priority == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
@@ -279,6 +292,7 @@ func (l *Cluster) getLeaderLock() error {
|
|||||||
default:
|
default:
|
||||||
if !l.priority.IsLatest(l.ctx) {
|
if !l.priority.IsLatest(l.ctx) {
|
||||||
cancel()
|
cancel()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-8
@@ -19,7 +19,7 @@ func TestCluster_AddEveryMonth(t *testing.T) {
|
|||||||
})
|
})
|
||||||
defer redis.Close()
|
defer redis.Close()
|
||||||
|
|
||||||
cluster := timerx.InitCluster(ctx, redis, "test")
|
cluster, _ := timerx.InitCluster(ctx, redis, "test")
|
||||||
|
|
||||||
taskId := "testTask"
|
taskId := "testTask"
|
||||||
hour := 2
|
hour := 2
|
||||||
@@ -49,7 +49,7 @@ func TestCluster_AddEveryWeek(t *testing.T) {
|
|||||||
})
|
})
|
||||||
defer redis.Close()
|
defer redis.Close()
|
||||||
|
|
||||||
cluster := timerx.InitCluster(ctx, redis, "test")
|
cluster,_ := timerx.InitCluster(ctx, redis, "test")
|
||||||
|
|
||||||
taskId := "testTask"
|
taskId := "testTask"
|
||||||
week := time.Sunday
|
week := time.Sunday
|
||||||
@@ -78,7 +78,7 @@ func TestCluster_AddEveryDay(t *testing.T) {
|
|||||||
})
|
})
|
||||||
defer redis.Close()
|
defer redis.Close()
|
||||||
|
|
||||||
cluster := timerx.InitCluster(ctx, redis, "test")
|
cluster,_ := timerx.InitCluster(ctx, redis, "test")
|
||||||
|
|
||||||
taskId := "testTask"
|
taskId := "testTask"
|
||||||
hour := 2
|
hour := 2
|
||||||
@@ -106,7 +106,7 @@ func TestCluster_AddEveryHour(t *testing.T) {
|
|||||||
})
|
})
|
||||||
defer redis.Close()
|
defer redis.Close()
|
||||||
|
|
||||||
cluster := timerx.InitCluster(ctx, redis, "test")
|
cluster,_ := timerx.InitCluster(ctx, redis, "test")
|
||||||
|
|
||||||
taskId := "testTask"
|
taskId := "testTask"
|
||||||
minute := 3
|
minute := 3
|
||||||
@@ -133,7 +133,7 @@ func TestCluster_AddEveryMinute(t *testing.T) {
|
|||||||
})
|
})
|
||||||
defer redis.Close()
|
defer redis.Close()
|
||||||
|
|
||||||
cluster := timerx.InitCluster(ctx, redis, "test")
|
cluster,_ := timerx.InitCluster(ctx, redis, "test")
|
||||||
|
|
||||||
taskId := "testTask"
|
taskId := "testTask"
|
||||||
second := 4
|
second := 4
|
||||||
@@ -165,7 +165,7 @@ func TestCluster_Add(t *testing.T) {
|
|||||||
|
|
||||||
t.Log("6666")
|
t.Log("6666")
|
||||||
|
|
||||||
cluster := timerx.InitCluster(ctx, redis, "test")
|
cluster,_ := timerx.InitCluster(ctx, redis, "test")
|
||||||
|
|
||||||
taskId := "testTask"
|
taskId := "testTask"
|
||||||
dur := time.Second
|
dur := time.Second
|
||||||
@@ -181,10 +181,8 @@ func TestCluster_Add(t *testing.T) {
|
|||||||
t.Errorf("Add failed,1 err: %v", err)
|
t.Errorf("Add failed,1 err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
time.Sleep(time.Second * 20)
|
time.Sleep(time.Second * 20)
|
||||||
|
|
||||||
|
|
||||||
// TODO: verify the job is added to the cluster and can be executed after the specified duration
|
// TODO: verify the job is added to the cluster and can be executed after the specified duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ type Options struct {
|
|||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
usePriority bool
|
usePriority bool
|
||||||
priorityVal int64
|
priorityVal int64
|
||||||
|
batchSize int
|
||||||
|
maxRetryCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultOptions() Options {
|
func defaultOptions() Options {
|
||||||
@@ -21,6 +23,8 @@ func defaultOptions() Options {
|
|||||||
timeout: time.Hour,
|
timeout: time.Hour,
|
||||||
usePriority: false,
|
usePriority: false,
|
||||||
priorityVal: 0,
|
priorityVal: 0,
|
||||||
|
batchSize: 100,
|
||||||
|
maxRetryCount: 100,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,30 +39,48 @@ func newOptions(opts ...Option) Options {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 设置日志
|
// 设置日志
|
||||||
func SetLogger(log logger.Logger) Option {
|
func WithLogger(log logger.Logger) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
o.logger = log
|
o.logger = log
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设定时区
|
// 设定时区
|
||||||
func SetTimeZone(zone *time.Location) Option {
|
func WithLocation(zone *time.Location) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
o.location = zone
|
o.location = zone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置任务最长执行时间
|
// 设置任务最长执行时间
|
||||||
func SetTimeout(d time.Duration) Option {
|
func WithTimeout(d time.Duration) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
o.timeout = d
|
o.timeout = d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置优先级
|
// 设置优先级
|
||||||
func SetPriority(priority int64) Option {
|
func WithPriority(priority int64) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
o.usePriority = true
|
o.usePriority = true
|
||||||
o.priorityVal = priority
|
o.priorityVal = priority
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithBatchSize(size int) Option {
|
||||||
|
return func(o *Options) {
|
||||||
|
if size <= 1 {
|
||||||
|
size = 1
|
||||||
|
}
|
||||||
|
o.batchSize = size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithMaxRetryCount(count int) Option {
|
||||||
|
return func(o *Options) {
|
||||||
|
if count <= 0 {
|
||||||
|
count = 1
|
||||||
|
}
|
||||||
|
o.maxRetryCount = count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+2
-2
@@ -32,14 +32,14 @@ func newOptions(opts ...Option) Options {
|
|||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetLogger(log logger.Logger) Option {
|
func WithLogger(log logger.Logger) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
o.logger = log
|
o.logger = log
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新周期
|
// 更新周期
|
||||||
func SetUpdateInterval(d time.Duration) Option {
|
func WithUpdateInterval(d time.Duration) Option {
|
||||||
if d.Abs() < time.Second {
|
if d.Abs() < time.Second {
|
||||||
d = time.Second * 5
|
d = time.Second * 5
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package priority
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -31,7 +32,12 @@ type Priority struct {
|
|||||||
latestMux sync.RWMutex
|
latestMux sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitPriority(ctx context.Context, re redis.UniversalClient, keyPrefix string, priority int64, opts ...Option) *Priority {
|
func InitPriority(ctx context.Context, re redis.UniversalClient, keyPrefix string, priority int64, opts ...Option) (*Priority, error) {
|
||||||
|
|
||||||
|
if re != nil {
|
||||||
|
return nil, errors.New("redis is nil")
|
||||||
|
}
|
||||||
|
|
||||||
conf := newOptions(opts...)
|
conf := newOptions(opts...)
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
@@ -50,7 +56,7 @@ func InitPriority(ctx context.Context, re redis.UniversalClient, keyPrefix strin
|
|||||||
|
|
||||||
pro.startDaemon()
|
pro.startDaemon()
|
||||||
|
|
||||||
return pro
|
return pro, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Priority) Close() {
|
func (p *Priority) Close() {
|
||||||
@@ -118,8 +124,6 @@ func (l *Priority) getLatestLoop() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (p *Priority) IsLatest(ctx context.Context) bool {
|
func (p *Priority) IsLatest(ctx context.Context) bool {
|
||||||
p.latestMux.RLock()
|
p.latestMux.RLock()
|
||||||
defer p.latestMux.RUnlock()
|
defer p.latestMux.RUnlock()
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func TestPriority(t *testing.T) {
|
|||||||
|
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
|
||||||
pro := InitPriority(ctx, re, "test", 10, SetUpdateInterval(time.Second*1))
|
pro, _ := InitPriority(ctx, re, "test", 10, WithUpdateInterval(time.Second*1))
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
bb := pro.IsLatest(ctx)
|
bb := pro.IsLatest(ctx)
|
||||||
@@ -50,7 +50,7 @@ func TestPriority(t *testing.T) {
|
|||||||
cancel()
|
cancel()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
pro := InitPriority(ctx, re, "test", 0, SetUpdateInterval(time.Second*1))
|
pro, _ := InitPriority(ctx, re, "test", 0, WithUpdateInterval(time.Second*1))
|
||||||
|
|
||||||
for i := 0; i < 25; i++ {
|
for i := 0; i < 25; i++ {
|
||||||
bb := pro.IsLatest(ctx)
|
bb := pro.IsLatest(ctx)
|
||||||
@@ -85,7 +85,7 @@ func TestInitPriority(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// 测试正常初始化
|
// 测试正常初始化
|
||||||
priority := InitPriority(ctx, getRedis(), "test", 100)
|
priority, _ := InitPriority(ctx, getRedis(), "test", 100)
|
||||||
assert.NotNil(t, priority)
|
assert.NotNil(t, priority)
|
||||||
assert.Equal(t, int64(100), priority.priority)
|
assert.Equal(t, int64(100), priority.priority)
|
||||||
}
|
}
|
||||||
@@ -137,7 +137,7 @@ func TestSetPriorityScenarios(t *testing.T) {
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
|
||||||
priority := InitPriority(ctx, redisConn, "test22", tc.newPriority)
|
priority, _ := InitPriority(ctx, redisConn, "test22", tc.newPriority)
|
||||||
defer priority.Close()
|
defer priority.Close()
|
||||||
|
|
||||||
time.Sleep(time.Second * 1)
|
time.Sleep(time.Second * 1)
|
||||||
@@ -154,7 +154,7 @@ func TestSetPriorityScenarios(t *testing.T) {
|
|||||||
func TestConcurrentAccess(t *testing.T) {
|
func TestConcurrentAccess(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
priority := InitPriority(ctx, getRedis(), "testacc", 100)
|
priority, _ := InitPriority(ctx, getRedis(), "testacc", 100)
|
||||||
|
|
||||||
time.Sleep(time.Second * 1)
|
time.Sleep(time.Second * 1)
|
||||||
|
|
||||||
@@ -186,7 +186,7 @@ func TestErrorScenarios(t *testing.T) {
|
|||||||
t.Run("Redis连接失败", func(t *testing.T) {
|
t.Run("Redis连接失败", func(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
priority := InitPriority(ctx, getRedis(), "test", 100)
|
priority, _ := InitPriority(ctx, getRedis(), "test", 100)
|
||||||
_, err := priority.setPriority()
|
_, err := priority.setPriority()
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|||||||
+9
-9
@@ -52,8 +52,8 @@ func TestSingleTimer_Basic(t *testing.T) {
|
|||||||
mockLogger := &MockLogger{}
|
mockLogger := &MockLogger{}
|
||||||
|
|
||||||
timer := timerx.InitSingle(ctx,
|
timer := timerx.InitSingle(ctx,
|
||||||
timerx.SetLogger(mockLogger),
|
timerx.WithLogger(mockLogger),
|
||||||
timerx.SetTimeZone(time.UTC))
|
timerx.WithLocation(time.UTC))
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
||||||
// 测试任务计数
|
// 测试任务计数
|
||||||
@@ -108,7 +108,7 @@ func TestSingleTimer_Deduplication(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
mockLogger := &MockLogger{}
|
mockLogger := &MockLogger{}
|
||||||
|
|
||||||
timer := timerx.InitSingle(ctx, timerx.SetLogger(mockLogger))
|
timer := timerx.InitSingle(ctx, timerx.WithLogger(mockLogger))
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
||||||
var executionCount int32
|
var executionCount int32
|
||||||
@@ -190,7 +190,7 @@ func TestSingleTimer_Timeout(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
mockLogger := &MockLogger{}
|
mockLogger := &MockLogger{}
|
||||||
|
|
||||||
timer := timerx.InitSingle(ctx, timerx.SetLogger(mockLogger))
|
timer := timerx.InitSingle(ctx, timerx.WithLogger(mockLogger))
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
||||||
// 长时间运行的任务
|
// 长时间运行的任务
|
||||||
@@ -217,7 +217,7 @@ func TestSingleTimer_PanicRecovery(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
mockLogger := &MockLogger{}
|
mockLogger := &MockLogger{}
|
||||||
|
|
||||||
timer := timerx.InitSingle(ctx, timerx.SetLogger(mockLogger))
|
timer := timerx.InitSingle(ctx, timerx.WithLogger(mockLogger))
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
||||||
panicTask := func(ctx context.Context, data interface{}) error {
|
panicTask := func(ctx context.Context, data interface{}) error {
|
||||||
@@ -236,7 +236,7 @@ func TestSingleTimer_PanicRecovery(t *testing.T) {
|
|||||||
// 测试不同时间类型的任务
|
// 测试不同时间类型的任务
|
||||||
func TestSingleTimer_DifferentJobTypes(t *testing.T) {
|
func TestSingleTimer_DifferentJobTypes(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
timer := timerx.InitSingle(ctx, timerx.SetTimeZone(time.UTC))
|
timer := timerx.InitSingle(ctx, timerx.WithLocation(time.UTC))
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
||||||
var counts struct {
|
var counts struct {
|
||||||
@@ -287,7 +287,7 @@ func TestSingleTimer_ContextCancellation(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
mockLogger := &MockLogger{}
|
mockLogger := &MockLogger{}
|
||||||
|
|
||||||
timer := timerx.InitSingle(ctx, timerx.SetLogger(mockLogger))
|
timer := timerx.InitSingle(ctx, timerx.WithLogger(mockLogger))
|
||||||
|
|
||||||
var executionCount int32
|
var executionCount int32
|
||||||
_, err := timer.AddSpace(ctx, "cancel-test", 100*time.Millisecond,
|
_, err := timer.AddSpace(ctx, "cancel-test", 100*time.Millisecond,
|
||||||
@@ -419,7 +419,7 @@ func TestSingleTimer_Logging(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
mockLogger := &MockLogger{}
|
mockLogger := &MockLogger{}
|
||||||
|
|
||||||
timer := timerx.InitSingle(ctx, timerx.SetLogger(mockLogger))
|
timer := timerx.InitSingle(ctx, timerx.WithLogger(mockLogger))
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
||||||
// 添加会panic的任务
|
// 添加会panic的任务
|
||||||
@@ -448,7 +448,7 @@ func TestSingleTimer_Timezone(t *testing.T) {
|
|||||||
for _, loc := range locations {
|
for _, loc := range locations {
|
||||||
t.Run(loc.String(), func(t *testing.T) {
|
t.Run(loc.String(), func(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
timer := timerx.InitSingle(ctx, timerx.SetTimeZone(loc))
|
timer := timerx.InitSingle(ctx, timerx.WithLocation(loc))
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
||||||
var executed bool
|
var executed bool
|
||||||
|
|||||||
Reference in New Issue
Block a user