Skip to content

Commit 014a6a8

Browse files
author
陆丹峰
committed
2 parents baebf2c + 87c9d49 commit 014a6a8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+11158
-5679
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
- name: Setup Go
1515
uses: actions/setup-go@v2
1616
with:
17-
go-version: 1.17
17+
go-version: 1.18
1818
- name: Setup golangci-lint
1919
uses: golangci/golangci-lint-action@v2.5.2
2020
- name: Run linter

README.md

Lines changed: 115 additions & 93 deletions
Large diffs are not rendered by default.

boot.go

Lines changed: 106 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,50 @@ import (
1010
"context"
1111
"embed"
1212
"fmt"
13-
"github.com/rookie-ninja/rk-entry/v2/entry"
14-
"github.com/rookie-ninja/rk-entry/v2/middleware"
15-
"go.uber.org/zap"
16-
"io/ioutil"
1713
"os"
18-
"path"
14+
"path/filepath"
1915
"runtime/debug"
16+
17+
rkentry "github.com/rookie-ninja/rk-entry/v2/entry"
18+
rkmid "github.com/rookie-ninja/rk-entry/v2/middleware"
19+
"go.uber.org/zap"
2020
)
2121

22+
type hookFuncM map[string]map[string]func(ctx context.Context)
23+
24+
func newHookFuncM() hookFuncM {
25+
return map[string]map[string]func(ctx context.Context){}
26+
}
27+
28+
func (m hookFuncM) addFunc(entryType, entryName string, f func(ctx context.Context)) {
29+
if _, ok := m[entryType]; !ok {
30+
m[entryType] = make(map[string]func(ctx context.Context))
31+
}
32+
33+
m[entryType][entryName] = f
34+
}
35+
36+
func (m hookFuncM) getFunc(entryType, entryName string) func(ctx context.Context) {
37+
if inner, ok := m[entryType]; ok {
38+
if f, ok := inner[entryName]; ok {
39+
return f
40+
}
41+
}
42+
43+
return func(ctx context.Context) {}
44+
}
45+
2246
// Boot is a structure for bootstrapping rk style application
2347
type Boot struct {
24-
bootConfigPath string `yaml:"-" json:"-"`
25-
embedFS *embed.FS `yaml:"-" json:"-"`
26-
bootConfigRaw []byte `yaml:"-" json:"-"`
27-
preloadF map[string]map[string]func() `yaml:"-" json:"-"`
28-
EventId string `yaml:"-" json:"-"`
48+
bootConfigPath string `yaml:"-" json:"-"`
49+
embedFS *embed.FS `yaml:"-" json:"-"`
50+
bootConfigRaw []byte `yaml:"-" json:"-"`
51+
beforeHookF hookFuncM `yaml:"-" json:"-"`
52+
afterHookF hookFuncM `yaml:"-" json:"-"`
53+
EventId string `yaml:"-" json:"-"`
54+
pluginEntries map[string]map[string]rkentry.Entry
55+
userEntries map[string]map[string]rkentry.Entry
56+
webEntries map[string]map[string]rkentry.Entry
2957
}
3058

