Skip to content

Commit

Permalink
feat: closer added
Browse files Browse the repository at this point in the history
  • Loading branch information
pshapovalov committed Mar 7, 2024
1 parent 2ad7bd7 commit a3c015d
Showing 1 changed file with 86 additions and 0 deletions.
86 changes: 86 additions & 0 deletions pkg/closer/closer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package app

import (
"log"
"os"
"os/signal"
"sync"
)

var globalCloser = New()

// Add adds `func() error` callback to the globalCloser
func Add(f ...func() error) {
globalCloser.Add(f...)
}

// Wait ...
func Wait() {
globalCloser.Wait()
}

// CloseAll ...
func CloseAll() {
globalCloser.CloseAll()
}

// Closer ...
type Closer struct {
mu sync.Mutex
once sync.Once
done chan struct{}
funcs []func() error
}

// New returns new Closer, if []os.Signal is specified Closer will automatically call CloseAll when one of signals is received from OS
func New(sig ...os.Signal) *Closer {
c := &Closer{done: make(chan struct{})}
if len(sig) > 0 {
go func() {
ch := make(chan os.Signal, 1)
signal.Notify(ch, sig...)
<-ch
signal.Stop(ch)
c.CloseAll()
}()
}
return c
}

// Add func to closer
func (c *Closer) Add(f ...func() error) {
c.mu.Lock()
c.funcs = append(c.funcs, f...)
c.mu.Unlock()
}

// Wait blocks until all closer functions are done
func (c *Closer) Wait() {
<-c.done
}

// CloseAll calls all closer functions
func (c *Closer) CloseAll() {
c.once.Do(func() {
defer close(c.done)

c.mu.Lock()
funcs := c.funcs
c.funcs = nil
c.mu.Unlock()

// call all Closer funcs async
errs := make(chan error, len(funcs))
for _, f := range funcs {
go func(f func() error) {
errs <- f()
}(f)
}

for i := 0; i < cap(errs); i++ {
if err := <-errs; err != nil {
log.Println("error returned from Closer")
}
}
})
}

0 comments on commit a3c015d

Please sign in to comment.