initial import

This commit is contained in:
kevin
2020-07-26 17:09:05 +08:00
commit 7e3a369a8f
647 changed files with 54754 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
package service
import (
"log"
"zero/core/load"
"zero/core/logx"
"zero/core/prometheus"
"zero/core/stat"
)
const (
DevMode = "dev"
TestMode = "test"
PreMode = "pre"
ProMode = "pro"
)
type ServiceConf struct {
Name string
Log logx.LogConf
Mode string `json:",default=pro,options=dev|test|pre|pro"`
MetricsUrl string `json:",optional"`
Prometheus prometheus.Config `json:",optional"`
}
func (sc ServiceConf) MustSetUp() {
if err := sc.SetUp(); err != nil {
log.Fatal(err)
}
}
func (sc ServiceConf) SetUp() error {
if len(sc.Log.ServiceName) == 0 {
sc.Log.ServiceName = sc.Name
}
if err := logx.SetUp(sc.Log); err != nil {
return err
}
sc.initMode()
prometheus.StartAgent(sc.Prometheus)
if len(sc.MetricsUrl) > 0 {
stat.SetReportWriter(stat.NewRemoteWriter(sc.MetricsUrl))
}
return nil
}
func (sc ServiceConf) initMode() {
switch sc.Mode {
case DevMode, TestMode, PreMode:
load.Disable()
stat.SetReporter(nil)
}
}

View File

@@ -0,0 +1,107 @@
package service
import (
"log"
"zero/core/proc"
"zero/core/syncx"
"zero/core/threading"
)
type (
Starter interface {
Start()
}
Stopper interface {
Stop()
}
Service interface {
Starter
Stopper
}
ServiceGroup struct {
services []Service
stopOnce func()
}
)
func NewServiceGroup() *ServiceGroup {
sg := new(ServiceGroup)
sg.stopOnce = syncx.Once(sg.doStop)
return sg
}
func (sg *ServiceGroup) Add(service Service) {
sg.services = append(sg.services, service)
}
// 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 *ServiceGroup) Start() {
proc.AddShutdownListener(func() {
log.Println("Shutting down...")
sg.stopOnce()
})
sg.doStart()
}
func (sg *ServiceGroup) Stop() {
sg.stopOnce()
}
func (sg *ServiceGroup) doStart() {
routineGroup := threading.NewRoutineGroup()
for i := range sg.services {
service := sg.services[i]
routineGroup.RunSafe(func() {
service.Start()
})
}
routineGroup.Wait()
}
func (sg *ServiceGroup) doStop() {
for _, service := range sg.services {
service.Stop()
}
}
func WithStart(start func()) Service {
return startOnlyService{
start: start,
}
}
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()
}

View File

@@ -0,0 +1,126 @@
package service
import (
"sync"
"testing"
"github.com/stretchr/testify/assert"
)
var (
number = 1
mutex sync.Mutex
done = make(chan struct{})
)
type mockedService struct {
quit chan struct{}
multiplier int
}
func newMockedService(multiplier int) *mockedService {
return &mockedService{
quit: make(chan struct{}),
multiplier: multiplier,
}
}
func (s *mockedService) Start() {
mutex.Lock()
number = number * s.multiplier
mutex.Unlock()
done <- struct{}{}
<-s.quit
}
func (s *mockedService) Stop() {
close(s.quit)
}
func TestServiceGroup(t *testing.T) {
multipliers := []int{2, 3, 5, 7}
want := 1
group := NewServiceGroup()
for _, multiplier := range multipliers {
want *= multiplier
service := newMockedService(multiplier)
group.Add(service)
}
go group.Start()
for i := 0; i < len(multipliers); i++ {
<-done
}
group.Stop()
mutex.Lock()
defer mutex.Unlock()
assert.Equal(t, want, number)
}
func TestServiceGroup_WithStart(t *testing.T) {
multipliers := []int{2, 3, 5, 7}
want := 1
var wait sync.WaitGroup
var lock sync.Mutex
wait.Add(len(multipliers))
group := NewServiceGroup()
for _, multiplier := range multipliers {
var mul = multiplier
group.Add(WithStart(func() {
lock.Lock()
want *= mul
lock.Unlock()
wait.Done()
}))
}
go group.Start()
wait.Wait()
group.Stop()
lock.Lock()
defer lock.Unlock()
assert.Equal(t, 210, want)
}
func TestServiceGroup_WithStarter(t *testing.T) {
multipliers := []int{2, 3, 5, 7}
want := 1
var wait sync.WaitGroup
var lock sync.Mutex
wait.Add(len(multipliers))
group := NewServiceGroup()
for _, multiplier := range multipliers {
var mul = multiplier
group.Add(WithStarter(mockedStarter{
fn: func() {
lock.Lock()
want *= mul
lock.Unlock()
wait.Done()
},
}))
}
go group.Start()
wait.Wait()
group.Stop()
lock.Lock()
defer lock.Unlock()
assert.Equal(t, 210, want)
}
type mockedStarter struct {
fn func()
}
func (s mockedStarter) Start() {
s.fn()
}