# Multi-services

# Introduction

Sometimes you need to run several services in the same executable. For example if you are also listening to a message queue on top of running your web API. Goyave can be run in a goroutine and stopped on-demand.

All functions below are features that require the goyave package to be imported.

import "goyave.dev/goyave/v4"

# Startup hooks

Startup hooks are functions executed in a goroutine after the server finished initializing. This is especially useful when you want to start other services or execute specific commands while being sure the server is up and running, ready to respond to incoming requests. Startup hooks must be registered before the goyave.Start() call.

# goyave.RegisterStartupHook

Register a startup hook to execute some code once the server is ready and running.

Parameters Return
hook func() void

Example:

goyave.RegisterStartupHook(func() {
    goyave.Logger.Println("Server ready.")
})

# goyave.ClearStartupHooks

Clear all registered startup hooks. Useful when you are writing tests or developing a service able to restart your server multiple times.

Parameters Return
void

Example:

goyave.ClearStartupHooks()

# Shutdown hooks

Shutdown hooks are functions executed when the server stops. This is especially useful when you want to stop other services when the server stops.

WARNING

Bear in mind that shutdown hooks are blocking operations during the shutdown process and there is no timeout mechanism. It is your responsibility that your code doesn't end up deadlocking.

# goyave.RegisterShutdownHook

Register a shutdown hook to execute some code after the server stopped. Shutdown hooks are executed before goyave.Start() returns.

Parameters Return
hook func() void

Example:

goyave.RegisterShutdownHook(func() {
    goyave.Logger.Println("Server shutdown.")
})

# goyave.ClearShutdownHooks

Clear all registered shutdown hooks. Useful when you are writing tests or developing a service able to restart your server multiple times.

Parameters Return
void

Example:

goyave.ClearShutdownHooks()

# Start the server

# goyave.Start

Starts the server. This functions needs a route registrer function as a parameter. Learn more in the routing section.
The configuration is not reloaded if you call Start multiple times. You can still reload the configuration with config.Load() if you need it. This operation is blocking. Triggers a panic if the server is already running. Errors returned can be safely type-asserted to *goyave.Error.

Parameters Return
routeRegistrer func(*goyave.Router) error

Examples:

if err := goyave.Start(route.Register); err != nil {
    os.Exit(err.(*goyave.Error).ExitCode)
}

Running the server in the background:

You can start the server in a goroutine. However, if you do this and the main goroutine terminates, the server will not shutdown gracefully and the program will exit right away. Be sure to call goyave.Stop() to stop the server gracefully before exiting. Learn more in the next section.

go goyave.Start(route.Register)
//...
goyave.Stop()

# Errors

Errors generated byt the server itself (when calling Start()) are wrapped into an instance of *goyave.Error. This struct contains an exit code and the original error.

type Error struct {
	ExitCode int
	Err      error
}

Exit codes:

  • 2: Panic (server already running, error when loading language files, etc)
  • 3: Configuration is invalid
  • 4: An error occurred when opening network listener
  • 5: An error occurred in the HTTP server

# Stop the server

When the running process receives a SIGINT or a SIGTERM signal, for example when you press CTRL+C to interrupt the program, the server will shutdown gracefully, so you don't have to handle that yourself.

However, if you start the server in a goroutine, you have the responsibility to shutdown properly. If you exit the program manually or if the main goroutine terminates, ensure that goyave.Stop() is called. If the program exits because of an interruption signal, the server will shutdown gracefully.

# goyave.Stop

Stop the server gracefully without interrupting any active connections. Make sure the program doesn't exit and waits instead for Stop to return.

Stop does not attempt to close nor wait for hijacked connections such as WebSockets. The caller of Stop should separately notify such long-lived connections of shutdown and wait for them to close, if desired.

Parameters Return
void

Examples:

goyave.Stop()

# Server status

The goyave.IsReady() function lets you know if the server is running or not.

This function should not be used to wait for the server to be ready. Use a startup hook instead.

# goyave.IsReady

Returns true if the server is ready to receive and serve incoming requests.

Parameters Return
bool

Example:

if goyave.IsReady() {
    goyave.Logger.Println("Server is ready")
}

# Maintenance mode

Since v2.1.0

On top of being able to start the server in maintenance mode using the maintenance configuration entry, you can enable and disable this mode at runtime.

# goyave.EnableMaintenance

Replace the main server handler with the "Service Unavailable" handler.

Parameters Return
void

Example:

goyave.EnableMaintenance()

# goyave.DisableMaintenance

Replace the main server handler with the original router.

Parameters Return
void

Example:

goyave.DisableMaintenance()

# goyave.IsMaintenanceEnabled

Returns true if the server is currently in maintenance mode.

Parameters Return
bool

Example:

fmt.Println(goyave.IsMaintenanceEnabled()) // false