func (kern *Kernel) Shutdown(ctx context.Context) (err error) {
	kern.shutdownOnce.Do(func() {
		logger := kern.Logger.WithScope("Shutdown")
		logger.InfoMsg("Attempting graceful shutdown...")
		logger.InfoMsg("Shutting down servers")
		ctx, cancel := context.WithTimeout(ctx, ServerShutdownTimeout)
		defer cancel()
		// Shutdown servers in reverse order to boot
		for i := len(kern.Launchers) - 1; i >= 0; i-- {
			name := kern.Launchers[i].Name
			srvr, ok := kern.processes[name]
			if ok {
				logger.InfoMsg("Shutting down server", "server_name", name)
				sErr := srvr.Shutdown(ctx)
				if sErr != nil {
					logger.InfoMsg("Failed to shutdown server",
						"server_name", name,
						structure.ErrorKey, sErr)
					if err == nil {
						err = sErr
					}
				}
			}
		}
		logger.InfoMsg("Shutdown complete")
		structure.Sync(kern.Logger.Info)
		structure.Sync(kern.Logger.Trace)
		// We don't want to wait for them, but yielding for a cooldown Let other goroutines flush
		// potentially interesting final output (e.g. log messages)
		time.Sleep(CooldownTime)
		close(kern.shutdownNotify)
	})
	return
}
// Stop the kernel allowing for a graceful shutdown of components in order
Stop the kernel allowing for a graceful shutdown of components in order
// Stop the kernel allowing for a graceful shutdown of components in order
func (kern *Kernel) Shutdown(ctx context.Context) (err error) {
	kern.shutdownOnce.Do(func() {
		logger := kern.Logger.WithScope("Shutdown")
		logger.InfoMsg("Attempting graceful shutdown...")
		logger.InfoMsg("Shutting down servers")
		ctx, cancel := context.WithTimeout(ctx, ServerShutdownTimeout)
		defer cancel()
		for i := len(kern.Launchers) - 1; i >= 0; i-- {
			name := kern.Launchers[i].Name
			srvr, ok := kern.processes[name]
			if ok {
				logger.InfoMsg("Shutting down server", "server_name", name)
				sErr := srvr.Shutdown(ctx)
				if sErr != nil {
					logger.InfoMsg("Failed to shutdown server",
						"server_name", name,
						structure.ErrorKey, sErr)
					if err == nil {
						err = sErr
					}
				}
			}
		}
		logger.InfoMsg("Shutdown complete")
		structure.Sync(kern.Logger.Info)
		structure.Sync(kern.Logger.Trace)
		time.Sleep(CooldownTime)
		close(kern.shutdownNotify)
	})
	return
}
func ( kern * Kernel ) Shutdown ( ctx context . Context ) ( err error ) { kern . shutdownOnce . Do ( func ( ) { logger := kern . Logger . WithScope ( " " ) logger . InfoMsg ( " " ) logger . InfoMsg ( " " ) ctx , cancel := context . WithTimeout ( ctx , ServerShutdownTimeout ) defer cancel ( ) for i := len ( kern . Launchers ) - 1 ; i >= 0 ; i -- { name := kern . Launchers [ i ] . Name srvr , ok := kern . processes [ name ] if ok { logger . InfoMsg ( " " , " " , name ) sErr := srvr . Shutdown ( ctx ) if sErr != nil { logger . InfoMsg ( " " , " " , name , structure . ErrorKey , sErr ) if err == nil { err = sErr } } } } logger . InfoMsg ( " " ) structure . Sync ( kern . Logger . Info ) structure . Sync ( kern . Logger . Trace ) time . Sleep ( CooldownTime ) close ( kern . shutdownNotify ) } ) return }
Stop the kernel allowing for a graceful shutdown of components in order
Stop the kernel allowing for a graceful shutdown of components in order
// Shutdown servers in reverse order to boot // We don't want to wait for them, but yielding for a cooldown Let other goroutines flush // potentially interesting final output (e.g. log messages)