package payment import ( "context" "time" "github.com/sony/gobreaker/v2" ) type breakerChannel struct { next channelClient createPayment *gobreaker.CircuitBreaker[*channelCreatePaymentResponse] queryPayment *gobreaker.CircuitBreaker[*channelQueryPaymentResponse] createRefund *gobreaker.CircuitBreaker[*channelCreateRefundResponse] queryRefund *gobreaker.CircuitBreaker[*channelQueryRefundResponse] } func withChannelBreaker(name string, next channelClient) channelClient { if next == nil { return nil } return breakerChannel{ next: next, createPayment: newPaymentBreaker[*channelCreatePaymentResponse](name + ".create_payment"), queryPayment: newPaymentBreaker[*channelQueryPaymentResponse](name + ".query_payment"), createRefund: newPaymentBreaker[*channelCreateRefundResponse](name + ".create_refund"), queryRefund: newPaymentBreaker[*channelQueryRefundResponse](name + ".query_refund"), } } func newPaymentBreaker[T any](name string) *gobreaker.CircuitBreaker[T] { return gobreaker.NewCircuitBreaker[T](gobreaker.Settings{ Name: name, MaxRequests: 3, Timeout: 10 * time.Second, ReadyToTrip: func(counts gobreaker.Counts) bool { return counts.ConsecutiveFailures >= 5 }, }) } func (c breakerChannel) CreatePayment(ctx context.Context, req channelCreatePaymentRequest) (*channelCreatePaymentResponse, error) { return c.createPayment.Execute(func() (*channelCreatePaymentResponse, error) { return c.next.CreatePayment(ctx, req) }) } func (c breakerChannel) QueryPayment(ctx context.Context, thirdOrderID string, providerOrderID string) (*channelQueryPaymentResponse, error) { return c.queryPayment.Execute(func() (*channelQueryPaymentResponse, error) { return c.next.QueryPayment(ctx, thirdOrderID, providerOrderID) }) } func (c breakerChannel) CreateRefund(ctx context.Context, req channelCreateRefundRequest) (*channelCreateRefundResponse, error) { return c.createRefund.Execute(func() (*channelCreateRefundResponse, error) { return c.next.CreateRefund(ctx, req) }) } func (c breakerChannel) QueryRefund(ctx context.Context, req channelQueryRefundRequest) (*channelQueryRefundResponse, error) { return c.queryRefund.Execute(func() (*channelQueryRefundResponse, error) { return c.next.QueryRefund(ctx, req) }) } func (c breakerChannel) VerifyNotify(params map[string]string, rawPayload string, contentType string, authorization string) (channelVerifyNotifyResult, error) { return c.next.VerifyNotify(params, rawPayload, contentType, authorization) }