diff --git a/timer.go b/timer.go index fd016b1..ee4d77a 100644 --- a/timer.go +++ b/timer.go @@ -196,6 +196,13 @@ func (t *StarTimer) SetBaseDate(date time.Time) { t.base = date } +func (t *StarTimer) StaticMode() bool { + return t.staticMode +} +func (t *StarTimer) SetStaticMode(s bool) { + t.staticMode = s +} + func (t *StarTimer) ResetWithRepeat(base time.Time, repeat []*Repeats) error { t.Stop() t.base = base @@ -212,7 +219,59 @@ func (t *StarTimer) Repeats() []*Repeats { return t.repeat } +func (t *StarTimer) runAsStaticMode() error { + t.mu.Lock() + defer t.mu.Unlock() + if t.running { + return nil + } + for _, v := range t.repeat { + if err := t.repeatsCheck(v); err != nil { + return err + } + } + t.base = time.Now() + base := t.base + t.nextDate = t.parseNextDate(base, false) + if t.nextDate.Before(time.Now()) { + return errors.New("Invalid Timer Options,Please Check") + } + t.running = true + t.stopCtx, t.stopFn = context.WithCancel(context.Background()) + go func() { + for { + if t.runLimit > 0 && t.runCount >= t.runLimit { + t.Stop() + } + now := time.Now() + t.nextDate = t.parseNextDate(now, false) + if t.nextDate.Before(now) || t.runLimit > 0 && t.runCount+1 >= t.runLimit { + t.Stop() + } + t.mu.Lock() + t.timer = time.NewTimer(t.nextDate.Sub(now)) + t.mu.Unlock() + select { + case <-t.timer.C: + t.runCount++ + for _, fn := range t.tasks { + go fn() + } + if !t.running { + return + } + case <-t.stopCtx.Done(): + return + } + } + }() + return nil +} + func (t *StarTimer) Run() error { + if t.staticMode { + return t.runAsStaticMode() + } t.mu.Lock() defer t.mu.Unlock() if t.running { diff --git a/typed.go b/typed.go index bfc2544..2804d2c 100644 --- a/typed.go +++ b/typed.go @@ -41,6 +41,8 @@ type StarTimer struct { runLimit int repeat []*Repeats tasks []func() + //staticMode 意味永久以当前时间为基准进行动作,例如crontab + staticMode bool } type TimerOptions func(option *TimerOption)