@@ -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
2347type 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
105150func (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
162208func (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}
0 commit comments