server.go
func (a *App) Serve(srvs ...servers.Server) error {
	a.Logger.Infof("Starting application at %s", a.Options.Addr)

	payload := events.Payload{
		"app": a,
	}
	if err := events.EmitPayload(EvtAppStart, payload); err != nil {
		return err
	}

	if len(srvs) == 0 {
		if strings.HasPrefix(a.Options.Addr, "unix:") {
			tcp, err := servers.UnixSocket(a.Options.Addr[5:])
			if err != nil {
				return err
			}
			srvs = append(srvs, tcp)
		} else {
			srvs = append(srvs, servers.New())
		}
	}

	ctx, cancel := sigtx.WithCancel(a.Context, syscall.SIGTERM, os.Interrupt)
	defer cancel()

	go func() {
		// gracefully shut down the application when the context is cancelled
		<-ctx.Done()
		a.Logger.Info("Shutting down application")

		events.EmitError(EvtAppStop, ctx.Err(), payload)

		if err := a.Stop(ctx.Err()); err != nil {
			events.EmitError(EvtAppStopErr, err, payload)
			a.Logger.Error(err)
		}

		if !a.WorkerOff {
			// stop the workers
			a.Logger.Info("Shutting down worker")
			events.EmitPayload(EvtWorkerStop, payload)
			if err := a.Worker.Stop(); err != nil {
				events.EmitError(EvtWorkerStopErr, err, payload)
				a.Logger.Error(err)
			}
		}

		for _, s := range srvs {
			if err := s.Shutdown(ctx); err != nil {
				a.Logger.Error(err)
			}
		}

	}()

	// if configured to do so, start the workers
	if !a.WorkerOff {
		go func() {
			events.EmitPayload(EvtWorkerStart, payload)
			if err := a.Worker.Start(ctx); err != nil {
				a.Stop(err)
			}
		}()
	}

	for _, s := range srvs {
		s.SetAddr(a.Addr)
		go func(s servers.Server) {
			if err := s.Start(ctx, a); err != nil {
				a.Stop(err)
			}
		}(s)
	}

	<-ctx.Done()

	return a.Context.Err()
}
func (a *App) Serve(srvs ...servers.Server) error {
	a.Logger.Infof("Starting application at %s", a.Options.Addr)

	payload := events.Payload{
		"app": a,
	}
	if err := events.EmitPayload(EvtAppStart, payload); err != nil {
		return err
	}

	if len(srvs) == 0 {
		if strings.HasPrefix(a.Options.Addr, "unix:") {
			tcp, err := servers.UnixSocket(a.Options.Addr[5:])
			if err != nil {
				return err
			}
			srvs = append(srvs, tcp)
		} else {
			srvs = append(srvs, servers.New())
		}
	}

	ctx, cancel := sigtx.WithCancel(a.Context, syscall.SIGTERM, os.Interrupt)
	defer cancel()

	go func() {
		// gracefully shut down the application when the context is cancelled
		<-ctx.Done()
		a.Logger.Info("Shutting down application")

		events.EmitError(EvtAppStop, ctx.Err(), payload)

		if err := a.Stop(ctx.Err()); err != nil {
			events.EmitError(EvtAppStopErr, err, payload)
			a.Logger.Error(err)
		}

		if !a.WorkerOff {
			// stop the workers
			a.Logger.Info("Shutting down worker")
			events.EmitPayload(EvtWorkerStop, payload)
			if err := a.Worker.Stop(); err != nil {
				events.EmitError(EvtWorkerStopErr, err, payload)
				a.Logger.Error(err)
			}
		}

		for _, s := range srvs {
			if err := s.Shutdown(ctx); err != nil {
				a.Logger.Error(err)
			}
		}

	}()

	// if configured to do so, start the workers
	if !a.WorkerOff {
		go func() {
			events.EmitPayload(EvtWorkerStart, payload)
			if err := a.Worker.Start(ctx); err != nil {
				a.Stop(err)
			}
		}()
	}

	for _, s := range srvs {
		s.SetAddr(a.Addr)
		go func(s servers.Server) {
			if err := s.Start(ctx, a); err != nil {
				a.Stop(err)
			}
		}(s)
	}

	<-ctx.Done()

	return a.Context.Err()
}
// Serve the application at the specified address/port and listen for OS
// interrupt and kill signals and will attempt to stop the application
// gracefully. This will also start the Worker process, unless WorkerOff is enabled.