package app import ( "context" "errors" "net/http" "github.com/danilsolovyov/croupierCbrf/internal/dal" "github.com/danilsolovyov/croupierCbrf/internal/handlers" "github.com/danilsolovyov/croupierCbrf/internal/worker" "github.com/gorilla/mux" "github.com/skeris/appInit" "github.com/themakers/hlog" "go.uber.org/zap" //"net/http" "os" "os/signal" "syscall" ) type Options struct { IsProduction bool `env:"IS_PRODUCTION" default:"false"` Development bool `env:"DEVELOPMENT" default:"true"` AppName string `env:"APP_NAME" default:"croupierWorkerQuotes"` AppAddr string `env:"APP_ADDR" default:"localhost:3131"` AllowedOrigins string `env:"ALLOWED_ORIGINS" default:"*"` AllowedHeaders string `env:"ALLOWED_HEADERS" default:"*"` ExposeHeaders string `env:"EXPOSE_HEADERS" default:"*"` MongoDbUri string `env:"DATABASE_URI" default:"mongodb+srv://user_1:cEDxC8ptLMMeoA5m@cluster0.aomle.mongodb.net/test"` MongoDbTable string `env:"DATABASE_TABLE" default:"croupier"` MongoCollections string `env:"COLLECTION_NAME" default:"quote"` } type App struct { logger *zap.Logger err chan error } func (a App) GetLogger() *zap.Logger { return a.logger } func (a App) GetErr() chan error { return a.err } //#region ======== Hl Info Structs ======== type InfoSvcStarted struct{} type InfoInterruptSignal struct{} type InfoTerminateSignal struct{} type InfoSvcShuttingDown struct{} type InfoSvcDone struct{} //#endregion //#region ======== Hl ErrorTypeApp Structs ======== type ErrorTypeApp struct { Error error } type ErrorCanNotServe ErrorTypeApp type ErrorSvcShuttingDown ErrorTypeApp type ErrorZlogSync ErrorTypeApp type ErrorConnectToMongo ErrorTypeApp type ErrorDisconnectFromMongo ErrorTypeApp type ErrorConnectToMinio ErrorTypeApp type ErrorNewPairCache ErrorTypeApp type ErrorNewMainWorker ErrorTypeApp type ErrorStoreConnect struct { Err string Credentials string } //#endregion func New(ctx context.Context, options interface{}) (appInit.CommonApp, error) { opts := options.(Options) var errCh chan error // Create logger zlog, err := zap.NewDevelopment() if err != nil { panic(err) } zlog = zlog.WithOptions(zap.AddCallerSkip(2)) //tl, err := zaptrashlog.NewCore( // ctx, // zapcore.DebugLevel, // "trashlog:8008", // v.Release, // v.Commit, // time.Now().Unix(), //) //if err != nil { // tel, err := zaptg.NewCore( // ctx, // zap.ErrorLevel, // "1408111289:AAHfWZRiBQRncb2gl2LtU8OeASjfJi4e8YE", // v.Release, // v.Commit, // 0, // -1001230000451, // ) // if err != nil { // panic(err) // } // zlog = zlog.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core { // return zapcore.NewTee(core, tel) // })) //} else { // zlog = zlog.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core { // return zapcore.NewTee(core, tl) // })) //} hlogger := hlog.New(zlog) //hlogger = hlogger.With(v.GetVersion()) defer func() { err = zlog.Sync() if err != nil { hlogger.Emit(ErrorZlogSync{err}) return } }() // Connect to MongoDb connMongo, err := dal.CreateMongo(ctx, hlogger, dal.MongoDbOptions{ DalName: "MongoDB", URI: opts.MongoDbUri, DbTable: opts.MongoDbTable, Collections: opts.MongoCollections, }) if err != nil { hlogger.Emit(ErrorConnectToMongo{err}) return App{zlog, errCh}, err } ctxL, cancL := context.WithCancel(ctx) defer cancL() err = worker.InitAndStart(ctxL, connMongo, hlogger) if err != nil { return App{zlog, errCh}, err } router := mux.NewRouter() handler := handlers.NewHandler(connMongo, hlogger, "") router.HandleFunc("/getQuotes", handler.GetQuotes) router.HandleFunc("/change", handler.Translate) // Startup server srv := &http.Server{Addr: opts.AppAddr, Handler: router} go func() { err = srv.ListenAndServe() if err != http.ErrServerClosed && err != nil { hlogger.Emit(ErrorCanNotServe{Error: err}) } }() hlogger.Emit(InfoSvcStarted{}) // Graceful Shutdown interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM) killSignal := <-interrupt switch killSignal { case os.Interrupt: err = errors.New("interrupted") hlogger.Emit(InfoInterruptSignal{}) case syscall.SIGTERM: err = errors.New("terminated") hlogger.Emit(InfoTerminateSignal{}) } hlogger.Emit(InfoSvcShuttingDown{}) err = srv.Shutdown(ctx) if err != nil { hlogger.Emit(ErrorSvcShuttingDown{err}) } hlogger.Emit(InfoSvcDone{}) err = errors.New("finished") // Костыль чтобы приложение нормально закрывалось... return App{zlog, errCh}, err }