Add idle package

This commit is contained in:
Balakrishnan Balasubramanian 2023-05-08 22:37:03 -04:00
parent bbef4be4a7
commit 710e8b66e6
2 changed files with 79 additions and 0 deletions

68
idle/idle.go Normal file
View File

@ -0,0 +1,68 @@
// Package idle helps to gracefully shutdown idle servers
package idle
import (
"sync/atomic"
"time"
)
type Idler interface {
Enter()
Exit()
Wait()
Tick()
Chan() <-chan struct{}
}
type idler struct {
lastTick atomic.Pointer[time.Time]
c chan struct{}
active atomic.Int64
}
func (i *idler) Enter() {
i.active.Add(1)
}
func (i *idler) Exit() {
i.Tick()
i.active.Add(-1)
}
func CreateIdler(timeout time.Duration) Idler {
i := &idler{}
i.c = make(chan struct{})
i.Tick()
go func() {
for {
if i.active.Load() != 0 {
time.Sleep(timeout)
} else {
t := *i.lastTick.Load()
now := time.Now()
dur := t.Add(timeout).Sub(now)
if dur == dur.Abs() {
time.Sleep(dur)
} else {
break
}
}
}
close(i.c)
}()
return i
}
func (i *idler) Tick() {
now := time.Now()
i.lastTick.Store(&now)
}
func (i *idler) Wait() {
<-i.c
}
func (i *idler) Chan() <-chan struct{} {
return i.c
}

11
idle/idle_test.go Normal file
View File

@ -0,0 +1,11 @@
package idle
import (
"testing"
"time"
)
func TestIdlerChan(t *testing.T) {
i := CreateIdler(1 * time.Second)
<-i.Chan()
}