123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- package svcfw
- import (
- "context"
- "fmt"
- "git.swzry.com/zry/GoHiedaLogger/hiedabke_console"
- "git.swzry.com/zry/GoHiedaLogger/hiedalog"
- "git.swzry.com/zry/zry-go-program-framework/core"
- ordmap "github.com/edofic/go-ordmap/v2"
- "github.com/oklog/run"
- "io"
- "sync"
- )
- var _ core.IAppFramework = (*AppFramework)(nil)
- var _ core.IModuleLogger = (*AppFramework)(nil)
- var _ core.IModuleLogLevelLimiter = (*AppFramework)(nil)
- type AppFramework struct {
- rg *run.Group
- logger *hiedalog.HiedaLogger
- gctx context.Context
- gcncl context.CancelFunc
- subSvc ordmap.NodeBuiltin[string, *core.SubServiceWrapper]
- moduleLoggers map[string]core.IModuleLogger
- moduleLoggersLock sync.RWMutex
- appLogModuleName string
- globalDebugSwitch bool
- prepared bool
- consoleLogBackend *hiedabke_console.ConsoleBackend
- mainLogLevelLimit uint8
- core.IModuleLogger
- core.IModuleLogLevelLimiter
- }
- func NewAppFramework(globalDebugMode bool, appLogModuleName string) *AppFramework {
- f := &AppFramework{
- rg: &run.Group{},
- logger: hiedalog.NewHiedaLogger(),
- subSvc: ordmap.NewBuiltin[string, *core.SubServiceWrapper](),
- appLogModuleName: appLogModuleName,
- moduleLoggers: map[string]core.IModuleLogger{},
- globalDebugSwitch: globalDebugMode,
- prepared: false,
- mainLogLevelLimit: 0,
- }
- mlog := core.NewModuleLogger(appLogModuleName, f)
- f.moduleLoggers[appLogModuleName] = mlog
- f.IModuleLogger = mlog
- f.IModuleLogLevelLimiter = mlog
- return f
- }
- // InitConsoleLogBackend add a hiedalog console backend to logger system
- // if lv == "", for globalDebugMode is on, will use hiedalog.DLN_DEBUG;
- // for globalDebugMode is off, will use hiedalog.DLN_INFO.
- func (f *AppFramework) InitConsoleLogBackend(writer io.Writer, lv string) {
- klv := lv
- if klv == "" {
- if f.globalDebugSwitch {
- klv = hiedalog.DLN_DEBUG
- } else {
- klv = hiedalog.DLN_INFO
- }
- }
- f.consoleLogBackend = hiedabke_console.NewConsoleBackend(writer)
- f.logger.AddBackend(f.consoleLogBackend, f.logger.LevelFilter.NameToID(klv))
- }
- // ShutdownConsoleLogBackend shutdown the console backend which created by InitConsoleLogBackend
- func (f *AppFramework) ShutdownConsoleLogBackend() {
- if f.consoleLogBackend != nil {
- f.consoleLogBackend.Shutdown()
- }
- }
- // AddSubSvc add a sub service
- func (f *AppFramework) AddSubSvc(name string, svc core.ISubService) {
- _, ok := f.subSvc.Get(name)
- if ok {
- panic("SubService name exists.")
- }
- sw := core.NewSubServiceWrapper(f, name, svc)
- f.subSvc = f.subSvc.Insert(name, sw)
- f.rg.Add(sw.Run, sw.Stop)
- }
- // GetRawLogger get the HiedaLogger inside this
- func (f *AppFramework) GetRawLogger() *hiedalog.HiedaLogger {
- return f.logger
- }
- func (f *AppFramework) GetModuleLogger(module string) core.IModuleLogger {
- f.moduleLoggersLock.RLock()
- v, ok := f.moduleLoggers[module]
- if !ok {
- f.moduleLoggersLock.RUnlock()
- f.moduleLoggersLock.Lock()
- v = core.NewModuleLogger(module, f)
- f.moduleLoggers[module] = v
- f.moduleLoggersLock.Unlock()
- } else {
- f.moduleLoggersLock.RUnlock()
- }
- return v
- }
- // Prepare call the `Prepare()` of each SubService by order of addition
- func (f *AppFramework) Prepare() error {
- var err error
- for i := f.subSvc.Iterate(); !i.Done(); i.Next() {
- f.DebugF("preparing for sub service '%s'...", i.GetKey())
- err = i.GetValue().Prepare()
- if err != nil {
- f.ErrorF("failed prepare sub service '%s': %v", i.GetKey(), err)
- return err
- }
- }
- f.prepared = true
- return nil
- }
- // Run start the app
- func (f *AppFramework) Run() error {
- if !f.prepared {
- return fmt.Errorf("failed run app: `Prepare()` not called")
- }
- return f.RunWithContext(context.Background())
- }
- // RunWithContext start the app with custom context
- func (f AppFramework) RunWithContext(ctx context.Context) error {
- ctx, cncl := context.WithCancel(ctx)
- f.gcncl = cncl
- f.gctx = ctx
- f.rg.Add(f.bgRun, f.bgStop)
- return f.rg.Run()
- }
- // Stop stop the app
- func (f *AppFramework) Stop() {
- if f.gcncl != nil {
- f.gcncl()
- }
- }
- func (f *AppFramework) bgRun() error {
- select {
- case <-f.gctx.Done():
- return nil
- }
- }
- func (f *AppFramework) bgStop(xerr error) {
- f.Stop()
- }
- func (f *AppFramework) GetContext() context.Context {
- return f.gctx
- }
- func (f *AppFramework) IsGlobalDebugMode() bool {
- return f.globalDebugSwitch
- }
- func (f *AppFramework) SetGlobalDebugMode(en bool) {
- f.globalDebugSwitch = en
- }
|