3.2 KiB
| order | synopsis |
|---|---|
| 5 | A `Querier` designates a function that processes [`queries`](./messages-and-queries.md#queries). `querier`s 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](../core/baseapp.md#query). |
Queriers
Pre-requisite Readings {hide}
- Module Manager {prereq}
- Messages and Queries {prereq}
Querier type
The querier type defined in the Cosmos SDK specifies the typical structure of a querier function:
+++ 7d7821b9af/types/queryable.go (L6)
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 cache-wrapped copy of the latest state. It is primarily used by thekeeperto access the state. - The result
resreturned tobaseapp, marhsalled using the application'scodec.
Implementation of a module queriers
Module queriers are typically implemented in a ./internal/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) (res []byte, err sdk.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, sdk.ErrUnknownRequest("unknown nameservice query endpoint")
}
}
}
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 nameservice tutorial.
Next {hide}
Learn about BeginBlocker and EndBlocker {hide}