Skip to content

Conversation

@costela
Copy link
Member

@costela costela commented Dec 3, 2025

This pull request introduces a significant refactor to the hoglet circuit breaker library, focusing on simplifying the API, improving type safety, and modernizing the codebase. The most notable change is the removal of the generic Circuit type in favor of a non-generic Circuit struct, with a new Wrap function to adapt user functions to the circuit breaker. The tests and examples have been updated to use the new API. Additionally, dependencies and the Go version have been updated.

❌ Old

h, err := hoglet.NewCircuit(
	someFunction,
	hoglet.NewSlidingWindowBreaker(time.Second, 0.1),
)
if err != nil { /* ... */ }

output, err := h.Call(ctx, someInputParameter)

🟢 New

h, err := hoglet.NewCircuit(
	hoglet.NewSlidingWindowBreaker(time.Second, 0.1),
)
if err != nil { /* ... */ }

output, err := hoglet.Wrap(h, someFunction)(ctx, someInputParameter)

This allows reusing the same circuit for multiple different functions.

Details:

API Refactor and Simplification:

  • Replaced the generic Circuit[IN, OUT] type with a non-generic Circuit struct, and removed the function parameter from NewCircuit. Instead, user functions are now wrapped using a new generic Wrap function, which applies the circuit breaker to any compatible function. (hoglet.go, example_test.go, hoglet_test.go, options_test.go) [1] [2] [3] [4] [5] [6] [7] [8]

  • Updated all usages in tests and examples to use Wrap(circuit, func) instead of the previous circuit.Call(...) method, ensuring consistency and demonstrating the new API. (example_test.go, hoglet_test.go, options_test.go) [1] [2] [3] [4] [5] [6] [7]

Type and Naming Improvements:

  • Introduced WrappableFunc as the new type for functions that can be wrapped by a Circuit, replacing the old WrappedFunc type. (hoglet.go)

Dependency and Go Version Updates:

  • Updated the Go version to 1.24.0 and bumped golang.org/x/sync to v0.18.0 in go.mod. Also removed an unused indirect dependency. (go.mod)

Testing Improvements:

  • Changed the package of options_test.go to hoglet_test for improved test isolation and updated imports accordingly. (options_test.go)

The change also brings some improvements to micro-benchmarks:

goos: linux
goarch: amd64
pkg: github.com/exaring/hoglet
cpu: 12th Gen Intel(R) Core(TM) i7-1250U
                           │  old.bench   │              new.bench              │
                           │    sec/op    │   sec/op     vs base                │
Hoglet_Do_EWMA-12            808.2n ± 24%   388.8n ± 3%  -51.90% (p=0.000 n=10)
Hoglet_Do_SlidingWindow-12   858.8n ±  2%   553.4n ± 3%  -35.55% (p=0.000 n=10)
geomean                      833.1n         463.8n       -44.32%

                           │ old.bench  │             new.bench             │
                           │    B/op    │    B/op     vs base               │
Hoglet_Do_EWMA-12            208.0 ± 0%   192.0 ± 1%  -7.69% (p=0.000 n=10)
Hoglet_Do_SlidingWindow-12   208.0 ± 0%   192.0 ± 0%  -7.69% (p=0.000 n=10)
geomean                      208.0        192.0       -7.69%

                           │ old.bench  │              new.bench              │
                           │ allocs/op  │ allocs/op   vs base                 │
Hoglet_Do_EWMA-12            5.000 ± 0%   5.000 ± 0%       ~ (p=1.000 n=10) ¹
Hoglet_Do_SlidingWindow-12   5.000 ± 0%   5.000 ± 0%       ~ (p=1.000 n=10) ¹
geomean                      5.000        5.000       +0.00%
¹ all samples are equal

@costela costela requested review from cdreier, Copilot, marcboeker and obitech and removed request for Copilot December 3, 2025 12:52
@costela costela changed the title Refactor usage to delay type specification Breaking: refactor usage to delay type specification Dec 3, 2025
Copilot finished reviewing on behalf of costela December 3, 2025 12:54
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the hoglet circuit breaker library to decouple the Circuit from specific function types, enabling reuse of a single Circuit instance across multiple functions. The key architectural change replaces the generic Circuit[IN, OUT] type with a non-generic Circuit struct, and introduces a new Wrap function to adapt user functions to the circuit breaker pattern. This improves API flexibility and reduces type parameter complexity.

Key Changes

  • Replaced generic Circuit[IN, OUT] with non-generic Circuit struct, moving function wrapping logic from NewCircuit to a new Wrap function
  • Updated Go version to 1.24.0 and bumped golang.org/x/sync dependency to v0.18.0
  • Updated all tests and examples to use the new API pattern with Wrap(circuit, func) instead of circuit.Call(...)

Reviewed changes

Copilot reviewed 5 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
hoglet.go Core API refactor: removed generics from Circuit type, introduced Wrap function, renamed WrappedFunc to WrappableFunc
hoglet_test.go Updated tests and benchmarks to use new Wrap API, improved benchmark setup by caching wrapped functions, removed obsolete tt := tt pattern
options_test.go Changed package to hoglet_test for better test isolation, updated tests to use new Wrap API
example_test.go Updated all examples to demonstrate new Wrap API pattern
go.mod Updated Go version to 1.24.0 and golang.org/x/sync to v0.18.0, removed unused protobuf dependency
go.sum Updated checksums for dependency changes
.gitignore Added *.profile pattern for profiling artifacts

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

// [ErrCircuitOpen].
// Wrap wraps the provided function with the given [Circuit].
//
// Calling the returned function if the circuit is closed and returns the result of the wrapped function.
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammar issue: "Calling the returned function if the circuit is closed" should be "Calls the returned function if the circuit is closed" or "The returned function calls the wrapped function if the circuit is closed".

Suggested change
// Calling the returned function if the circuit is closed and returns the result of the wrapped function.
// The returned function calls the wrapped function if the circuit is closed and returns its result.

Copilot uses AI. Check for mistakes.
This makes the circuit itself type-agnostic, allowing reuse of circuits for multiple functions with different types.

BREAKING CHANGE: circuit initialization now does not require the function and does not provide the Call() method
anymore, instead relying on the package-level Wrap().
@costela costela force-pushed the refactor-usage-to-delay-type-specification branch from 0b4fb83 to f99c9ae Compare December 3, 2025 17:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants