Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(baseapp): add setter for circuit breaker (backport) #16290

Merged
merged 3 commits into from
May 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Features

* (baseapp) [#16290](https://github.com/cosmos/cosmos-sdk/pull/16290) Add circuit breaker setter in baseapp.
* (x/group) [#16191](https://github.com/cosmos/cosmos-sdk/pull/16191) Add EventProposalPruned event to group module whenever a proposal is pruned.

### Improvements
Expand Down
9 changes: 9 additions & 0 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,15 @@ func (app *BaseApp) SetMsgServiceRouter(msgServiceRouter *MsgServiceRouter) {
app.msgServiceRouter = msgServiceRouter
}

// SetCircuitBreaker sets the circuit breaker for the BaseApp.
// The circuit breaker is checked on every message execution to verify if a transaction should be executed or not.
func (app *BaseApp) SetCircuitBreaker(cb CircuitBreaker) {
if app.msgServiceRouter == nil {
panic("must be called after message server is set")
}
app.msgServiceRouter.SetCircuit(cb)
}

// MountStores mounts all IAVL or DB stores to the provided keys in the BaseApp
// multistore.
func (app *BaseApp) MountStores(keys ...storetypes.StoreKey) {
Expand Down
10 changes: 10 additions & 0 deletions baseapp/circuit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package baseapp

import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

// CircuitBreaker is an interface that defines the methods for a circuit breaker.
type CircuitBreaker interface {
IsAllowed(ctx sdk.Context, typeURL string) bool
}
12 changes: 12 additions & 0 deletions baseapp/msg_service_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
type MsgServiceRouter struct {
interfaceRegistry codectypes.InterfaceRegistry
routes map[string]MsgServiceHandler
circuitBreaker CircuitBreaker
}

var _ gogogrpc.Server = &MsgServiceRouter{}
Expand All @@ -31,6 +32,10 @@ func NewMsgServiceRouter() *MsgServiceRouter {
// MsgServiceHandler defines a function type which handles Msg service message.
type MsgServiceHandler = func(ctx sdk.Context, req sdk.Msg) (*sdk.Result, error)

func (msr *MsgServiceRouter) SetCircuit(cb CircuitBreaker) {
msr.circuitBreaker = cb
}

// Handler returns the MsgServiceHandler for a given msg or nil if not found.
func (msr *MsgServiceRouter) Handler(msg sdk.Msg) MsgServiceHandler {
return msr.routes[sdk.MsgTypeURL(msg)]
Expand Down Expand Up @@ -116,6 +121,13 @@ func (msr *MsgServiceRouter) RegisterService(sd *grpc.ServiceDesc, handler inter
if err := req.ValidateBasic(); err != nil {
return nil, err
}

if msr.circuitBreaker != nil {
msgURL := sdk.MsgTypeURL(req)
if !msr.circuitBreaker.IsAllowed(ctx, msgURL) {
return nil, fmt.Errorf("circuit breaker disables execution of this message: %s", msgURL)
}
}
// Call the method handler from the service description with the handler object.
// We don't do any decoding here because the decoding was already done.
res, err := methodHandler(handler, sdk.WrapSDKContext(ctx), noopDecoder, interceptor)
Expand Down