A complete solution to reload your go code without restarting your server, interrupting or blocking any ongoing procedure.
Hotswap
provides you a complete solution to reload your go
code without restarting your server, interrupting or blocking any ongoing procedure. Hotswap
is built upon the plugin mechanism.
Plugin.InvokeFunc()
PluginManager.Vault.Extension
and/or PluginManager.Vault.DataBag
live function
, live type
, and live data
Export()
Import()
go install github.com/edwingeng/hotswap/cli/hotswap@latest
Usage:
hotswap build [flags] <pluginDir> <outputDir> -- [buildFlags]
Examples:
hotswap build plugin/foo bin
hotswap build -v plugin/foo bin -- -race
hotswap build --staticLinking plugin/foo plugin
Flags:
--debug enable debug mode
--exclude string go-regexp matching files to exclude from included
--goBuild if --goBuild=false, skip the go build procedure (default true)
-h, --help help for build
--include string go-regexp matching files to include in addition to .go files
--leaveTemps do not delete temporary files
--livePrefix string case-insensitive name prefix of live functions and live types (default "live_")
--staticLinking generate code for static linking instead of building a plugin
-v, --verbose enable verbose mode
You can find these examples under the demo
directory. To have a direct experience, start a server with run.sh
and reload its plugin(s) with reload.sh
.
hello
demonstrates the basic usage, including how to organize host and plugin, how to build them, how to load plugin on server startup, how to use InvokeEach
, and how to reload.extension
shows how to define a custom extension and how to use PluginManager.Vault.Extension
. A small hint: WithExtensionNewer()
livex
is somewhat complex. It shows how to work with live function
, live type
, and live data
.slink
is an example of plugin static-linking, with which debugging a plugin with a debugger (delve) under MacOS and Windows becomes possible.trine
is the last example. It demonstrates the plugin dependency mechanism.A plugin must have the following functions defined in its root package.
// OnLoad gets called after all plugins are successfully loaded and before the Vault is initialized.
func OnLoad(data interface{}) error {
return nil
}
// OnInit gets called after the execution of all OnLoad functions. The Vault is ready now.
func OnInit(sharedVault *vault.Vault) error {
return nil
}
// OnFree gets called at some time after a reload.
func OnFree() {
}
// Export returns an object to export to other plugins.
func Export() interface{} {
return nil
}
// Import returns an object indicating the dependencies of the plugin.
func Import() interface{} {
return nil
}
// InvokeFunc invokes the specified function.
func InvokeFunc(name string, params ...interface{}) (interface{}, error) {
return nil, nil
}
// Reloadable indicates whether the plugin is reloadable.
func Reloadable() bool {
return true
}
1. Reloadable
2. Export
3. Import
4. OnLoad
5. Vault Initialization
6. OnInit
CGO_ENABLED=1
and the -trimpath
flag.live function
, live type
, and live data
to avoid the trap.Hotswap
offers you a chance, the OnFree
function, to clear caches.git
and go module
.live function
is a type of function whose name is prefixed with live_
(case-insensitive). Live functions are automatically collected and stored in PluginManager.Vault.LiveFuncs
. For example:func live_Foo(jobData live.Data) error {
return nil
}
live type
is a type of struct whose name is prefixed with live_
(case-insensitive). Live types are automatically collected and stored in PluginManager.Vault.LiveTypes
. For example:type Live_Bar struct {
N int
}
live data
is a type guardian. You can convert your data into a live data
object when scheduling an asynchronous job and restore your data from the live data
object when handling the job.livex
for details.Build it with --staticLink
. For more information, please refer to the demo slink
.
hotswap
work on Windows?
Building with --staticLink
works on Windows, but plugin reloading is not an option because Go's plugin mechanism doesn't support Windows.