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

[Clients] embed ParamsQuerier into SessionQueryClient #999

Draft
wants to merge 1 commit into
base: issues/543/params-querier/service
Choose a base branch
from
Draft
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
5 changes: 2 additions & 3 deletions pkg/client/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,16 +287,15 @@ type SupplierQueryClient interface {
// SessionQueryClient defines an interface that enables the querying of the
// on-chain session information
type SessionQueryClient interface {
ParamsQuerier[*sessiontypes.Params]

// GetSession queries the chain for the details of the session provided
GetSession(
ctx context.Context,
appAddress string,
serviceId string,
blockHeight int64,
) (*sessiontypes.Session, error)

// GetParams queries the chain for the session module parameters.
GetParams(ctx context.Context) (*sessiontypes.Params, error)
}

// SharedQueryClient defines an interface that enables the querying of the
Expand Down
91 changes: 73 additions & 18 deletions pkg/client/query/sessionquerier.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ package query

import (
"context"
"errors"
"fmt"
"time"

"cosmossdk.io/depinject"
"github.com/cosmos/gogoproto/grpc"

"github.com/pokt-network/poktroll/pkg/client"
"github.com/pokt-network/poktroll/pkg/client/query/cache"
"github.com/pokt-network/poktroll/pkg/polylog"
sessiontypes "github.com/pokt-network/poktroll/x/session/types"
)

Expand All @@ -16,59 +21,109 @@ var _ client.SessionQueryClient = (*sessionQuerier)(nil)
// querying of on-chain session information through a single exposed method
// which returns an sessiontypes.Session struct
type sessionQuerier struct {
client.ParamsQuerier[*sessiontypes.Params]

clientConn grpc.ClientConn
sessionQuerier sessiontypes.QueryClient
sessionCache client.QueryCache[*sessiontypes.Session]
}

// NewSessionQuerier returns a new instance of a client.SessionQueryClient by
// injecting the dependecies provided by the depinject.Config.
//
// Required dependencies:
// - clientCtx (grpc.ClientConn)
func NewSessionQuerier(deps depinject.Config) (client.SessionQueryClient, error) {
sessq := &sessionQuerier{}
func NewSessionQuerier(
deps depinject.Config,
paramsQuerierOpts ...ParamsQuerierOptionFn,
) (client.SessionQueryClient, error) {
paramsQuerierCfg := DefaultParamsQuerierConfig()
for _, opt := range paramsQuerierOpts {
opt(paramsQuerierCfg)
}

paramsQuerier, err := NewCachedParamsQuerier[*sessiontypes.Params, sessiontypes.SessionQueryClient](
deps, sessiontypes.NewSessionQueryClient,
WithModuleInfo[*sessiontypes.Params](sessiontypes.ModuleName, sessiontypes.ErrSessionParamInvalid),
WithParamsCacheOptions(paramsQuerierCfg.CacheOpts...),
)
if err != nil {
return nil, err
}

// Initialize session cache with historical mode since sessions can vary by height
// TODO_IN_THIS_COMMIT: consider supporting multiple cache configs per query client.
sessionCache := cache.NewInMemoryCache[*sessiontypes.Session](
// TODO_IN_THIS_COMMIT: extract to an option fn.
cache.WithMaxKeys(100),
cache.WithEvictionPolicy(cache.LeastRecentlyUsed),
// TODO_IN_THIS_COMMIT: extract to a constant.
cache.WithTTL(time.Hour*3),
)

if err := depinject.Inject(
querier := &sessionQuerier{
ParamsQuerier: paramsQuerier,
sessionCache: sessionCache,
}

if err = depinject.Inject(
deps,
&sessq.clientConn,
&querier.clientConn,
); err != nil {
return nil, err
}

sessq.sessionQuerier = sessiontypes.NewQueryClient(sessq.clientConn)
querier.sessionQuerier = sessiontypes.NewQueryClient(querier.clientConn)

return sessq, nil
return querier, nil
}

// GetSession returns an sessiontypes.Session struct for a given appAddress,
// serviceId and blockHeight. It implements the SessionQueryClient#GetSession function.
func (sessq *sessionQuerier) GetSession(
func (sq *sessionQuerier) GetSession(
ctx context.Context,
appAddress string,
serviceId string,
blockHeight int64,
) (*sessiontypes.Session, error) {
logger := polylog.Ctx(ctx).With(
"querier", "session",
"method", "GetSession",
)

// Create cache key from query parameters
cacheKey := fmt.Sprintf("%s:%s:%d", appAddress, serviceId, blockHeight)

// Check cache first
cached, err := sq.sessionCache.Get(cacheKey)
switch {
case err == nil:
logger.Debug().Msg("cache hit")
return cached, nil
case !errors.Is(err, cache.ErrCacheMiss):
return nil, err
default:
logger.Debug().Msg("cache miss")
}

// If not cached, query the chain
req := &sessiontypes.QueryGetSessionRequest{
ApplicationAddress: appAddress,
ServiceId: serviceId,
BlockHeight: blockHeight,
}
res, err := sessq.sessionQuerier.GetSession(ctx, req)
res, err := sq.sessionQuerier.GetSession(ctx, req)
if err != nil {
return nil, ErrQueryRetrieveSession.Wrapf(
"address: %s; serviceId: %s; block height: %d; error: [%v]",
"address: %s; serviceId: %s; block height: %d; error: %s",
appAddress, serviceId, blockHeight, err,
)
}
return res.Session, nil
}

// GetParams queries & returns the session module on-chain parameters.
func (sessq *sessionQuerier) GetParams(ctx context.Context) (*sessiontypes.Params, error) {
req := &sessiontypes.QueryParamsRequest{}
res, err := sessq.sessionQuerier.Params(ctx, req)
if err != nil {
return nil, ErrQuerySessionParams.Wrapf("[%v]", err)
// Cache the result before returning
if err = sq.sessionCache.Set(cacheKey, res.Session); err != nil {
return nil, err
}
return &res.Params, nil

return res.Session, nil
}
31 changes: 31 additions & 0 deletions x/session/types/query_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package types

import (
"context"

gogogrpc "github.com/cosmos/gogoproto/grpc"
)

// TODO_IN_THIS_COMMIT: godoc...
type SessionQueryClient interface {
QueryClient

GetParams(context.Context) (*Params, error)
}

// TODO_IN_THIS_COMMIT: godoc...
func NewSessionQueryClient(conn gogogrpc.ClientConn) SessionQueryClient {
return NewQueryClient(conn).(SessionQueryClient)
}

// TODO_IN_THIS_COMMIT: investigate generalization...
// TODO_IN_THIS_COMMIT: godoc...
func (c *queryClient) GetParams(ctx context.Context) (*Params, error) {
res, err := c.Params(ctx, &QueryParamsRequest{})
if err != nil {
return nil, err
}

params := res.GetParams()
return &params, nil
}
Loading