{"id":34133087,"url":"https://github.com/marincor/gendure","last_synced_at":"2026-05-27T18:03:14.238Z","repository":{"id":323964774,"uuid":"1095412849","full_name":"Marincor/gendure","owner":"Marincor","description":"a Go library providing resilience patterns to make your services more robust and fault-tolerant. Built to endure failures with battle-tested patterns like Circuit Breaker and Exponential Backoff Retry.","archived":false,"fork":false,"pushed_at":"2025-11-25T03:16:22.000Z","size":37,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-17T12:03:20.111Z","etag":null,"topics":["circuit-breaker","fault-tolerance","go","golang","resilience","resilience-analysis","resilience-patterns","retry"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/marincor/gendure?utm_source=godoc","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Marincor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-13T02:41:05.000Z","updated_at":"2025-12-03T14:49:51.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Marincor/gendure","commit_stats":null,"previous_names":["marincor/gendure"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Marincor/gendure","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Marincor%2Fgendure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Marincor%2Fgendure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Marincor%2Fgendure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Marincor%2Fgendure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Marincor","download_url":"https://codeload.github.com/Marincor/gendure/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Marincor%2Fgendure/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33577636,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-27T02:00:06.184Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["circuit-breaker","fault-tolerance","go","golang","resilience","resilience-analysis","resilience-patterns","retry"],"created_at":"2025-12-15T01:04:01.172Z","updated_at":"2026-05-27T18:03:14.233Z","avatar_url":"https://github.com/Marincor.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Gendure\n\n\u003cimg src=\"https://iili.io/ffQcqS2.png\" alt=\"Gendure Logo\" width=\"100\"/\u003e\n\n**Gendure** is a Go library providing resilience patterns to make your services more robust and fault-tolerant. Built to endure failures with battle-tested patterns like Circuit Breaker and Exponential Backoff Retry.\n\n[![Go Version](https://img.shields.io/badge/Go-%3E%3D%201.18-blue)](https://go.dev/)\n[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)\n[![made-with-Go](https://img.shields.io/badge/Made%20with-Go-1f425f.svg)](https://go.dev/)\n[![GoDoc reference example](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/marincor/gendure)\n[![GoReportCard example](https://goreportcard.com/badge/github.com/nanomsg/mangos)](https://goreportcard.com/report/github.com/marincor/gendure)\n[![Gendure](https://github.com/marincor/gendure/actions/workflows/tests.yml/badge.svg)](https://github.com/marincor/gendure/actions/workflows/tests.yml)\n\n\n## Features\n\n- 🔌 **Circuit Breaker** - Prevent cascading failures by blocking requests to failing services\n- 🔄 **Exponential Backoff Retry** - Retry failed operations with intelligent delay strategies\n- 🎲 **Jitter Support** - Prevent thundering herd problems with randomized delays\n- 🧵 **Thread-Safe** - Safe for concurrent use across multiple goroutines\n- 📊 **Context-Aware** - Respect context cancellation and timeouts\n- 🔍 **Observable** - Built-in logging support for monitoring and debugging\n- 🎯 **Generic Types** - Type-safe implementations using Go generics\n\n## Installation\n\n```bash\ngo get github.com/marincor/gendure\n```\n\n## Quick Start\n\n### Circuit Breaker\n\nProtect your services from cascading failures by automatically opening the circuit when error thresholds are reached.\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"time\"\n    \n    \"github.com/marincor/gendure\"\n)\n\nfunc main() {\n    // Create a circuit breaker for string responses\n    cb := gendure.NewCircuitBreaker[string](\n        3,                    // failure threshold\n        30*time.Second,       // recovery timeout\n        nil,                  // optional logger\n    )\n    \n    ctx := context.Background()\n    \n    result, err := cb.Execute(\n        ctx,\n        // Primary operation\n        func() (string, error) {\n            return callExternalAPI()\n        },\n        // Fallback operation\n        func() (string, error) {\n            return \"cached response\", nil\n        },\n    )\n    \n    if err != nil {\n        fmt.Printf(\"Error: %v\\n\", err)\n    }\n    fmt.Printf(\"Result: %s\\n\", result)\n}\n```\n\n### Exponential Backoff Retry\n\nRetry failed operations with exponentially increasing delays and jitter to avoid overwhelming recovering services.\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"time\"\n    \n    \"github.com/marincor/gendure\"\n)\n\nfunc main() {\n    retry := gendure.NewExponentialBackoffRetry[string](\n        func() (string, error) {\n            return callUnreliableService()\n        },\n        100*time.Millisecond, // initial delay\n        5,                     // max retries\n        2,                     // multiplier (2^attempt)\n        3,                     // jitter up to 3 seconds\n        nil,                   // optional logger\n    )\n    \n    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\n    defer cancel()\n    \n    result, err := retry.Execute(ctx)\n    if err != nil {\n        fmt.Printf(\"All retries failed: %v\\n\", err)\n        return\n    }\n    \n    fmt.Printf(\"Success: %s\\n\", result)\n}\n```\n\n## Documentation\n\n### Circuit Breaker\n\nThe Circuit Breaker pattern prevents cascading failures by monitoring error rates and temporarily blocking requests when thresholds are exceeded.\n\n#### States\n\n- **Closed**: Normal operation, requests pass through\n- **Open**: Failure threshold exceeded, requests are blocked and fallback is used\n- **Half-Open**: Testing if service recovered, allows one request\n\n#### API\n\n```go\n// Create a new circuit breaker\nfunc NewCircuitBreaker[T any](\n    failureThreshold int32,     // failures before opening (default: 1)\n    recoveryTimeout time.Duration, // wait before testing recovery (default: 30s)\n    logger glogger.GLogger,      // optional logger\n) *circuitBreaker[T]\n\n// Execute with circuit breaker protection\nfunc (cb *circuitBreaker[T]) Execute(\n    ctx context.Context,\n    operation func() (T, error),  // primary operation\n    fallback func() (T, error),   // fallback when circuit is open\n) (T, error)\n\n// Get current state\nfunc (cb *circuitBreaker[T]) GetState() int32\n\n// Get current failure count\nfunc (cb *circuitBreaker[T]) GetCountFailure() int32\n\n// Manually reset the circuit breaker\nfunc (cb *circuitBreaker[T]) Reset()\n```\n\n#### Example: HTTP Client with Circuit Breaker\n\n```go\ntype APIClient struct {\n    cb *gendure.CircuitBreaker[*http.Response]\n}\n\nfunc NewAPIClient() *APIClient {\n    return \u0026APIClient{\n        cb: gendure.NewCircuitBreaker[*http.Response](\n            5,                // open after 5 failures\n            1*time.Minute,    // try recovery after 1 minute\n            nil,\n        ),\n    }\n}\n\nfunc (c *APIClient) Get(ctx context.Context, url string) (*http.Response, error) {\n    return c.cb.Execute(\n        ctx,\n        func() (*http.Response, error) {\n            return http.Get(url)\n        },\n        func() (*http.Response, error) {\n            // Return cached response or error\n            return nil, errors.New(\"circuit open: service unavailable\")\n        },\n    )\n}\n```\n\n### Exponential Backoff Retry\n\nThe Exponential Backoff Retry pattern retries failed operations with exponentially increasing delays, plus random jitter to prevent thundering herd.\n\n#### Delay Calculation\n\n```\ntotalDelay = initialDelay × (multiplier^attempt) + randomJitter\n```\n\nWhere `randomJitter` is a random value between 0 and `randomInt-1` seconds.\n\n#### API\n\n```go\n// Create a new exponential backoff retry\nfunc NewExponentialBackoffRetry[T any](\n    callback CallbackFunc[T],      // operation to retry\n    initialDelay time.Duration,    // base delay (default: 100ms)\n    maxRetries int,                // max attempts (default: 3)\n    multiplier int,                // growth factor (default: 2)\n    randomInt int,                 // jitter range in seconds (default: 1)\n    logger glogger.GLogger,        // optional logger\n) ExponentialBackoffRetry[T]\n\n// Execute with retry logic\nfunc (ebr ExponentialBackoffRetry[T]) Execute(\n    ctx context.Context,\n) (T, error)\n```\n\n#### Example: Database Connection with Retry\n\n```go\nfunc connectToDatabase(ctx context.Context) (*sql.DB, error) {\n    retry := gendure.NewExponentialBackoffRetry[*sql.DB](\n        func() (*sql.DB, error) {\n            return sql.Open(\"postgres\", connectionString)\n        },\n        500*time.Millisecond, // start with 500ms\n        5,                     // try 5 times\n        2,                     // double delay each time\n        2,                     // add 0-1s jitter\n        nil,\n    )\n    \n    return retry.Execute(ctx)\n}\n```\n\n#### Retry Timeline Example\n\nWith `initialDelay=100ms`, `multiplier=2`, `maxRetries=5`, `jitter=0-2s`:\n\n| Attempt | Base Delay | Jitter | Total Delay |\n|---------|-----------|--------|-------------|\n| 1       | 100ms     | 0-2s   | 100ms-2.1s  |\n| 2       | 200ms     | 0-2s   | 200ms-2.2s  |\n| 3       | 400ms     | 0-2s   | 400ms-2.4s  |\n| 4       | 800ms     | 0-2s   | 800ms-2.8s  |\n| 5       | 1600ms    | 0-2s   | 1.6s-3.6s   |\n\n## Combining Patterns\n\nCircuit Breaker and Retry work great together:\n\n```go\n// Circuit breaker protects the service\ncb := gendure.NewCircuitBreaker[string](3, 30*time.Second, nil)\n\n// Retry handles transient failures\nretry := gendure.NewExponentialBackoffRetry[string](\n    func() (string, error) {\n        return cb.Execute(\n            ctx,\n            func() (string, error) {\n                return callService()\n            },\n            func() (string, error) {\n                return \"\", errors.New(\"circuit open\")\n            },\n        )\n    },\n    100*time.Millisecond,\n    3,\n    2,\n    1,\n    nil,\n)\n\nresult, err := retry.Execute(ctx)\n```\n\n## Context Cancellation\n\nAll operations respect `context.Context` cancellation:\n\n```go\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\ndefer cancel()\n\n// Will stop immediately if context is cancelled\nresult, err := retry.Execute(ctx)\nif errors.Is(err, context.DeadlineExceeded) {\n    fmt.Println(\"Operation timed out\")\n}\n```\n\n## Best Practices\n\n### Circuit Breaker\n\n- Set `failureThreshold` based on your service's error budget\n- Use longer `recoveryTimeout` for services that take time to recover\n- Always provide a meaningful fallback (cached data, default values, or graceful degradation)\n- Monitor circuit state changes in production\n\n### Exponential Backoff\n\n- Start with small `initialDelay` (100-500ms) for fast operations\n- Use `multiplier=2` for standard exponential growth\n- Add jitter (`randomInt=1-5`) to prevent thundering herd\n- Set reasonable `maxRetries` to avoid excessive delays\n- Use context timeouts to bound total retry time\n\n## Thread Safety\n\nAll components are thread-safe and can be:\n- Shared across multiple goroutines\n- Called concurrently\n- Used in high-concurrency scenarios\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nMIT License - see LICENSE file for details.\n\n## Author\n\nMarincor\n\n## Roadmap\n\nFuture features under consideration:\n\n- 🚦 **Rate Limiting** - Control request rates with token bucket/leaky bucket\n- 🏗️ **Bulkhead** - Isolate resources to prevent cascading failures\n- ⏱️ **Timeout** - Configurable operation timeouts\n- 🔄 **Fallback** - Advanced fallback strategies\n- 📊 **Metrics** - Prometheus integration\n- 🏥 **Health Checks** - Service health monitoring\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarincor%2Fgendure","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarincor%2Fgendure","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarincor%2Fgendure/lists"}