3159
// BootOption is used as options while bootstrapping from code
@@ -53,8 +81,12 @@ func NewBoot(opts ...BootOption) *Boot {
5381
defer syncLog("N/A")
5482

5583
boot := &Boot{
56-
EventId: rkmid.GenerateRequestId(),
57-
preloadF: map[string]map[string]func(){},
84+
EventId: rkmid.GenerateRequestId(nil),
85+
beforeHookF: newHookFuncM(),
86+
afterHookF: newHookFuncM(),
87+
pluginEntries: map[string]map[string]rkentry.Entry{},
88+
userEntries: map[string]map[string]rkentry.Entry{},
89+
webEntries: map[string]map[string]rkentry.Entry{},
5890
}
5991

6092
for i := range opts {
@@ -64,59 +96,83 @@ func NewBoot(opts ...BootOption) *Boot {
6496
raw := boot.readYAML()
6597

6698
// Register entries need to pre-build.
67-
rkentry.BootstrapPreloadEntryYAML(raw)
99+
rkentry.BootstrapBuiltInEntryFromYAML(raw)
100+
101+
for _, f := range rkentry.ListPluginEntryRegFunc() {
102+
for _, v := range f(raw) {
103+
if boot.pluginEntries[v.GetType()] == nil {
104+
boot.pluginEntries[v.GetType()] = make(map[string]rkentry.Entry)
105+
}
106+
boot.pluginEntries[v.GetType()][v.GetName()] = v
107+
}
108+
}
68109

69-
// Register entries
70-
regFuncList := rkentry.ListEntryRegFunc()
71-
for i := range regFuncList {
72-
regFuncList[i](raw)
110+
for _, f := range rkentry.ListUserEntryRegFunc() {
111+
for _, v := range f(raw) {
112+
if boot.userEntries[v.GetType()] == nil {
113+
boot.userEntries[v.GetType()] = make(map[string]rkentry.Entry)
114+
}
115+
boot.userEntries[v.GetType()][v.GetName()] = v
116+
}
117+
}
118+
119+
for _, f := range rkentry.ListWebFrameEntryRegFunc() {
120+
for _, v := range f(raw) {
121+
if boot.webEntries[v.GetType()] == nil {
122+
boot.webEntries[v.GetType()] = make(map[string]rkentry.Entry)
123+
}
124+
boot.webEntries[v.GetType()][v.GetName()] = v
125+
}
73126
}
74127

75128
return boot
76129
}
77130

78-
// AddPreloadFuncBeforeBootstrap run functions before certain entry Bootstrap()
79-
func (boot *Boot) AddPreloadFuncBeforeBootstrap(entry rkentry.Entry, f func()) {
80-
if entry == nil || f == nil {
131+
// AddHookFuncBeforeBootstrap run functions before certain entry Bootstrap()
132+
func (boot *Boot) AddHookFuncBeforeBootstrap(entryType, entryName string, f func(ctx context.Context)) {
133+
if f == nil {
81134
return
82135
}
83136

84-
entryName := entry.GetName()
85-
entryType := entry.GetType()
137+
boot.beforeHookF.addFunc(entryType, entryName, f)
138+
}
86139

87-
if _, ok := boot.preloadF[entryType]; !ok {
88-
boot.preloadF[entryType] = make(map[string]func())
140+
// AddHookFuncAfterBootstrap run functions before certain entry Bootstrap()
141+
func (boot *Boot) AddHookFuncAfterBootstrap(entryType, entryName string, f func(ctx context.Context)) {
142+
if f == nil {
143+
return
89144
}
90145

91-
boot.preloadF[entryType][entryName] = f
146+
boot.afterHookF.addFunc(entryType, entryName, f)
92147
}
93148

94-
// Bootstrap entries in rkentry.GlobalAppCtx including bellow:
95-
//
96-
// Internal entries:
97-
// 1: rkentry.AppInfoEntry
98-
// 2: rkentry.ConfigEntry
99-
// 3: rkentry.LoggerEntry
100-
// 4: rkentry.EventEntry
101-
// 5: rkentry.CertEntry
102-
//
103-
// External entries:
104-
// User defined entries
149+
// Bootstrap entries as sequence of plugin, user defined and web framework
105150
func (boot *Boot) Bootstrap(ctx context.Context) {
106151
defer syncLog(boot.EventId)
107152

108153
ctx = context.WithValue(ctx, "eventId", boot.EventId)
109154

110-
// Bootstrap external entries
111-
for _, m := range rkentry.GlobalAppCtx.ListEntries() {
112-
for _, entry := range m {
113-
if m, ok := boot.preloadF[entry.GetType()]; ok {
114-
if v, ok := m[entry.GetName()]; ok {
115-
v()
116-
}
117-
}
155+
for entryType, byEntryName := range boot.pluginEntries {
156+
for entryName, e := range byEntryName {
157+
boot.beforeHookF.getFunc(entryType, entryName)(ctx)
158+
e.Bootstrap(ctx)
159+
boot.afterHookF.getFunc(entryType, entryName)(ctx)
160+
}
161+
}
118162

119-
entry.Bootstrap(ctx)
163+
for entryType, byEntryName := range boot.userEntries {
164+
for entryName, e := range byEntryName {
165+
boot.beforeHookF.getFunc(entryType, entryName)(ctx)
166+
e.Bootstrap(ctx)
167+
boot.afterHookF.getFunc(entryType, entryName)(ctx)
168+
}
169+
}
170+
171+
for entryType, byEntryName := range boot.webEntries {
172+
for entryName, e := range byEntryName {
173+
boot.beforeHookF.getFunc(entryType, entryName)(ctx)
174+
e.Bootstrap(ctx)
175+
boot.afterHookF.getFunc(entryType, entryName)(ctx)
120176
}
121177
}
122178
}
@@ -148,17 +204,7 @@ func (boot *Boot) AddShutdownHookFunc(name string, f rkentry.ShutdownHook) {
148204
rkentry.GlobalAppCtx.AddShutdownHook(name, f)
149205
}
150206

151-
// Interrupt entries in rkentry.GlobalAppCtx including bellow:
152-
//
153-
// Internal entries:
154-
// 1: rkentry.AppInfoEntry
155-
// 2: rkentry.ConfigEntry
156-
// 3: rkentry.ZapLoggerEntry
157-
// 4: rkentry.EventLoggerEntry
158-
// 5: rkentry.CertEntry
159-
//
160-
// External entries:
161-
// User defined entries
207+
// Interrupt entries as sequence of plugin, user defined and web framework
162208
func (boot *Boot) interrupt(ctx context.Context) {
163209
defer syncLog(boot.EventId)
164210

@@ -192,12 +238,12 @@ func (boot *Boot) readYAML() []byte {
192238
if len(boot.bootConfigPath) < 1 {
193239
boot.bootConfigPath = "boot.yaml"
194240
}
195-
if !path.IsAbs(boot.bootConfigPath) {
241+
if !filepath.IsAbs(boot.bootConfigPath) {
196242
wd, _ := os.Getwd()
197-
boot.bootConfigPath = path.Join(wd, boot.bootConfigPath)
243+
boot.bootConfigPath = filepath.Join(wd, boot.bootConfigPath)
198244
}
199245

200-
res, err := ioutil.ReadFile(boot.bootConfigPath)
246+
res, err := os.ReadFile(boot.bootConfigPath)
201247
if err != nil {
202248
rkentry.ShutdownWithError(err)
203249
}
@@ -231,6 +277,6 @@ func syncLog(eventId string) {
231277
event.Sync()
232278
}
233279

234-
panic(r)
280+
os.Exit(1)
235281
}
236282
}

boot_test.go

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"context"
1010
"embed"
1111
"encoding/json"
12+
"fmt"
1213
"github.com/rookie-ninja/rk-entry/v2/entry"
1314
"github.com/stretchr/testify/assert"
1415
"syscall"
@@ -24,14 +25,25 @@ myEntry:
2425
enabled: true
2526
`
2627

28+
triggerBefore := false
29+
triggerAfter := false
30+
2731
boot := NewBoot(WithBootConfigRaw([]byte(config)))
2832
boot.AddShutdownHookFunc("ut-shutdown", func() {
2933
// noop
3034
})
35+
boot.AddHookFuncBeforeBootstrap("myEntry", "ut", func(ctx context.Context) {
36+
triggerBefore = true
37+
})
38+
boot.AddHookFuncAfterBootstrap("myEntry", "ut", func(ctx context.Context) {
39+
triggerAfter = true
40+
})
3141

3242
boot.Bootstrap(context.TODO())
3343

3444
assert.Len(t, rkentry.GlobalAppCtx.ListEntriesByType("myEntry"), 1)
45+
assert.True(t, triggerBefore)
46+
assert.True(t, triggerAfter)
3547

3648
go func() {
3749
boot.WaitForShutdownSig(context.TODO())
@@ -51,28 +63,15 @@ func TestNewBoot_WithEmbedCase(t *testing.T) {
5163
myEntry := rkentry.GlobalAppCtx.GetEntry("myEntry", "ut")
5264
assert.NotNil(t, myEntry)
5365

54-
preCall := false
55-
56-
boot.AddPreloadFuncBeforeBootstrap(myEntry, func() {
57-
preCall = true
58-
})
59-
6066
boot.Bootstrap(context.TODO())
6167
boot.interrupt(context.TODO())
6268

63-
assert.True(t, preCall)
64-
6569
rkentry.GlobalAppCtx.RemoveEntry(rkentry.GlobalAppCtx.GetEntry("myEntry", "ut"))
6670
}
6771

68-
func TestNewBoot_EmptyConfig(t *testing.T) {
69-
defer assertPanic(t)
70-
71-
NewBoot()
72-
}
73-
7472
func assertPanic(t *testing.T) {
7573
if r := recover(); r != nil {
74+
fmt.Println("adsfadfafd")
7675
// Expect panic to be called with non nil error
7776
assert.True(t, true)
7877
} else {
@@ -83,7 +82,7 @@ func assertPanic(t *testing.T) {
8382

8483
// Register entry, must be in init() function since we need to register entry at beginning
8584
func init() {
86-
rkentry.RegisterEntryRegFunc(RegisterMyEntriesFromConfig)
85+
rkentry.RegisterUserEntryRegFunc(RegisterMyEntriesFromConfig)
8786
}
8887

8988
// A struct which is for unmarshalled YAML

docs/img/gin-sw.png

-187 KB
Binary file not shown.

docs/img/gin-tv.png

-184 KB
Binary file not shown.

docs/img/rk-boot-logo.png

23.2 KB
Loading

docs/img/rk-op.gif

2.54 MB
Loading

docs/img/wechat-group-cn.png

15.6 KB
Loading

0 commit comments

Comments
 (0)