package app import ( "bitbucket.org/skeris/heruvym/dal" "bitbucket.org/skeris/heruvym/middleware" "bitbucket.org/skeris/heruvym/router" "bitbucket.org/skeris/heruvym/service" "bitbucket.org/skeris/heruvym/tools" "bitbucket.org/skeris/heruvym/version" rAL "bitbucket.org/skeris/profile/dal" "context" "errors" "fmt" "github.com/BlackBroker/trashlog/wrappers/zaptg" "github.com/skeris/appInit" "go.uber.org/zap/zapcore" "net/http" "os" "os/signal" "syscall" "github.com/themakers/hlog" "go.uber.org/zap" ) type App struct { err chan error logger *zap.Logger } const ( ENV = "env" DEFAULT = "default" ) type Options struct { MongoURI string `env:"BB_MONGO_URI" default:"mongodb://localhost:27017"` NumberPortLocal string `env:"BB_PORT" default:"1488"` LoggerDevMode bool `env:"BB_IS_PROD" default:"false"` MongoDbTable string `env:"DATABASE_TABLE" default:"profile"` MongoCollections string `env:"COLLECTION_NAME" default:"profile,role"` } var ( errInvalidOptions = errors.New("invalid options") ) var _ appInit.CommonApp = (*App)(nil) type InfoSvcStarted struct{} type InfoSvcReady struct{} type InfoSvcShutdown struct { Signal string } type ErrorStoring struct { Err error Uri string } type ErrorCanNotServe struct { Err error } var zapOptions = []zap.Option{ zap.AddCaller(), zap.AddCallerSkip(2), zap.AddStacktrace(zap.ErrorLevel), } func New(ctx context.Context, opts interface{}) (appInit.CommonApp, error) { var ( err error zapLogger *zap.Logger errChan = make(chan error) options Options ok bool ) if options, ok = opts.(Options); !ok { return App{}, errInvalidOptions } if options.LoggerDevMode { zapLogger, err = zap.NewDevelopment(zapOptions...) if err != nil { return nil, err } } else { zapLogger, err = zap.NewProduction(zapOptions...) if err != nil { return nil, err } } zapLogger = zapLogger.With( zap.String("SvcCommit", version.Commit), zap.String("SvcVersion", version.Release), zap.String("SvcBuildTime", version.BuildTime), ) tl, err := zaptg.NewCore( ctx, zap.ErrorLevel, "1408111289:AAHfWZRiBQRncb2gl2LtU8OeASjfJi4e8YE", version.Release, version.Commit, 0, -1001230000451, ) if err != nil { panic(err) } zapLogger = zapLogger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core { return zapcore.NewTee(core, tl) })) logger := hlog.New(zapLogger) logger.Emit(InfoSvcStarted{}) database, err := dal.New( ctx, options.MongoURI, "support", logger, ) if err != nil { return nil, err } connRoles, err := rAL.ConnectToDb(ctx, logger, rAL.MongoDbOptions{ DalName: "MongoDB", URI: options.MongoURI, DbTable: options.MongoDbTable, Collections: options.MongoCollections, }) heruvym := service.New(database, connRoles, logger) interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM) mux := router.NewRouter(map[string]http.HandlerFunc{ "/support/create": heruvym.CreateTicket, "/support/subscribe": tools.SseWrapper(heruvym.GetList), "/support/ticket": tools.SseWrapper(heruvym.Subscribe), "/support/send": tools.HandlerWrapper(heruvym.PutMessage), "/support/getTickets": tools.HandlerWrapper(heruvym.GetTickets), "/support/getMessages": tools.HandlerWrapper(heruvym.GetMessages), "/support/pick": tools.HandlerWrapper(heruvym.Pick), "/support/delegate": tools.HandlerWrapper(heruvym.Delegate), "/support/vote": tools.HandlerWrapper(heruvym.Vote), "/support/close": tools.HandlerWrapper(heruvym.CloseTicket), }) mw := middleware.NewMiddleware( logger, nil, "*", nil, ) mux.Use( mw.MiddlewareLogger, mw.MiddlewareOriginAccess, mw.MiddlewareRecovery, mw.MiddlewareJwt, mw.MiddlewareGetJwt, //mw.MiddlewareJwtPlug, //mw.MiddlewareRoleAccess, ) server := &http.Server{ Handler: mux, Addr: fmt.Sprintf(":%s", options.NumberPortLocal), } go func() { killSignal := <-interrupt switch killSignal { case os.Interrupt: logger.Emit(InfoSvcShutdown{ Signal: "Interrupt", }) case syscall.SIGTERM: logger.Emit(InfoSvcShutdown{ Signal: "Terminate", }) } if err := server.Shutdown(ctx); err != nil { panic(err) } }() logger.Emit(InfoSvcStarted{}) if err := server.ListenAndServe(); err != nil { logger.Emit(ErrorCanNotServe{ Err: err, }) return nil, err } return &App{ logger: zapLogger, err: errChan, }, nil } func (a App) GetLogger() *zap.Logger { return a.logger } func (a App) GetErr() chan error { return a.err }