## Description Closes: #9404 --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [x] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [x] reviewed "Files changed" and left comments if necessary - [x] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
4.2 KiB
Query Services
A Protobuf Query service processes queries. Query services are specific to the module in which they are defined, and only process queries defined within said module. They are called from BaseApp's Query method. {synopsis}
Pre-requisite Readings
- Module Manager {prereq}
- Messages and Queries {prereq}
Querier type
The querier type defined in the Cosmos SDK will be deprecated in favor of gRPC Services. It specifies the typical structure of a querier function:
Let us break it down:
- The
pathis an array ofstrings that contains the type of the query, and that can also containqueryarguments. Seequeriesfor more information. - The
reqitself is primarily used to retrieve arguments if they are too large to fit in thepath. This is done using theDatafield ofreq. - The
Contextcontains all the necessary information needed to process thequery, as well as a branch of the latest state. It is primarily used by thekeeperto access the state. - The result
resreturned toBaseApp, marshalled using the application'scodec.
Implementation of a module query service
gRPC Service
When defining a Protobuf Query service, a QueryServer interface is generated for each module with all the service methods:
type QueryServer interface {
QueryBalance(context.Context, *QueryBalanceParams) (*types.Coin, error)
QueryAllBalances(context.Context, *QueryAllBalancesParams) (*QueryAllBalancesResponse, error)
}
These custom queries methods should be implemented by a module's keeper, typically in ./keeper/grpc_query.go. The first parameter of these methods is a generic context.Context, whereas querier methods generally need an instance of sdk.Context to read
from the store. Therefore, the Cosmos SDK provides a function sdk.UnwrapSDKContext to retrieve the sdk.Context from the provided
context.Context.
Here's an example implementation for the bank module:
Legacy Queriers
Module legacy queriers are typically implemented in a ./keeper/querier.go file inside the module's folder. The module manager is used to add the module's queriers to the application's queryRouter via the NewQuerier() method. Typically, the manager's NewQuerier() method simply calls a NewQuerier() method defined in keeper/querier.go, which looks like the following:
func NewQuerier(keeper Keeper) sdk.Querier {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) {
switch path[0] {
case QueryType1:
return queryType1(ctx, path[1:], req, keeper)
case QueryType2:
return queryType2(ctx, path[1:], req, keeper)
default:
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint: %s", types.ModuleName, path[0])
}
}
}
This simple switch returns a querier function specific to the type of the received query. At this point of the query lifecycle, the first element of the path (path[0]) contains the type of the query. The following elements are either empty or contain arguments needed to process the query.
The querier functions themselves are pretty straighforward. They generally fetch a value or values from the state using the keeper. Then, they marshall the value(s) using the codec and return the []byte obtained as result.
For a deeper look at queriers, see this example implementation of a querier function from the bank module.
Next {hide}
Learn about BeginBlocker and EndBlocker {hide}