Skip to content

Commit 003847c

Browse files
author
PotatoCloud
committed
fixed destroy order bug
1 parent e0784c6 commit 003847c

File tree

5 files changed

+59
-160
lines changed

5 files changed

+59
-160
lines changed

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
# Package controller
2-
- a simple golang task controller
2+
- a modular project management (startup) framework
33

44
```
5-
go get github.com/RealFax/pkg-ctl
5+
go get github.com/RealFax/pkg-ctl@latest
66
```
77
## how to use
8-
9-
_using pkg-ctl is very simple_
108

119
- First add pkg-ctl to your `go.mod`
1210
- Then refer to the example code to register your package in `pkg-ctl`

ctl.go

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ type Handler interface {
1212
Async() bool
1313
}
1414

15+
type HandlerFunc func(*context.Context) Handler
16+
1517
type Unit struct {
1618
Seq int
1719
Name string
18-
Handle func(ctx *context.Context) Handler
20+
Handle HandlerFunc
1921
}
2022

2123
type DestroyUnit struct {
@@ -24,16 +26,7 @@ type DestroyUnit struct {
2426
Unit Handler
2527
}
2628

27-
// Deprecated
28-
func registerDestroy(seq int, name string, unit Handler) {
29-
destroyUnits = append(destroyUnits, DestroyUnit{
30-
Seq: seq,
31-
Name: name,
32-
Unit: unit,
33-
})
34-
}
35-
36-
func RegisterHandler(seq int, name string, handler func(ctx *context.Context) Handler) {
29+
func RegisterHandler(seq int, name string, handler HandlerFunc) {
3730
units = append(units, Unit{
3831
Seq: seq,
3932
Name: name,

logger.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package pkgCtl
2+
3+
import (
4+
"log"
5+
"os"
6+
)
7+
8+
type Logger interface {
9+
Debug(v ...any)
10+
Info(v ...any)
11+
Error(v ...any)
12+
}
13+
14+
type defaultLogger struct{ *log.Logger }
15+
16+
func (l defaultLogger) Debug(v ...any) {
17+
l.Println("[DEBUG]", v)
18+
}
19+
20+
func (l defaultLogger) Info(v ...any) {
21+
l.Println("[INFO]", v)
22+
}
23+
24+
func (l defaultLogger) Error(v ...any) {
25+
log.Println()
26+
l.Println("[ERROR]", v)
27+
}
28+
29+
var DefaultLogger = defaultLogger{
30+
log.New(os.Stderr, "", log.LstdFlags),
31+
}

store.go

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,5 @@
11
package pkgCtl
22

3-
import (
4-
"context"
5-
"log"
6-
)
7-
83
var (
9-
// Deprecated
10-
closeListener = make(chan struct{}, 1)
11-
// Deprecated
12-
cancelFunc context.CancelFunc
13-
units = make([]Unit, 0)
14-
destroyUnits = make([]DestroyUnit, 0)
4+
units = make([]Unit, 0)
155
)
16-
17-
var Log *log.Logger
18-
19-
func init() {
20-
Log = log.Default()
21-
}

tool.go

Lines changed: 21 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -3,135 +3,18 @@ package pkgCtl
33
import (
44
"context"
55
"errors"
6-
"log"
6+
"fmt"
77
"os"
88
"os/signal"
9+
"sort"
910
"syscall"
10-
"time"
1111
)
1212

13-
// ForceExit the ListenAndDestroy func
14-
//
15-
// Deprecated
16-
func ForceExit() error {
17-
if len(closeListener) != 0 {
18-
return errors.New("exiting")
19-
}
20-
closeListener <- struct{}{}
21-
return nil
22-
}
23-
24-
// Exit unregister all services immediately after calling
25-
//
26-
// this func can only be called when ListenAndDestroy is used, otherwise an error will be return
27-
//
28-
// Deprecated
29-
func Exit() error {
30-
if cancelFunc == nil {
31-
return errors.New("unset cancelFunc")
32-
}
33-
return Destroy(cancelFunc)
34-
}
35-
36-
// ExitWithTimeout
37-
//
38-
// Deprecated
39-
func ExitWithTimeout(d time.Duration) error {
40-
err := make(chan error, 1)
41-
ticker := time.NewTicker(d)
42-
go func() {
43-
select {
44-
case <-ticker.C:
45-
ticker.Stop()
46-
log.Println("exit timeout! calling ForceExit")
47-
err <- ForceExit()
48-
}
49-
}()
50-
go func() {
51-
err <- Exit()
52-
ticker.Stop()
53-
}()
54-
return <-err
55-
}
56-
57-
// Destroy unregister all services immediately after calling
58-
//
59-
// Deprecated
60-
func Destroy(cancel context.CancelFunc) (err error) {
61-
cancel()
62-
for i := 0; i < len(destroyUnits); i++ {
63-
if err = destroyUnits[i].Unit.Destroy(); err != nil {
64-
Log.Printf(
65-
"unit %s destroy fail, error: %s",
66-
destroyUnits[i].Name,
67-
err.Error(),
68-
)
69-
}
70-
}
71-
Log.Println("all unit are unmount")
72-
closeListener <- struct{}{}
73-
return
74-
}
75-
76-
// Startup all registered services in order
77-
//
78-
// Deprecated
79-
func Startup(rootCtx *context.Context) error {
80-
if len(units) == 0 {
81-
return errors.New("no unit require register")
82-
}
83-
var (
84-
errorChan = make(chan error, 1)
85-
err error
86-
)
87-
for _, unit := range units {
88-
if len(errorChan) == 1 {
89-
return <-errorChan
90-
}
91-
handler := unit.Handle(rootCtx)
92-
if err = handler.Create(); err != nil {
93-
Log.Printf("unit %s create fail, error: %s", unit.Name, err.Error())
94-
return err
95-
}
96-
registerDestroy(unit.Seq, unit.Name, handler)
97-
if handler.Async() {
98-
go func() {
99-
Log.Printf("[Ctl(Startup<ASYNC>)] unit %s startup", unit.Name)
100-
if hErr := handler.Start(); hErr != nil {
101-
Log.Printf("[Ctl(Startup<ASYNC>)] unit %s start fail, error: %s", unit.Name, hErr.Error())
102-
return
103-
}
104-
}()
105-
continue
106-
}
107-
if err = handler.Start(); err != nil {
108-
Log.Printf("unit %s start fail, error: %s", unit.Name, err.Error())
109-
return err
110-
}
111-
Log.Printf("unit %s startup", unit.Name)
112-
}
113-
return nil
114-
}
115-
116-
// ListenAndDestroy
117-
//
118-
// Deprecated
119-
func ListenAndDestroy(cancel context.CancelFunc) error {
120-
cancelFunc = cancel
121-
c := make(chan os.Signal, 1)
122-
signal.Notify(c, syscall.SIGTERM, syscall.SIGINT)
123-
select {
124-
case <-closeListener:
125-
return nil
126-
case <-c:
127-
return Destroy(cancel)
128-
}
129-
}
130-
13113
type Root struct {
13214
Context context.Context
13315
CancelFunc context.CancelFunc
13416

17+
logger Logger
13518
destroyUnits []DestroyUnit
13619
closeSignal chan struct{}
13720
}
@@ -140,6 +23,7 @@ func (r *Root) Stop() {
14023
if r.CancelFunc == nil {
14124
return
14225
}
26+
r.logger.Info("context cancel signal")
14327
r.CancelFunc()
14428
}
14529

@@ -153,15 +37,19 @@ func (r *Root) Exit() error {
15337
}
15438

15539
func (r *Root) Destroy() error {
40+
r.logger.Debug("starting destroy unit")
41+
sort.Slice(r.destroyUnits, func(i, j int) bool {
42+
return r.destroyUnits[i].Seq > r.destroyUnits[j].Seq
43+
})
15644
var err error
15745
for _, unit := range r.destroyUnits {
15846
if err = unit.Unit.Destroy(); err != nil {
159-
Log.Printf("unit %s destroy fail, error: %s", unit.Name, err.Error())
47+
r.logger.Error(fmt.Sprintf("unit %s destroy fail, error: %s", unit.Name, err.Error()))
16048
return err
16149
}
16250
}
16351
r.Stop()
164-
Log.Println("all unit are unmount")
52+
r.logger.Info("all unit are unmount")
16553
return nil
16654
}
16755

@@ -177,7 +65,7 @@ func (r *Root) Startup() error {
17765
for _, unit := range units {
17866
handle := unit.Handle(&r.Context)
17967
if err = handle.Create(); err != nil {
180-
Log.Printf("unit %s create fail, error: %s", unit.Name, err.Error())
68+
r.logger.Error(fmt.Sprintf("unit %s create fail, error: %s", unit.Name, err.Error()))
18169
return err
18270
}
18371

@@ -189,20 +77,24 @@ func (r *Root) Startup() error {
18977

19078
if handle.Async() {
19179
go func() {
192-
Log.Printf("[Ctl(Startup<ASYNC>)] unit %s startup", unit.Name)
80+
r.logger.Info(fmt.Sprintf("[Ctl(Startup<ASYNC>)] unit %s startup", unit.Name))
19381
if aErr := handle.Start(); aErr != nil {
194-
Log.Printf("[Ctl(Startup<ASYNC>)] unit %s start fail, error: %s", unit.Name, aErr.Error())
82+
r.logger.Error(fmt.Sprintf(
83+
"[Ctl(Startup<ASYNC>)] unit %s start fail, error: %s",
84+
unit.Name,
85+
aErr.Error(),
86+
))
19587
return
19688
}
19789
}()
19890
continue
19991
}
20092

20193
if err = handle.Start(); err != nil {
202-
Log.Printf("unit %s start fail, error: %s", unit.Name, err.Error())
94+
r.logger.Error(fmt.Sprintf("unit %s start fail, error: %s", unit.Name, err.Error()))
20395
return err
20496
}
205-
Log.Printf("unit %s startup", unit.Name)
97+
r.logger.Info("unit %s startup", unit.Name)
20698
}
20799

208100
return nil
@@ -219,12 +111,13 @@ func (r *Root) ListenAndDestroy() error {
219111
}
220112
}
221113

222-
func New(ctx context.Context) *Root {
114+
func New(ctx context.Context, logger Logger) *Root {
223115
if ctx == nil {
224116
ctx = context.Background()
225117
}
226118

227119
root := &Root{
120+
logger: logger,
228121
destroyUnits: make([]DestroyUnit, 0),
229122
closeSignal: make(chan struct{}, 1),
230123
}

0 commit comments

Comments
 (0)