40 lines
897 B
Go
40 lines
897 B
Go
package svc
|
|
|
|
import "errors"
|
|
|
|
// Close is idempotent, including startup failure and graceful shutdown.
|
|
func (c *ServiceContext) Close() error {
|
|
if c == nil {
|
|
return nil
|
|
}
|
|
c.closeOnce.Do(func() {
|
|
if c.Lifecycle != nil {
|
|
c.Lifecycle.RequestShutdown(nil)
|
|
}
|
|
c.closeMu.Lock()
|
|
c.closed = true
|
|
cleanups := c.cleanups
|
|
c.cleanups = nil
|
|
c.closeMu.Unlock()
|
|
for i := len(cleanups) - 1; i >= 0; i-- {
|
|
c.closeErr = errors.Join(c.closeErr, cleanups[i]())
|
|
}
|
|
|
|
})
|
|
return c.closeErr
|
|
}
|
|
|
|
// OnClose transfers a resource cleanup to this context immediately after creation.
|
|
// Hooks run once in reverse order, also when later initialization fails.
|
|
func (c *ServiceContext) OnClose(cleanup func() error) {
|
|
if cleanup == nil {
|
|
return
|
|
}
|
|
c.closeMu.Lock()
|
|
defer c.closeMu.Unlock()
|
|
if c.closed {
|
|
panic("svc: register cleanup after Close")
|
|
}
|
|
c.cleanups = append(c.cleanups, cleanup)
|
|
}
|