commit 4c8a16617873bcf637d14674f0c0f985303f4d1f Author: Shelikhoo xiaokangwang@outlook.com Date: Thu Nov 4 20:21:59 2021 +0000
Port V2Ray periodic task standard library to snowflake
This is a mature implementation of periodic task that run a function at given interval. It allows task to be stopped, and deals with edge case like interval too short gracefully.
V2Ray/V2Fly is MIT licensed. --- common/task/periodic.go | 85 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+)
diff --git a/common/task/periodic.go b/common/task/periodic.go new file mode 100644 index 0000000..6abe41a --- /dev/null +++ b/common/task/periodic.go @@ -0,0 +1,85 @@ +package task + +import ( + "sync" + "time" +) + +// Periodic is a task that runs periodically. +type Periodic struct { + // Interval of the task being run + Interval time.Duration + // Execute is the task function + Execute func() error + + access sync.Mutex + timer *time.Timer + running bool +} + +func (t *Periodic) hasClosed() bool { + t.access.Lock() + defer t.access.Unlock() + + return !t.running +} + +func (t *Periodic) checkedExecute() error { + if t.hasClosed() { + return nil + } + + if err := t.Execute(); err != nil { + t.access.Lock() + t.running = false + t.access.Unlock() + return err + } + + t.access.Lock() + defer t.access.Unlock() + + if !t.running { + return nil + } + + t.timer = time.AfterFunc(t.Interval, func() { + t.checkedExecute() + }) + + return nil +} + +// Start implements common.Runnable. +func (t *Periodic) Start() error { + t.access.Lock() + if t.running { + t.access.Unlock() + return nil + } + t.running = true + t.access.Unlock() + + if err := t.checkedExecute(); err != nil { + t.access.Lock() + t.running = false + t.access.Unlock() + return err + } + + return nil +} + +// Close implements common.Closable. +func (t *Periodic) Close() error { + t.access.Lock() + defer t.access.Unlock() + + t.running = false + if t.timer != nil { + t.timer.Stop() + t.timer = nil + } + + return nil +}
tor-commits@lists.torproject.org