github.com/zly-app/zapp@v1.3.3/app.go (about)

     1  /*
     2  -------------------------------------------------
     3     Author :       zlyuancn
     4     date:         2021/1/20
     5     Description :
     6  -------------------------------------------------
     7  */
     8  
     9  package zapp
    10  
    11  import (
    12  	"context"
    13  	"os"
    14  	"os/signal"
    15  	"sync"
    16  	"syscall"
    17  
    18  	_ "go.uber.org/automaxprocs"
    19  	"go.uber.org/zap"
    20  	"gopkg.in/yaml.v3"
    21  
    22  	"github.com/zly-app/zapp/config"
    23  	"github.com/zly-app/zapp/core"
    24  	"github.com/zly-app/zapp/logger"
    25  )
    26  
    27  var defaultApp core.IApp
    28  
    29  func App() core.IApp {
    30  	return defaultApp
    31  }
    32  
    33  type appCli struct {
    34  	name string
    35  
    36  	opt *option
    37  
    38  	baseCtx       context.Context
    39  	baseCtxCancel context.CancelFunc
    40  
    41  	config core.IConfig
    42  	core.ILogger
    43  	component core.IComponent
    44  	plugins   map[core.PluginType]core.IPlugin
    45  	services  map[core.ServiceType]core.IService
    46  
    47  	interrupt chan os.Signal
    48  	onceExit  sync.Once
    49  }
    50  
    51  // 创建一个app
    52  //
    53  // 根据提供的app名和选项创建一个app
    54  // 正常启动时会初始化所有服务
    55  func NewApp(appName string, opts ...Option) core.IApp {
    56  	app := &appCli{
    57  		name:      appName,
    58  		interrupt: make(chan os.Signal, 1),
    59  		plugins:   make(map[core.PluginType]core.IPlugin),
    60  		services:  make(map[core.ServiceType]core.IService),
    61  		opt:       newOption(opts...),
    62  	}
    63  	app.baseCtx, app.baseCtxCancel = context.WithCancel(context.Background())
    64  	defaultApp = app
    65  
    66  	// 启用守护进程
    67  	app.enableDaemon()
    68  
    69  	app.config = config.NewConfig(appName, app.opt.ConfigOpts...)
    70  	if name := app.config.Config().Frame.Name; name != "" {
    71  		app.name = name
    72  	}
    73  	if app.name == "" {
    74  		logger.Log.Fatal("appName is empty")
    75  	}
    76  	app.config.Config().Frame.Name = app.name
    77  
    78  	app.ILogger = logger.NewLogger(appName, app.config, app.opt.LogOpts...)
    79  
    80  	if app.config.Config().Frame.PrintConfig {
    81  		data, err := yaml.Marshal(app.config.GetViper().AllSettings())
    82  		if err != nil {
    83  			app.Error("打印配置时序列化失败", zap.Error(err))
    84  		} else {
    85  			app.Info("配置数据:\n", string(data), "\n")
    86  		}
    87  	}
    88  
    89  	app.handler(BeforeInitializeHandler)
    90  	app.Debug("app初始化")
    91  
    92  	// 构建组件
    93  	app.makeComponent()
    94  	// 构建插件
    95  	app.makePlugin()
    96  	// 构建服务
    97  	app.makeService()
    98  
    99  	app.Debug("app初始化完毕")
   100  	app.handler(AfterInitializeHandler)
   101  
   102  	return app
   103  }
   104  
   105  func (app *appCli) run() {
   106  	app.handler(BeforeStartHandler)
   107  	app.Debug("启动app")
   108  
   109  	// 启动插件
   110  	app.startPlugin()
   111  	// 启动服务
   112  	app.startService()
   113  	// 开始释放内存
   114  	app.startFreeMemory()
   115  
   116  	app.Info("app已启动")
   117  	app.handler(AfterStartHandler)
   118  
   119  	signal.Notify(app.interrupt, os.Kill, os.Interrupt, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM)
   120  	<-app.interrupt
   121  
   122  	app.onceExit.Do(func() {
   123  		app.exit()
   124  	})
   125  }
   126  
   127  func (app *appCli) exit() {
   128  	// app退出前
   129  	app.handler(BeforeExitHandler)
   130  	app.Debug("app准备退出")
   131  
   132  	// 关闭基础上下文
   133  	app.baseCtxCancel()
   134  	// 关闭服务
   135  	app.closeService()
   136  	// 关闭插件
   137  	app.closePlugin()
   138  	// 释放组件资源
   139  	app.releaseComponentResource()
   140  
   141  	// app退出后
   142  	app.Warn("app已退出")
   143  	app.handler(AfterExitHandler)
   144  }
   145  
   146  func (app *appCli) Name() string {
   147  	return app.name
   148  }
   149  
   150  // 启动
   151  func (app *appCli) Run() {
   152  	app.run()
   153  }
   154  
   155  // 退出
   156  func (app *appCli) Exit() {
   157  	app.onceExit.Do(func() {
   158  		// 尝试发送退出信号
   159  		select {
   160  		case app.interrupt <- syscall.SIGQUIT:
   161  		default:
   162  		}
   163  
   164  		app.exit()
   165  	})
   166  }
   167  
   168  func (app *appCli) BaseContext() context.Context {
   169  	return app.baseCtx
   170  }
   171  
   172  func (app *appCli) GetConfig() core.IConfig {
   173  	return app.config
   174  }
   175  
   176  func (app *appCli) GetLogger() core.ILogger {
   177  	return app.ILogger
   178  }