diff --git a/crontab.go b/crontab.go index c8c04c0..1fe63c6 100644 --- a/crontab.go +++ b/crontab.go @@ -23,9 +23,6 @@ type hInterval struct { PlanFail []randLR PlanTrue []randLR - TrueCount int - FailCount int - Count int ConstCount int } @@ -61,7 +58,10 @@ type Crontab struct { interval *clinked.CircularLinked lastStatus bool isCalculated bool - nextTime time.Time + + trueCount int + failCount int + nextTime time.Time } // NewCrontab create 一个crontab @@ -222,34 +222,19 @@ func (cron *Crontab) linuxTimeUp() bool { // IntervalCalculateNextTime 计算时间间隔的下次时间 func (cron *Crontab) intervalCalculateNextTime(now time.Time) { - iv := cron.interval.Cursor().GetValue().(hInterval) + iv := cron.interval.Cursor().GetValue().(*hInterval) isecond := 0 - if cron.lastStatus { - iv.TrueCount++ - iv.FailCount = 0 - } else { - iv.FailCount++ - iv.TrueCount = 0 + if iv.PlanFailCount.Size() == 0 && len(iv.PlanFail) == 0 { + cron.lastStatus = true } - if cron.lastStatus == false { + if cron.lastStatus { - isecond = intervalPriorityListISecond(&iv.PlanFailCount, iv.FailCount) - if isecond == -1 { - if len(iv.PlanFail) > 0 { - idx := randomdata.Number(len(iv.PlanFail)) - lr := iv.PlanFail[idx] - isecond = randomdata.Number(lr.left, lr.right+1) - } else { - isecond = 0 - } - } + cron.trueCount++ + cron.failCount = 0 - log.Println("fail:", iv.FailCount, "count time wait:", isecond, "s") - } else { - - isecond = intervalPriorityListISecond(&iv.PlanTrueCount, iv.TrueCount) + isecond = intervalPriorityListISecond(&iv.PlanTrueCount, cron.trueCount) if isecond == -1 { if len(iv.PlanTrue) > 0 { idx := randomdata.Number(len(iv.PlanTrue)) @@ -261,8 +246,26 @@ func (cron *Crontab) intervalCalculateNextTime(now time.Time) { } } else { - log.Println("success:", iv.TrueCount, "count time wait:", isecond, "s") + log.Println("success:", cron.trueCount, "count time wait:", isecond, "s") } + + } else { + + cron.failCount++ + cron.trueCount = 0 + + isecond = intervalPriorityListISecond(&iv.PlanFailCount, cron.failCount) + if isecond == -1 { + if len(iv.PlanFail) > 0 { + idx := randomdata.Number(len(iv.PlanFail)) + lr := iv.PlanFail[idx] + isecond = randomdata.Number(lr.left, lr.right+1) + } else { + isecond = 0 + } + } + + log.Println("fail:", cron.failCount, "count time wait:", isecond, "s") } iv.Count-- @@ -381,7 +384,8 @@ func parseIntervalString(crontab string) []interface{} { values := strings.Split(crontab, ",") for _, value := range values { - interval := hInterval{} + interval := &hInterval{} + // 次数 valuesCounts := strings.Split(value, "x") switch len(valuesCounts) { diff --git a/crontab_test.go b/crontab_test.go index 4b87401..190d1d7 100644 --- a/crontab_test.go +++ b/crontab_test.go @@ -59,6 +59,13 @@ func TestParseInterval(t *testing.T) { } } +func isInRangeTime(sec, t float64) error { + if sec >= t-0.05 && sec <= t+0.05 { + return nil + } + return fmt.Errorf("计算错误 范围 %f-%f interval time is %f", t-0.05, t+0.05, sec) +} + func TestParseIntervalPlus(t *testing.T) { // crontab := "0-5/2,7-30/3,30,35,40-^1 * * * *" //(秒) 分 时 号(每月的多少号, 要注意月可可能性) 星期几(每个星期的) /每 ,列表 -范围 // crondata := NewCrontab("*22 * * * *") @@ -66,51 +73,62 @@ func TestParseIntervalPlus(t *testing.T) { //crontab := "0-5/2,7-30/3,30,35,40-^1 * * * *" //(秒) 分 时 号(每月的多少号, 要注意月可可能性) 星期几(每个星期的) /每 ,列表 -范围 //crontab := "f1-2|1-3|5-8x5,f1|10m,10-15,f1" ^代表往后算 ^5 2月份就代表 28-4=24 f代表失败后1-2秒设置 由SetStatus控制 t 相反默认不写前缀为t - crontab := "f2|f2?3|f3?4|1" + log.SetFlags(log.Llongfile) + + crontab := "f2|f2?3|f3?4|1|t4?5" cron := NewCrontab(crontab) + + i := 0 now := time.Now() - t.Error("") - for i := 0; i <= 5*15; i++ { - cron.NextTime() + lasttime := now + + for j := 0; j <= 2500; j++ { + + nexttime := cron.NextTime() + if j >= 5 && !nexttime.Equal(lasttime) { + lasttime = nexttime + } + if cron.TimeUp() { sec := time.Since(now).Seconds() - cron.SetStatus(false) - t.Error(i, sec) - if i == 0 { - if 1.0 <= sec && sec <= 1.1 { - t.Log(sec) - } else { - t.Error(i, "interval time is ", sec) + + switch i { + case 0: + + case 1: + if err := isInRangeTime(sec, 2.0); err != nil { + t.Error(err.Error(), "status = ", cron.GetStatus()) + } + case 2: + if err := isInRangeTime(sec, 3.0); err != nil { + t.Error(err.Error(), "status = ", cron.GetStatus()) + } + case 3: + if err := isInRangeTime(sec, 4.0); err != nil { + t.Error(err.Error(), "status = ", cron.GetStatus()) + } + case 5: + if err := isInRangeTime(sec, 1); err != nil { + t.Error(err.Error(), "status = ", cron.GetStatus()) + } + default: + if i >= 10 { + if err := isInRangeTime(sec, 5.0); err != nil { + t.Error(err.Error(), "status = ", cron.GetStatus()) + } } } - - if i == 1 { - if 2.0 <= sec && sec <= 2.1 { - t.Log(sec) - } else { - t.Error(i, "interval time is ", sec) - } - } - - if i == 2 { - if 3.0 <= sec && sec <= 3.1 { - t.Log(sec) - } else { - t.Error(i, "interval time is ", sec) - } - } - - if i == 3 { - if 4.0 <= sec && sec <= 4.1 { - t.Log(sec) - } else { - t.Error(i, "interval time is ", sec) - } + if i <= 3 { + cron.SetStatus(false) + } else { + cron.SetStatus(true) } now = time.Now() + i++ } - time.Sleep(time.Millisecond * 200) + + time.Sleep(time.Millisecond * 10) } }