mirror of
https://github.com/foomo/gofuncy.git
synced 2026-04-14 17:24:33 +00:00
main
Some checks failed
Test Branch / test (push) Has been cancelled
feat: make name conditionally and add helpers
gofuncy
Stop using
go func, start usinggofuncy!
Context-aware, observable goroutine management with built-in resilience patterns.
Features
- Context propagation with routine name and parent chain
- Automatic panic recovery
- Built-in telemetry (metrics and tracing via OpenTelemetry)
- Resilience: retry with exponential backoff, circuit breaker, fallback
- Concurrency control via semaphores and group limits
- Stall detection
Installation
go get github.com/foomo/gofuncy
Quick Start
ctx := gofuncy.Ctx(context.Background()).Root()
// Fire-and-forget goroutine
gofuncy.Go(ctx, func(ctx context.Context) error {
return doWork(ctx)
})
// Synchronous execution with middleware chain
err := gofuncy.Do(ctx, fetchData)
// Goroutine with wait
wait := gofuncy.Wait(ctx, processItems)
// ... do other work ...
err := wait()
Core API
Every function wraps a gofuncy.Func:
type Func func(ctx context.Context) error
| Function | Description |
|---|---|
Go(ctx, fn, ...GoOption) |
Fire-and-forget goroutine with error logging |
Start(ctx, fn, ...GoOption) |
Like Go, blocks until the goroutine is running |
StartWithReady(ctx, fn, ...GoOption) |
Like Go, blocks until fn signals readiness |
StartWithStop(ctx, fn, ...GoOption) |
Like Go, goroutine receives a stop function to cancel itself |
GoWithCancel(ctx, fn, ...GoOption) |
Like Go, returns a stop function |
Do(ctx, fn, ...GoOption) |
Synchronous execution, returns error directly |
Wait(ctx, fn, ...GoOption) |
Goroutine that returns a wait function |
WaitWithStop(ctx, fn, ...GoOption) |
Like Wait, goroutine receives a stop function |
WaitWithReady(ctx, fn, ...GoOption) |
Like Wait, blocks until fn signals readiness |
NewGroup(ctx, ...GroupOption) |
Concurrent group with shared lifecycle |
All(ctx, items, fn, ...GroupOption) |
Execute fn for each item concurrently |
Map(ctx, items, fn, ...GroupOption) |
Transform items concurrently, preserving order |
Options
// Naming (optional)
gofuncy.WithName("my-routine")
// Resilience
gofuncy.WithTimeout(5 * time.Second)
gofuncy.WithRetry(3)
gofuncy.WithCircuitBreaker(cb)
gofuncy.WithFallback(fallbackFn)
// Concurrency
gofuncy.WithLimit(10) // Group only
gofuncy.WithLimiter(sem) // Shared semaphore
// Telemetry (on by default, opt-out)
gofuncy.WithoutTracing()
gofuncy.WithoutStartedCounter()
gofuncy.WithoutErrorCounter()
gofuncy.WithoutActiveUpDownCounter()
gofuncy.WithDurationHistogram() // opt-in
Telemetry
Metrics (all via OpenTelemetry):
| Name | Type | Default |
|---|---|---|
gofuncy.goroutines.started |
Counter | on |
gofuncy.goroutines.errors |
Counter | on |
gofuncy.goroutines.active |
UpDownCounter | on |
gofuncy.goroutines.stalled |
Counter | on |
gofuncy.goroutines.duration.seconds |
Histogram | off |
gofuncy.groups.duration.seconds |
Histogram | off |
Channel
The channel subpackage provides a generic, observable channel:
import "github.com/foomo/gofuncy/channel"
ch := channel.New[string](channel.WithBuffer[string](100))
defer ch.Close()
ch.Send(ctx, "hello", "world")
for msg := range ch.Receive() {
fmt.Println(msg)
}
Channel metrics:
| Name | Type | Default |
|---|---|---|
gofuncy.chans.current |
UpDownCounter | on |
gofuncy.messages.sent |
Counter | on |
gofuncy.messages.duration.seconds |
Histogram | off |
How to Contribute
Contributions are welcome! Please read the contributing guide.
License
Distributed under MIT License, please see the license file within the code for more details.
Languages
Go
98.2%
Makefile
1.8%
