github.com/vseinstrumentiru/lego@v1.0.2/run.go (about)

     1  package LeGo
     2  
     3  import (
     4  	"context"
     5  	"emperror.dev/emperror"
     6  	"emperror.dev/errors/match"
     7  	"errors"
     8  	"github.com/gorilla/mux"
     9  	"github.com/oklog/run"
    10  	appkiterrors "github.com/sagikazarmark/appkit/errors"
    11  	appkitrun "github.com/sagikazarmark/appkit/run"
    12  	"github.com/vseinstrumentiru/lego/internal/lego"
    13  	"github.com/vseinstrumentiru/lego/internal/lego/monitor/exporter"
    14  	"github.com/vseinstrumentiru/lego/internal/lego/monitor/telemetry"
    15  	"github.com/vseinstrumentiru/lego/internal/lego/transport/event"
    16  	"github.com/vseinstrumentiru/lego/internal/lego/transport/grpc"
    17  	"github.com/vseinstrumentiru/lego/internal/lego/transport/http"
    18  	"github.com/vseinstrumentiru/lego/pkg/contexttool"
    19  	"logur.dev/logur"
    20  	"os"
    21  	"os/signal"
    22  	"syscall"
    23  )
    24  
    25  func Run(ctx context.Context, app lego.App) {
    26  	s := newServer(app.GetName(), extractConfig(app))
    27  	provideConfig(app, s.Config.Custom)
    28  
    29  	defer emperror.HandleRecover(s.Handler())
    30  
    31  	// Do an upgrade on SIGHUP
    32  	go func() {
    33  		ch := make(chan os.Signal, 1)
    34  		signal.Notify(ch, syscall.SIGHUP)
    35  		for range ch {
    36  			s.Info("graceful reloading")
    37  
    38  			_ = s.Upgrader.Upgrade()
    39  		}
    40  	}()
    41  
    42  	{
    43  		config := s.Config.Monitor.Telemetry
    44  
    45  		if cApp, ok := app.(lego.AppWithStats); ok {
    46  			config.Stats = cApp.GetStats()
    47  		}
    48  
    49  		closer := telemetry.Run(s, s.Telemetry, config)
    50  		defer closer.Close()
    51  	}
    52  
    53  	{
    54  		const name = "app"
    55  		app.SetLogErr(
    56  			lego.NewContextAwareLogErr(
    57  				logur.WithField(s.Log(), "server", name),
    58  				s.Handler(),
    59  				contexttool.Extractor,
    60  			).
    61  				WithFilter(appkiterrors.IsServiceError),
    62  		)
    63  	}
    64  
    65  	pubApp, pubOk := app.(lego.AppWithPublishers)
    66  	subApp, subOk := app.(lego.AppWithEventHandlers)
    67  	pubOk, subOk = pubOk && s.Config.Events.Enabled, subOk && s.Config.Events.Enabled
    68  
    69  	if pubOk || subOk {
    70  		em, exec, interrupt := event.Run(s, s.Config.Events)
    71  		defer em.Close()
    72  
    73  		if pubOk {
    74  			err := pubApp.RegisterEventDispatcher(em.Publisher())
    75  			emperror.Panic(err)
    76  		}
    77  
    78  		if cApp, ok := app.(lego.AppWithRegistration); ok {
    79  			closer, err := cApp.Register(s)
    80  			emperror.Panic(err)
    81  
    82  			defer lego.Close(closer)
    83  		}
    84  
    85  		if subOk {
    86  			err := subApp.RegisterEventHandlers(em)
    87  			emperror.Panic(err)
    88  			s.Background(exec, interrupt)
    89  		}
    90  	} else if cApp, ok := app.(lego.AppWithRegistration); ok {
    91  		closer, err := cApp.Register(s)
    92  		emperror.Panic(err)
    93  
    94  		defer lego.Close(closer)
    95  	}
    96  
    97  	if httpApp, ok := app.(lego.AppWithHttp); ok {
    98  		if !s.Config.Http.Enabled {
    99  			emperror.Panic(errors.New("http config not defined"))
   100  		}
   101  
   102  		var mw []mux.MiddlewareFunc
   103  
   104  		if s.Config.Monitor.Exporter.NewRelic.Enabled {
   105  			name := s.Config.Name
   106  
   107  			if s.Config.Monitor.Exporter.NewRelic.AppName != "" {
   108  				name = s.Config.Monitor.Exporter.NewRelic.AppName
   109  			}
   110  
   111  			mw = append(mw, exporter.NewRelicMiddleware(name, s.Config.Monitor.Exporter.NewRelic.Key, s.LogErr.WithFields(map[string]interface{}{"component": "newrelic"})))
   112  		}
   113  
   114  		httpRouter, closer := http.Run(s, s.Config.Http, mw...)
   115  		defer closer.Close()
   116  
   117  		err := httpApp.RegisterHTTP(httpRouter)
   118  		emperror.Panic(err)
   119  	}
   120  
   121  	if grpcApp, ok := app.(lego.AppWithGrpc); ok {
   122  		if !s.Config.Grpc.Enabled {
   123  			emperror.Panic(errors.New("grpc config not defined"))
   124  		}
   125  
   126  		server, closer := grpc.Run(s, s.Config.Grpc)
   127  		defer closer.Close()
   128  
   129  		err := grpcApp.RegisterGRPC(server)
   130  		emperror.Panic(err)
   131  	}
   132  
   133  	if runApp, ok := app.(lego.AppWithRunner); ok {
   134  		terminate := make(chan bool, 1)
   135  		s.Runner.Add(func() error {
   136  			return runApp.Run(terminate)
   137  		}, func(err error) {
   138  			terminate <- true
   139  		})
   140  	}
   141  
   142  	// Setup signal handler
   143  	s.Runner.Add(run.SignalHandler(ctx, syscall.SIGINT, syscall.SIGTERM))
   144  	// Setup graceful restart
   145  	s.Runner.Add(appkitrun.GracefulRestart(ctx, s.Upgrader))
   146  
   147  	err := s.Runner.Run()
   148  	if err != nil {
   149  		s.WithFilter(match.As(&run.SignalError{}).MatchError).Handle(err)
   150  	}
   151  }