Hangar provides a local daemon for developing distributed Fly.io servers locally in Go.
Usage
To start the package at ./demo
in this repository, you can:
$ go get github.com/samthor/hangar/bin
$ go run github.com/samthor/hangar/bin -p github.com/samthor/hangar/demo
This starts a daemon with small number of machines all running in different 'regions'.
It performs basic load-balancing between them (with "the user" assumed to be in the 1st region), or respects the fly-prefer-region
header.
You can demonstrate having multiple jobs run with:
$ curl http://localhost:8080/info -H "fly-prefer-region: ams"
$ curl http://localhost:8080/info -H "fly-prefer-region: syd"
The code inside ./lib
helps provide a layer that hides local development vs. the real Fly deployed environment.
(It also works without either, but just provides sensible single-node defaults.)
You can use it in your code like:
import (
hangar "github.com/samthor/hangar/lib"
)
func main() {
// find out about ourselves
self := hangar.Self()
// do something with other instances
others, err := hangar.Discover(context.Background())
// serve on the local $PORT
log.Fatal(http.ListenAndServe(hangar.ListenPort(), nil))
}
Mount
Use StoragePath()
with a mounted path as a no-op in prod, but to get a local path in dev created under your home directory (in "~/.fly/hangar/").
This doesn't quite match Fly's semantics.
Extensions/TODOs
This has no knowledge of process groups.
In production, actively only discovers instances in the same process group—has no knowledge of them.
This currently runs Go packages, but really, it could run any command N times—Hangar just sets $PORT
and other environment variables.
Assumes that the processes under control stop after some time (does not kill it when idle).
Restarts on non-zero exit code (same as Fly).