shanshanzhong c582087c0f
Some checks failed
Build docker and publish / build (20.15.1) (push) Failing after 6m27s
refactor: 更新项目引用路径从perfect-panel/ppanel-server到perfect-panel/server
feat: 添加版本和构建时间变量
fix: 修正短信队列类型注释错误
style: 清理未使用的代码和测试文件
docs: 更新安装文档中的下载链接
chore: 迁移数据库脚本添加日志和订阅配置
2025-10-13 01:33:03 -07:00

124 lines
2.1 KiB
Go

package service
import (
"sync"
"github.com/perfect-panel/server/pkg/proc"
"github.com/perfect-panel/server/pkg/threading"
)
type (
// Starter is the interface wraps the Start method.
Starter interface {
Start()
}
// Stopper is the interface wraps the Stop method.
Stopper interface {
Stop()
}
// Service is the interface that groups Start and Stop methods.
Service interface {
Starter
Stopper
}
// Group A ServiceGroup is a group of services.
// Attention: the starting order of the added services is not guaranteed.
Group struct {
services []Service
stopOnce func()
}
)
// NewServiceGroup returns a ServiceGroup.
func NewServiceGroup() *Group {
sg := new(Group)
sg.stopOnce = Once(sg.doStop)
return sg
}
// Add adds service into sg.
func (sg *Group) Add(service Service) {
// push front, stop with reverse order.
sg.services = append([]Service{service}, sg.services...)
}
// Start starts the ServiceGroup.
// There should not be any logic code after calling this method, because this method is a blocking one.
// Also, quitting this method will close the logx output.
func (sg *Group) Start() {
proc.AddShutdownListener(func() {
sg.stopOnce()
})
sg.doStart()
}
// Stop stops the ServiceGroup.
func (sg *Group) Stop() {
sg.stopOnce()
}
func (sg *Group) doStart() {
routineGroup := threading.NewRoutineGroup()
for i := range sg.services {
service := sg.services[i]
routineGroup.Run(func() {
service.Start()
})
}
routineGroup.Wait()
}
func (sg *Group) doStop() {
for _, service := range sg.services {
service.Stop()
}
}
// WithStart wraps a start func as a Service.
func WithStart(start func()) Service {
return startOnlyService{
start: start,
}
}
// WithStarter wraps a Starter as a Service.
func WithStarter(start Starter) Service {
return starterOnlyService{
Starter: start,
}
}
type (
stopper struct{}
startOnlyService struct {
start func()
stopper
}
starterOnlyService struct {
Starter
stopper
}
)
func (s stopper) Stop() {
}
func (s startOnlyService) Start() {
s.start()
}
func Once(fn func()) func() {
once := new(sync.Once)
return func() {
once.Do(fn)
}
}