Home

Awesome

Banner

简体中文版

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.

Major Features

Getting Started

go install github.com/edwingeng/hotswap/cli/hotswap@latest

Build a Plugin from Source Code

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

Demos

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.

  1. 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.
  2. extension shows how to define a custom extension and how to use PluginManager.Vault.Extension. A small hint: WithExtensionNewer()
  3. livex is somewhat complex. It shows how to work with live function, live type, and live data.
  4. slink is an example of plugin static-linking, with which debugging a plugin with a debugger (delve) under MacOS and Windows becomes possible.
  5. trine is the last example. It demonstrates the plugin dependency mechanism.

Required Functions

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
}

Order of Execution during Plugin Reload

1. Reloadable
2. Export
3. Import
4. OnLoad
5. Vault Initialization
6. OnInit

Attentions

Live Things

func live_Foo(jobData live.Data) error {
      return nil
}
type Live_Bar struct {
      N int
}

FAQ

Build it with --staticLink. For more information, please refer to the demo slink.

Building with --staticLink works on Windows, but plugin reloading is not an option because Go's plugin mechanism doesn't support Windows.

 <br/>  <br/>  <br/>  <br/>  <br/>  <br/>  <br/>  <br/>  <br/>  <br/>  <br/>  <br/>  <br/>  <br/>  <br/>  <br/>  <br/>  <br/>  <br/>  <br/>