Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Add iterators for array requests #30

Open
fedekunze opened this issue Dec 4, 2019 · 0 comments
Open

Add iterators for array requests #30

fedekunze opened this issue Dec 4, 2019 · 0 comments
Assignees

Comments

@fedekunze
Copy link

fedekunze commented Dec 4, 2019

Keepers can use the store Iterator to retrieve all the items from the store by performing a callback function (eg an aggregator):

// IterateClients provides an iterator over all stored light client State
// objects. For each State object, cb will be called. If the cb returns true,
// the iterator will close and stop.
func (k Keeper) IterateClients(ctx sdk.Context, cb func(types.State) bool) {
	store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixClient)
	iterator := sdk.KVStorePrefixIterator(store, nil)

	defer iterator.Close()
	for ; iterator.Valid(); iterator.Next() {
		var clientState types.State
		k.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &clientState)

		if cb(clientState) {
			break
		}
	}
}

Then you can use the Iterator function above to retrieve all the objects from the store by aggregating them:

// GetAllClients returns all stored light client State objects.
func (k Keeper) GetAllClients(ctx sdk.Context) (states []types.State) {
	k.IterateClients(ctx, func(state types.State) bool {
		states = append(states, state)
		return false
	})
	return states
}

Finally, we add the Querier method:

// QueryAllClients defines the sdk.Querier to query all the light client states.
func QueryAllClients(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
	var params types.QueryAllClientsParams

	err := k.cdc.UnmarshalJSON(req.Data, &params)
	if err != nil {
		return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
	}

	clients := k.GetAllClients(ctx)

	start, end := client.Paginate(len(clients), params.Page, params.Limit, 100)
	if start < 0 || end < 0 {
		clients = []types.State{}
	} else {
		clients = clients[start:end]
	}

	res, err := types.SubModuleCdc.MarshalJSON(clients)
	if err != nil {
		return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
	}

	return res, nil
}

where QueryAllClientsParams contains only the pagination parameters:

type QueryAllClientsParams struct {
	Page  int `json:"page" yaml:"page"`
	Limit int `json:"limit" yaml:"limit"`
}

This is a pretty standard way on the SDK which would be helpful to support on the scaffold.

@jackzampolin jackzampolin self-assigned this Dec 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants