Garr - Go libs in a Jar
Collection of high performance, thread-safe, lock-free go data structures.
- adder - Data structure to perform highly-performant sum under high contention. Inspired by OpenJDK LongAdder
- circuit-breaker - Data structure to implement circuit breaker pattern to detect remote service failure/alive status.
- queue - Queue data structure, go implementation of
JDKLinkedQueue
andMutexLinkedQueue
fromOpenJDK
. - retry - Controls backoff between attempts in a retry operation.
- worker-pool - Worker pool implementation in go to help perform multiple tasks concurrently with a fixed-but-expandable amount of workers.
Usage
Getting started
go get -u go.linecorp.com/garr
Examples
Please find detailed examples in each sub-package.
Adder
package main
import (
"fmt"
"time"
ga "go.linecorp.com/garr/adder"
)
func main() {
// or ga.DefaultAdder() which uses jdk long-adder as default
adder := ga.NewLongAdder(ga.JDKAdderType)
for i := 0; i < 100; i++ {
go func() {
adder.Add(123)
}()
}
time.Sleep(3 * time.Second)
// get total added value
fmt.Println(adder.Sum())
}
Build your own Prometheus counter with Adder
package prom
import (
ga "go.linecorp.com/garr/adder"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
)
// NewCounterI64 creates a new CounterI64 based on the provided prometheus.CounterOpts.
func NewCounterI64(opts prometheus.CounterOpts) CounterI64 {
return CounterI64{counter: prometheus.NewCounter(opts)}
}
// CounterI64 is optimized Prometheus Counter for int64 value type.
type CounterI64 struct {
val ga.JDKAdder
counter prometheus.Counter
}
// Value returns current value.
func (c *CounterI64) Value() int64 {
return c.val.Sum()
}
// Reset value.
func (c *CounterI64) Reset() {
c.val.Reset()
}
// Desc returns metric desc.
func (c *CounterI64) Desc() *prometheus.Desc {
return c.counter.Desc()
}
// Inc by 1.
func (c *CounterI64) Inc() {
c.val.Add(1)
}
// Add by variant.
func (c *CounterI64) Add(val int64) {
if val > 0 {
c.val.Add(val)
}
}
// Write implements prometheus.Metric interface.
func (c *CounterI64) Write(out *dto.Metric) (err error) {
if err = c.counter.Write(out); err == nil {
value := float64(c.val.Sum())
out.Counter.Value = &value
}
return
}
// Collect implements prometheus.Collector interface.
func (c *CounterI64) Collect(ch chan<- prometheus.Metric) {
ch <- c
}
// Describe implements prometheus.Collector interface.
func (c *CounterI64) Describe(ch chan<- *prometheus.Desc) {
ch <- c.counter.Desc()
}
Queue
package main
import (
"fmt"
"go.linecorp.com/garr/queue"
)
func main() {
q := queue.DefaultQueue() // default using jdk linked queue
// push
q.Offer(123)
// return head queue but not remove
head := q.Peek()
fmt.Println(head)
// remove and return head queue
polled := q.Poll()
fmt.Println(polled)
}
Circuit Breaker
package main
import (
cbreaker "go.linecorp.com/garr/circuit-breaker"
)
func makeRequest() error {
return nil
}
func main() {
cb := cbreaker.NewCircuitBreakerBuilder().
SetTicker(cbreaker.SystemTicker).
SetFailureRateThreshold(validFailureRateThreshold).
Build()
if cb.CanRequest() {
err := makeRequest()
if err != nil {
cb.OnFailure()
} else {
cb.OnSuccess()
}
}
}