Skip to content

Commit

Permalink
refactor: session query client
Browse files Browse the repository at this point in the history
  • Loading branch information
bryanchriswhite committed Dec 11, 2024
1 parent e804abd commit e96b5bd
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 21 deletions.
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
}

0 comments on commit e96b5bd

Please sign in to comment.