Files
sing-box-extended-mirror/adapter/lifecycle.go
T

115 lines
2.2 KiB
Go
Raw Normal View History

2024-11-09 21:16:11 +08:00
package adapter
2025-12-20 18:47:50 +08:00
import (
"reflect"
"strings"
"time"
"github.com/sagernet/sing-box/log"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
)
2024-11-10 16:46:59 +08:00
2025-03-29 17:24:34 +08:00
type SimpleLifecycle interface {
Start() error
Close() error
}
2024-11-09 21:16:11 +08:00
type StartStage uint8
const (
StartStateInitialize StartStage = iota
StartStateStart
StartStatePostStart
StartStateStarted
)
var ListStartStages = []StartStage{
StartStateInitialize,
StartStateStart,
StartStatePostStart,
StartStateStarted,
}
2024-11-10 16:46:59 +08:00
func (s StartStage) String() string {
2024-11-09 21:16:11 +08:00
switch s {
case StartStateInitialize:
return "initialize"
case StartStateStart:
return "start"
case StartStatePostStart:
return "post-start"
case StartStateStarted:
2024-11-10 16:46:59 +08:00
return "finish-start"
2024-11-09 21:16:11 +08:00
default:
panic("unknown stage")
}
}
2024-11-10 16:46:59 +08:00
type Lifecycle interface {
Start(stage StartStage) error
2024-11-09 21:16:11 +08:00
Close() error
}
2024-11-10 16:46:59 +08:00
type LifecycleService interface {
Name() string
Lifecycle
}
2025-12-20 18:47:50 +08:00
func getServiceName(service any) string {
if named, ok := service.(interface {
Type() string
Tag() string
}); ok {
tag := named.Tag()
if tag != "" {
return named.Type() + "[" + tag + "]"
}
return named.Type()
}
t := reflect.TypeOf(service)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
return strings.ToLower(t.Name())
}
func Start(logger log.ContextLogger, stage StartStage, services ...Lifecycle) error {
2024-11-10 16:46:59 +08:00
for _, service := range services {
2025-12-20 18:47:50 +08:00
name := getServiceName(service)
2026-04-21 17:15:16 +08:00
done := LogElapsed(logger, stage, " ", name)
2024-11-10 16:46:59 +08:00
err := service.Start(stage)
2026-04-21 17:15:16 +08:00
done()
2024-11-10 16:46:59 +08:00
if err != nil {
return err
}
}
return nil
}
2025-12-20 18:47:50 +08:00
func StartNamed(logger log.ContextLogger, stage StartStage, services []LifecycleService) error {
2024-11-10 16:46:59 +08:00
for _, service := range services {
2026-04-21 17:15:16 +08:00
done := LogElapsed(logger, stage, " ", service.Name())
2024-11-10 16:46:59 +08:00
err := service.Start(stage)
2026-04-21 17:15:16 +08:00
done()
2024-11-10 16:46:59 +08:00
if err != nil {
return E.Cause(err, stage.String(), " ", service.Name())
}
}
return nil
2024-11-09 21:16:11 +08:00
}
2026-04-19 23:25:00 +08:00
2026-04-21 17:15:16 +08:00
func LogElapsed(logger log.ContextLogger, description ...any) func() {
prefix := F.ToString(description...)
startTime := time.Now()
timer := time.AfterFunc(time.Second, func() {
logger.Trace(prefix, "...")
})
return func() {
if timer.Stop() {
return
}
logger.Trace(prefix, " completed (", F.Seconds(time.Since(startTime).Seconds()), "s)")
2026-04-19 23:25:00 +08:00
}
}