organism
organism copied to clipboard
Organism
Abstraction for liveness and readiness probes of your app
Description
We can describe each app as Organism, that consists of core and Limbs. Each Limb describes important part of your app, without which app can't work properly. If each Limb is ready to work, then the whole organism ready to work too (readiness probe). If at least one Limb is dead, then the whole organism is partially dead too.
Example
Let's take simple http handlers funcs, to answer on readiness and liveness probes
package main
import (
"github.com/citilinkru/organism"
"github.com/gorilla/mux"
"net/http"
"log"
)
func main() {
o := organism.New()
limb1 := o.GrowLimb()
go func() {
defer limb1.Die()
limb1.Ready()
err := DoSmtValuable()
if err != nil {
log.Println("something wrong with 1: ", err)
}
}()
limb2 := o.GrowLimb()
go func() {
defer limb2.Die()
limb2.Ready()
err := DoAnotherValuable()
if err != nil {
log.Println("something wrong with 2: ", err)
}
}()
o.Ready()
// ...
r := mux.NewRouter()
r.HandleFunc("/healty", ReadinessHandler(o))
r.HandleFunc("/healtz", LivenessHandler(o))
http.Handle("/", r)
// ...
}
func LivenessHandler(o *organism.Organism) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
if !o.IsAlive() {
return
}
_, err := writer.Write([]byte("OK"))
if err != nil {
writer.WriteHeader(http.StatusInternalServerError)
}
}
}
func ReadinessHandler(o *organism.Organism) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
if !o.IsReady() {
return
}
_, err := writer.Write([]byte("OK"))
if err != nil {
writer.WriteHeader(http.StatusInternalServerError)
}
}
}
Testing
Unit-tests:
go test -v -race ./...
Run linter:
go mod vendor \
&& docker run --rm -v $(pwd):/app -w /app golangci/golangci-lint:v1.40 golangci-lint run -v \
&& rm -R vendor
CONTRIBUTE
- write code
- run
go fmt ./...
- run all linters and tests (see above)
- create a PR describing the changes
LICENSE
MIT
AUTHOR
Nikita Sapogov [email protected]