Documentation
ΒΆ
Index ΒΆ
- Variables
- func GetJSON[T any](c *Client, ctx context.Context, url string) (T, error)
- func Permanent(err error) error
- func PostJSON[T any](c *Client, ctx context.Context, url string, body any) (T, error)
- type Backoff
- type BulkheadConfig
- type BulkheadPolicy
- type CircuitBreakerPolicy
- func (cb *CircuitBreakerPolicy) Execute(ctx context.Context, req *http.Request, next PolicyFunc) (*http.Response, error)
- func (cb *CircuitBreakerPolicy) State() State
- func (cb *CircuitBreakerPolicy) WithHooks(h Hooks) *CircuitBreakerPolicy
- func (cb *CircuitBreakerPolicy) WithLogger(l *slog.Logger) *CircuitBreakerPolicy
- func (cb *CircuitBreakerPolicy) WithName(name string) *CircuitBreakerPolicy
- type CircuitConfig
- type Client
- func (c *Client) Close() error
- func (c *Client) Do(req *http.Request) (*http.Response, error)
- func (c *Client) DoWithContext(ctx context.Context, req *http.Request) (*http.Response, error)
- func (c *Client) Get(ctx context.Context, url string) (*http.Response, error)
- func (c *Client) HealthChecker() *HealthChecker
- func (c *Client) Post(ctx context.Context, url, contentType string, body io.Reader) (*http.Response, error)
- func (c *Client) RoundTrip(req *http.Request) (*http.Response, error)
- func (c *Client) Transport() http.RoundTripper
- type FallbackConfig
- type FallbackPolicy
- type HealthChecker
- type HealthStatus
- type Hooks
- type MemoryStats
- type MetricsRecorder
- type Option
- func AggressiveConfig() []Option
- func ConservativeConfig() []Option
- func DefaultConfig() []Option
- func ProductionConfig() []Option
- func WithBulkhead(cfg BulkheadConfig) Option
- func WithCircuitBreaker(cfg CircuitConfig) Option
- func WithDebug() Option
- func WithFallback(cfg FallbackConfig) Option
- func WithHTTPClient(hc *http.Client) Option
- func WithHooks(h Hooks) Option
- func WithLogger(l *slog.Logger) Option
- func WithMetrics(r MetricsRecorder) Option
- func WithPolicy(p Policy) Option
- func WithRateLimit(cfg RateLimitConfig) Option
- func WithRequestID(header string) Option
- func WithRequestIDPolicy(p *RequestIDPolicy) Option
- func WithRetry(cfg RetryConfig) Option
- func WithSingleflight() Option
- func WithTimeout(cfg TimeoutConfig) Option
- type PermanentError
- type Policy
- type PolicyFunc
- type RateLimitConfig
- type RateLimitPolicy
- type RequestError
- type RequestIDPolicy
- type RetryConfig
- type RetryPolicy
- type SingleflightConfig
- type SingleflightPolicy
- type State
- type TimeoutConfig
- type TimeoutPolicy
Examples ΒΆ
Constants ΒΆ
This section is empty.
Variables ΒΆ
var ( ErrCircuitOpen = errors.New("ambatukam: circuit breaker is open") ErrMaxRetries = errors.New("ambatukam: max retries exceeded") ErrNilRequest = errors.New("ambatukam: nil request") ErrTimeout = errors.New("ambatukam: per-attempt timeout exceeded") ErrBulkheadFull = errors.New("ambatukam: bulkhead full") ErrRateLimited = errors.New("ambatukam: rate limited") ErrFallback = errors.New("ambatukam: fallback failed") )
Functions ΒΆ
func GetJSON ΒΆ
Example ΒΆ
ExampleGetJSON demonstrates the typed JSON helper.
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
fmt.Fprint(w, `{"name":"alice","age":30}`)
}))
defer srv.Close()
client := ambatukam.New()
defer client.Close()
u, err := ambatukam.GetJSON[testUser](client, context.Background(), srv.URL)
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(u.Name, u.Age)
Output: alice 30
func Permanent ΒΆ
Example ΒΆ
ExamplePermanent demonstrates marking an error as non-retryable.
package main
import (
"errors"
"fmt"
"github.com/farhanturu/ambatukam-go"
)
func main() {
err := ambatukam.Permanent(errors.New("do not retry me"))
fmt.Println(err)
}
Output: permanent: do not retry me
func PostJSON ΒΆ
Example ΒΆ
ExamplePostJSON demonstrates the typed JSON POST helper.
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(201)
fmt.Fprint(w, `{"name":"bob","age":25}`)
}))
defer srv.Close()
client := ambatukam.New()
defer client.Close()
out, err := ambatukam.PostJSON[testUser](client, context.Background(), srv.URL, testUser{Name: "alice", Age: 30})
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(out.Name, out.Age)
Output: bob 25
Types ΒΆ
type BulkheadConfig ΒΆ
type BulkheadPolicy ΒΆ
type BulkheadPolicy struct {
// contains filtered or unexported fields
}
func NewBulkhead ΒΆ
func NewBulkhead(cfg BulkheadConfig) *BulkheadPolicy
Example ΒΆ
ExampleNewBulkhead demonstrates configuring a bulkhead.
package main
import (
"fmt"
"time"
"github.com/farhanturu/ambatukam-go"
)
func main() {
cfg := ambatukam.BulkheadConfig{
MaxConcurrent: 5,
MaxQueue: 10,
QueueTimeout: 100 * time.Millisecond,
}
client := ambatukam.New(ambatukam.WithBulkhead(cfg))
defer client.Close()
fmt.Println("max concurrent:", cfg.MaxConcurrent)
}
Output: max concurrent: 5
func (*BulkheadPolicy) Denied ΒΆ
func (b *BulkheadPolicy) Denied() uint64
func (*BulkheadPolicy) Execute ΒΆ
func (b *BulkheadPolicy) Execute(ctx context.Context, req *http.Request, next PolicyFunc) (*http.Response, error)
func (*BulkheadPolicy) InFlight ΒΆ
func (b *BulkheadPolicy) InFlight() uint32
func (*BulkheadPolicy) WithLogger ΒΆ
func (b *BulkheadPolicy) WithLogger(l *slog.Logger) *BulkheadPolicy
type CircuitBreakerPolicy ΒΆ
type CircuitBreakerPolicy struct {
// contains filtered or unexported fields
}
func NewCircuitBreaker ΒΆ
func NewCircuitBreaker(cfg CircuitConfig) *CircuitBreakerPolicy
Example ΒΆ
ExampleNewCircuitBreaker demonstrates configuring the circuit breaker.
package main
import (
"fmt"
"time"
"github.com/farhanturu/ambatukam-go"
)
func main() {
cfg := ambatukam.DefaultCircuitConfig()
cfg.FailureThreshold = 3
cfg.OpenDuration = 10 * time.Second
client := ambatukam.New(ambatukam.WithCircuitBreaker(cfg))
defer client.Close()
fmt.Println("failure threshold:", cfg.FailureThreshold)
}
Output: failure threshold: 3
func (*CircuitBreakerPolicy) Execute ΒΆ
func (cb *CircuitBreakerPolicy) Execute(ctx context.Context, req *http.Request, next PolicyFunc) (*http.Response, error)
func (*CircuitBreakerPolicy) State ΒΆ
func (cb *CircuitBreakerPolicy) State() State
func (*CircuitBreakerPolicy) WithHooks ΒΆ
func (cb *CircuitBreakerPolicy) WithHooks(h Hooks) *CircuitBreakerPolicy
func (*CircuitBreakerPolicy) WithLogger ΒΆ
func (cb *CircuitBreakerPolicy) WithLogger(l *slog.Logger) *CircuitBreakerPolicy
func (*CircuitBreakerPolicy) WithName ΒΆ
func (cb *CircuitBreakerPolicy) WithName(name string) *CircuitBreakerPolicy
type CircuitConfig ΒΆ
type CircuitConfig struct {
FailureThreshold uint32
OpenDuration time.Duration
HalfOpenMaxReqs uint32
ShouldTrip func(resp *http.Response, err error) bool
}
func DefaultCircuitConfig ΒΆ
func DefaultCircuitConfig() CircuitConfig
type Client ΒΆ
type Client struct {
// contains filtered or unexported fields
}
func NewDefaultClient ΒΆ
func NewDefaultClient() *Client
Example ΒΆ
ExampleNewDefaultClient demonstrates the one-call production-default client.
package main
import (
"fmt"
"github.com/farhanturu/ambatukam-go"
)
func main() {
client := ambatukam.NewDefaultClient()
defer client.Close()
fmt.Println("ok")
}
Output: ok
func (*Client) DoWithContext ΒΆ
func (*Client) Get ΒΆ
Example ΒΆ
ExampleClient_Get demonstrates a basic GET request with all three policies.
package main
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"time"
"github.com/farhanturu/ambatukam-go"
)
func main() {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, `{"hello":"world"}`)
}))
defer srv.Close()
client := ambatukam.New(
ambatukam.WithTimeout(ambatukam.TimeoutConfig{Timeout: 2 * time.Second}),
ambatukam.WithRetry(ambatukam.DefaultRetryConfig()),
ambatukam.WithCircuitBreaker(ambatukam.DefaultCircuitConfig()),
)
defer client.Close()
resp, err := client.Get(context.Background(), srv.URL)
if err != nil {
fmt.Println("error:", err)
return
}
defer resp.Body.Close()
fmt.Println("status:", resp.StatusCode)
}
Output: status: 200
func (*Client) HealthChecker ΒΆ added in v1.1.0
func (c *Client) HealthChecker() *HealthChecker
func (*Client) Post ΒΆ
func (c *Client) Post(ctx context.Context, url, contentType string, body io.Reader) (*http.Response, error)
Example ΒΆ
ExampleClient_Post demonstrates a POST with a JSON body.
package main
import (
"context"
"fmt"
"io"
"net/http"
"net/http/httptest"
"strings"
"github.com/farhanturu/ambatukam-go"
)
func main() {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
fmt.Println("server received:", string(body))
w.WriteHeader(http.StatusCreated)
}))
defer srv.Close()
client := ambatukam.New()
defer client.Close()
resp, err := client.Post(
context.Background(),
srv.URL+"/users",
"application/json",
io.NopCloser(strings.NewReader(`{"name":"alice"}`)),
)
if err != nil {
fmt.Println("error:", err)
return
}
defer resp.Body.Close()
fmt.Println("status:", resp.StatusCode)
}
Output: server received: {"name":"alice"} status: 201
func (*Client) RoundTrip ΒΆ
Example ΒΆ
ExampleClient_RoundTrip shows how to use an amba *Client as the Transport of a standard *http.Client.
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/farhanturu/ambatukam-go"
)
func main() {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
}))
defer srv.Close()
amba := ambatukam.New(ambatukam.WithRetry(ambatukam.RetryConfig{MaxRetries: 2}))
defer amba.Close()
hc := &http.Client{Transport: amba.Transport()}
resp, err := hc.Get(srv.URL)
if err != nil {
fmt.Println("error:", err)
return
}
defer resp.Body.Close()
fmt.Println("status:", resp.StatusCode)
}
Output: status: 200
func (*Client) Transport ΒΆ
func (c *Client) Transport() http.RoundTripper
type FallbackConfig ΒΆ added in v1.1.0
type FallbackPolicy ΒΆ added in v1.1.0
type FallbackPolicy struct {
// contains filtered or unexported fields
}
func NewFallback ΒΆ added in v1.1.0
func NewFallback(cfg FallbackConfig) *FallbackPolicy
func (*FallbackPolicy) Execute ΒΆ added in v1.1.0
func (f *FallbackPolicy) Execute(ctx context.Context, req *http.Request, next PolicyFunc) (*http.Response, error)
func (*FallbackPolicy) WithHooks ΒΆ added in v1.1.0
func (f *FallbackPolicy) WithHooks(h Hooks) *FallbackPolicy
type HealthChecker ΒΆ added in v1.1.0
type HealthChecker struct {
// contains filtered or unexported fields
}
func NewHealthChecker ΒΆ added in v1.1.0
func NewHealthChecker(c *Client) *HealthChecker
func (*HealthChecker) Handler ΒΆ added in v1.1.0
func (h *HealthChecker) Handler() http.HandlerFunc
type HealthStatus ΒΆ added in v1.1.0
type MemoryStats ΒΆ added in v1.1.0
type MetricsRecorder ΒΆ added in v1.1.0
type MetricsRecorder interface {
RecordRequest(method, url string, status int, duration time.Duration)
RecordRetry(method, url string, attempt int)
RecordCircuitStateChange(name string, from, to State)
RecordBulkheadDenied(method, url string)
RecordRateLimitDenied(method, url string)
RecordFallback(method, url string)
RecordTimeout(method, url string)
}
func NewNoopMetricsRecorder ΒΆ added in v1.1.0
func NewNoopMetricsRecorder() MetricsRecorder
type Option ΒΆ
type Option func(*Client)
func AggressiveConfig ΒΆ
func AggressiveConfig() []Option
func ConservativeConfig ΒΆ
func ConservativeConfig() []Option
func DefaultConfig ΒΆ
func DefaultConfig() []Option
func ProductionConfig ΒΆ
func ProductionConfig() []Option
func WithBulkhead ΒΆ
func WithBulkhead(cfg BulkheadConfig) Option
func WithCircuitBreaker ΒΆ
func WithCircuitBreaker(cfg CircuitConfig) Option
func WithFallback ΒΆ added in v1.1.0
func WithFallback(cfg FallbackConfig) Option
func WithHTTPClient ΒΆ
Example ΒΆ
ExampleWithHTTPClient demonstrates swapping in a custom *http.Client.
package main
import (
"fmt"
"net/http"
"time"
"github.com/farhanturu/ambatukam-go"
)
func main() {
client := ambatukam.New(
ambatukam.WithHTTPClient(&http.Client{Timeout: 5 * time.Second}),
)
defer client.Close()
fmt.Println("custom http.Client")
}
Output: custom http.Client
func WithLogger ΒΆ
func WithMetrics ΒΆ added in v1.1.0
func WithMetrics(r MetricsRecorder) Option
func WithPolicy ΒΆ
func WithRateLimit ΒΆ
func WithRateLimit(cfg RateLimitConfig) Option
func WithRequestID ΒΆ
func WithRequestIDPolicy ΒΆ
func WithRequestIDPolicy(p *RequestIDPolicy) Option
func WithRetry ΒΆ
func WithRetry(cfg RetryConfig) Option
func WithSingleflight ΒΆ added in v1.1.0
func WithSingleflight() Option
func WithTimeout ΒΆ
func WithTimeout(cfg TimeoutConfig) Option
type PermanentError ΒΆ
type PermanentError struct{ Err error }
func (*PermanentError) Error ΒΆ
func (e *PermanentError) Error() string
func (*PermanentError) Unwrap ΒΆ
func (e *PermanentError) Unwrap() error
type Policy ΒΆ
type Policy interface {
Execute(ctx context.Context, req *http.Request, next PolicyFunc) (*http.Response, error)
}
func Chain ΒΆ
Example ΒΆ
ExampleChain demonstrates manual composition of policies.
package main
import (
"fmt"
"time"
"github.com/farhanturu/ambatukam-go"
)
func main() {
client := ambatukam.New(ambatukam.WithPolicy(ambatukam.Chain(
ambatukam.NewTimeout(ambatukam.TimeoutConfig{Timeout: 2 * time.Second}),
ambatukam.NewRetry(ambatukam.DefaultRetryConfig()),
ambatukam.NewCircuitBreaker(ambatukam.DefaultCircuitConfig()),
)))
defer client.Close()
fmt.Println("chained: ok")
}
Output: chained: ok
type PolicyFunc ΒΆ
type RateLimitConfig ΒΆ
type RateLimitPolicy ΒΆ
type RateLimitPolicy struct {
// contains filtered or unexported fields
}
func NewRateLimit ΒΆ
func NewRateLimit(cfg RateLimitConfig) *RateLimitPolicy
Example ΒΆ
ExampleNewRateLimit demonstrates building a rate-limit policy directly.
package main
import (
"fmt"
"github.com/farhanturu/ambatukam-go"
)
func main() {
client := ambatukam.New(ambatukam.WithRateLimit(ambatukam.RateLimitConfig{
Rate: 10,
Burst: 5,
}))
defer client.Close()
fmt.Println("rate limited client ready")
}
Output: rate limited client ready
func (*RateLimitPolicy) Execute ΒΆ
func (r *RateLimitPolicy) Execute(ctx context.Context, req *http.Request, next PolicyFunc) (*http.Response, error)
func (*RateLimitPolicy) WithLogger ΒΆ
func (r *RateLimitPolicy) WithLogger(l *slog.Logger) *RateLimitPolicy
type RequestError ΒΆ
type RequestError struct {
Method string
URL string
Status int
Attempts int
Policy string
Err error
}
func (*RequestError) Error ΒΆ
func (e *RequestError) Error() string
func (*RequestError) Unwrap ΒΆ
func (e *RequestError) Unwrap() error
type RequestIDPolicy ΒΆ
type RequestIDPolicy struct {
// contains filtered or unexported fields
}
func NewRequestIDPolicy ΒΆ
func NewRequestIDPolicy() *RequestIDPolicy
Example ΒΆ
ExampleNewRequestIDPolicy demonstrates registering a request-ID policy.
package main
import (
"fmt"
"github.com/farhanturu/ambatukam-go"
)
func main() {
client := ambatukam.New(ambatukam.WithRequestIDPolicy(ambatukam.NewRequestIDPolicy()))
defer client.Close()
fmt.Println("request ID policy enabled")
}
Output: request ID policy enabled
func (*RequestIDPolicy) Execute ΒΆ
func (r *RequestIDPolicy) Execute(ctx context.Context, req *http.Request, next PolicyFunc) (*http.Response, error)
func (*RequestIDPolicy) WithGenerator ΒΆ
func (r *RequestIDPolicy) WithGenerator(gen func() string) *RequestIDPolicy
func (*RequestIDPolicy) WithHeader ΒΆ
func (r *RequestIDPolicy) WithHeader(name string) *RequestIDPolicy
type RetryConfig ΒΆ
type RetryConfig struct {
MaxRetries int
InitialBackoff time.Duration
MaxBackoff time.Duration
Multiplier float64
Jitter float64
Backoff Backoff
ShouldRetry func(resp *http.Response, err error) bool
}
func DefaultRetryConfig ΒΆ
func DefaultRetryConfig() RetryConfig
type RetryPolicy ΒΆ
type RetryPolicy struct {
// contains filtered or unexported fields
}
func NewRetry ΒΆ
func NewRetry(cfg RetryConfig) *RetryPolicy
Example ΒΆ
ExampleNewRetry demonstrates configuring the retry policy.
package main
import (
"fmt"
"time"
"github.com/farhanturu/ambatukam-go"
)
func main() {
cfg := ambatukam.DefaultRetryConfig()
cfg.MaxRetries = 5
cfg.Backoff = ambatukam.ExponentialBackoff(50*time.Millisecond, time.Second, 2.0)
client := ambatukam.New(ambatukam.WithRetry(cfg))
defer client.Close()
fmt.Println("max retries:", cfg.MaxRetries)
}
Output: max retries: 5
func (*RetryPolicy) Execute ΒΆ
func (r *RetryPolicy) Execute(ctx context.Context, req *http.Request, next PolicyFunc) (*http.Response, error)
func (*RetryPolicy) WithHooks ΒΆ
func (r *RetryPolicy) WithHooks(h Hooks) *RetryPolicy
func (*RetryPolicy) WithLogger ΒΆ
func (r *RetryPolicy) WithLogger(l *slog.Logger) *RetryPolicy
type SingleflightConfig ΒΆ added in v1.1.0
type SingleflightConfig struct {
Enabled bool
}
type SingleflightPolicy ΒΆ added in v1.1.0
type SingleflightPolicy struct {
// contains filtered or unexported fields
}
func NewSingleflight ΒΆ added in v1.1.0
func NewSingleflight() *SingleflightPolicy
type TimeoutConfig ΒΆ
type TimeoutPolicy ΒΆ
type TimeoutPolicy struct {
// contains filtered or unexported fields
}
func NewTimeout ΒΆ
func NewTimeout(cfg TimeoutConfig) *TimeoutPolicy
Example ΒΆ
ExampleNewTimeout demonstrates configuring the per-attempt timeout.
package main
import (
"fmt"
"time"
"github.com/farhanturu/ambatukam-go"
)
func main() {
client := ambatukam.New(
ambatukam.WithTimeout(ambatukam.TimeoutConfig{Timeout: 500 * time.Millisecond}),
)
defer client.Close()
fmt.Println("timeout: ok")
}
Output: timeout: ok