-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial version. Added code, documentation and etc.
- Loading branch information
Showing
9 changed files
with
356 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
name: Test and coverage | ||
on: [push, pull_request] | ||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
with: | ||
fetch-depth: 2 | ||
- uses: actions/setup-go@v2 | ||
with: | ||
go-version: '1.13' | ||
- name: Run coverage | ||
run: go test -race -coverprofile=coverage.txt -covermode=atomic | ||
- name: Upload coverage to Codecov | ||
run: bash <(curl -s https://codecov.io/bash) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
name: golangci-lint | ||
on: | ||
push: | ||
pull_request: | ||
workflow_dispatch: | ||
jobs: | ||
golangci: | ||
strategy: | ||
matrix: | ||
go-version: [1.13, 1.14, 1.15, 1.16] | ||
name: lint | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/setup-go@v2 | ||
with: | ||
go-version: ${{ matrix.go-version }} | ||
- run: go mod vendor | ||
- name: golangci-lint | ||
uses: golangci/golangci-lint-action@v2 | ||
with: | ||
version: v1.40 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
name: test | ||
on: | ||
push: | ||
pull_request: | ||
workflow_dispatch: | ||
jobs: | ||
test: | ||
strategy: | ||
matrix: | ||
go-version: [1.13, 1.14, 1.15, 1.16] | ||
name: test | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: checkout | ||
uses: actions/checkout@v2 | ||
- uses: actions/setup-go@v2 | ||
with: | ||
go-version: ${{ matrix.go-version }} | ||
- name: run tests | ||
run: go test -json ./... > test.json | ||
- name: Annotate tests | ||
if: always() | ||
uses: guyarb/golang-test-annotations@v0.3.0 | ||
with: | ||
test-results: test.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
run: | ||
timeout: 5m | ||
modules-download-mode: vendor | ||
skip-files: | ||
- '.*_test.go' | ||
|
||
linters: | ||
enable: | ||
- prealloc | ||
- dogsled | ||
- exportloopref | ||
- unconvert | ||
- unparam | ||
- whitespace | ||
- bodyclose | ||
- gosec | ||
- asciicheck | ||
- depguard | ||
- errorlint | ||
- goconst | ||
- gocritic |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,118 @@ | ||
# organism | ||
# Organism | ||
|
||
![Lint](https://github.com/citilinkru/organism/actions/workflows/golangci-lint.yml/badge.svg?branch=master) | ||
![Tests](https://github.com/citilinkru/organism/actions/workflows/test.yml/badge.svg?branch=master) | ||
[![codecov](https://codecov.io/gh/citilinkru/organism/branch/master/graph/badge.svg)](https://codecov.io/gh/citilinkru/organism) | ||
[![Go Report Card](https://goreportcard.com/badge/github.com/citilinkru/organism)](https://goreportcard.com/report/github.com/citilinkru/organism) | ||
[![License](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/citilinkru/organism/blob/master/LICENSE) | ||
[![GoDoc](https://godoc.org/github.com/citilinkru/organism?status.svg)](https://godoc.org/github.com/citilinkru/organism) | ||
[![Release](https://img.shields.io/github/release/citilinkru/organism.svg?style=flat-square)](https://github.com/citilinkru/organism/releases/latest) | ||
|
||
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 | ||
|
||
```go | ||
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: | ||
```bash | ||
go test -v -race ./... | ||
``` | ||
|
||
Run linter: | ||
```bash | ||
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 <amstaffix@gmail.com> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module github.com/citilinkru/organism | ||
|
||
go 1.13 | ||
|
||
require github.com/stretchr/testify v1.7.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package organism | ||
|
||
// New create new organism | ||
func New() *Organism { | ||
o := &Organism{} | ||
o.core = o.GrowLimb() | ||
return o | ||
} | ||
|
||
// Organism is your application, it has core and limbs. Each Limb describes important part of your app, and if this part | ||
// is dead, then organism is partially dead too (liveness probe). If each Limb of Organism, and the core too, are ready | ||
// to work, then whole Organism ready too work too (readiness probe) | ||
type Organism struct { | ||
limbs []*Limb | ||
core *Limb | ||
} | ||
|
||
// GrowLimb grow new Limb for Organism and returns it | ||
func (o *Organism) GrowLimb() *Limb { | ||
limb := newLimb() | ||
o.limbs = append(o.limbs, limb) | ||
|
||
return limb | ||
} | ||
|
||
func (o *Organism) IsReady() bool { | ||
for _, l := range o.limbs { | ||
if !l.IsReady() { | ||
return false | ||
} | ||
} | ||
|
||
return true | ||
} | ||
|
||
func (o *Organism) IsAlive() bool { | ||
for _, l := range o.limbs { | ||
if !l.IsAlive() { | ||
return false | ||
} | ||
} | ||
|
||
return true | ||
} | ||
|
||
// Ready marks core of Organism as ready | ||
func (o *Organism) Ready() { | ||
o.core.Ready() | ||
} | ||
|
||
// Ready marks core of Organism as dead | ||
func (o *Organism) Die() { | ||
o.core.Die() | ||
} | ||
|
||
func newLimb() *Limb { | ||
return &Limb{isAlive: true} | ||
} | ||
|
||
type Limb struct { | ||
isReady bool | ||
isAlive bool | ||
} | ||
|
||
// Ready marks Limb as ready | ||
func (l *Limb) Ready() { | ||
l.isReady = true | ||
} | ||
|
||
// Die marks Limb as dead (not alive) | ||
func (l *Limb) Die() { | ||
l.isAlive = false | ||
} | ||
|
||
func (l *Limb) IsReady() bool { | ||
return l.isReady | ||
} | ||
|
||
func (l *Limb) IsAlive() bool { | ||
return l.isAlive | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package organism | ||
|
||
import ( | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
) | ||
|
||
func TestNewOrganism(t *testing.T) { | ||
o := New() | ||
assert.True(t, o.IsAlive()) | ||
assert.False(t, o.IsReady()) | ||
|
||
o.Ready() | ||
|
||
assert.True(t, o.IsReady()) | ||
|
||
o.Die() | ||
|
||
assert.False(t, o.IsAlive()) | ||
assert.True(t, o.IsReady()) | ||
} | ||
|
||
func TestOrganism_GrowLimb_One(t *testing.T) { | ||
o := New() | ||
limb := o.GrowLimb() | ||
|
||
assert.True(t, limb.IsAlive()) | ||
assert.False(t, limb.IsReady()) | ||
|
||
limb.Ready() | ||
|
||
assert.True(t, limb.IsAlive()) | ||
assert.True(t, limb.IsReady()) | ||
assert.True(t, o.IsAlive()) | ||
assert.False(t, o.IsReady()) | ||
|
||
o.Ready() | ||
|
||
assert.True(t, limb.IsAlive()) | ||
assert.True(t, limb.IsReady()) | ||
assert.True(t, o.IsAlive()) | ||
assert.True(t, o.IsReady()) | ||
|
||
limb.Die() | ||
|
||
assert.False(t, limb.IsAlive()) | ||
assert.True(t, limb.IsReady()) | ||
assert.False(t, o.IsAlive()) | ||
assert.True(t, o.IsReady()) | ||
|
||
o.Die() | ||
|
||
assert.False(t, limb.IsAlive()) | ||
assert.True(t, limb.IsReady()) | ||
assert.False(t, o.IsAlive()) | ||
assert.True(t, o.IsReady()) | ||
} |