Skip to content

Commit

Permalink
feat: Split sortedSetFetch up into ByRank and ByScore functions (#280)
Browse files Browse the repository at this point in the history
* feat: Split sortedSetFetch up into ByRank and ByScore functions

As per the API design discussion and the pattern we established
in the node.js SDK, this commit splits the SortedSetFetch into
two functions, one for fetching by score and one for by rank.
This prevents the user from needing to reason about which
combinations of arguments are and are not legal together.
  • Loading branch information
cprice404 authored Mar 13, 2023
1 parent 2ed735f commit 0a12ba3
Show file tree
Hide file tree
Showing 6 changed files with 355 additions and 231 deletions.
17 changes: 13 additions & 4 deletions momento/cache_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ type CacheClient interface {
// KeysExist checks if provided keys exist in the cache.
KeysExist(ctx context.Context, r *KeysExistRequest) (responses.KeysExistResponse, error)

// SortedSetFetch fetches the elements in the given sorted set by index rank or by score.
SortedSetFetch(ctx context.Context, r *SortedSetFetchRequest) (responses.SortedSetFetchResponse, error)
// SortedSetElement adds an element to the given sorted set. If the element already exists,
// SortedSetFetchByRank fetches the elements in the given sorted set by rank.
SortedSetFetchByRank(ctx context.Context, r *SortedSetFetchByRankRequest) (responses.SortedSetFetchResponse, error)
// SortedSetFetchByScore fetches the elements in the given sorted set by score.
SortedSetFetchByScore(ctx context.Context, r *SortedSetFetchByScoreRequest) (responses.SortedSetFetchResponse, error)
// SortedSetPutElement adds an element to the given sorted set. If the element already exists,
// its score is updated. Creates the sorted set if it does not exist.
SortedSetPutElement(ctx context.Context, r *SortedSetPutElementRequest) (responses.SortedSetPutElementResponse, error)
// SortedSetPutElements adds elements to the given sorted set. If an element already exists,
Expand Down Expand Up @@ -271,7 +273,14 @@ func (c defaultScsClient) KeysExist(ctx context.Context, r *KeysExistRequest) (r
return r.response, nil
}

func (c defaultScsClient) SortedSetFetch(ctx context.Context, r *SortedSetFetchRequest) (responses.SortedSetFetchResponse, error) {
func (c defaultScsClient) SortedSetFetchByRank(ctx context.Context, r *SortedSetFetchByRankRequest) (responses.SortedSetFetchResponse, error) {
if err := c.dataClient.makeRequest(ctx, r); err != nil {
return nil, err
}
return r.response, nil
}

func (c defaultScsClient) SortedSetFetchByScore(ctx context.Context, r *SortedSetFetchByScoreRequest) (responses.SortedSetFetchResponse, error) {
if err := c.dataClient.makeRequest(ctx, r); err != nil {
return nil, err
}
Expand Down
167 changes: 0 additions & 167 deletions momento/sorted_set_fetch.go

This file was deleted.

100 changes: 100 additions & 0 deletions momento/sorted_set_fetch_by_rank.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package momento

import (
"context"

"github.com/momentohq/client-sdk-go/responses"

pb "github.com/momentohq/client-sdk-go/internal/protos"
)

type SortedSetFetchByRankRequest struct {
CacheName string
SetName string
Order SortedSetOrder
StartRank *int32
EndRank *int32

grpcRequest *pb.XSortedSetFetchRequest
grpcResponse *pb.XSortedSetFetchResponse
response responses.SortedSetFetchResponse
}

func (r *SortedSetFetchByRankRequest) cacheName() string { return r.CacheName }

func (r *SortedSetFetchByRankRequest) requestName() string { return "Sorted set fetch" }

func (r *SortedSetFetchByRankRequest) initGrpcRequest(scsDataClient) error {
var err error

if _, err = prepareName(r.SetName, "Set name"); err != nil {
return err
}

grpcReq := &pb.XSortedSetFetchRequest{
SetName: []byte(r.SetName),
Order: pb.XSortedSetFetchRequest_Order(r.Order),
WithScores: true,
}

// This is the default: fetch everything in ascending order.
by_index := pb.XSortedSetFetchRequest_ByIndex{
ByIndex: &pb.XSortedSetFetchRequest_XByIndex{
Start: &pb.XSortedSetFetchRequest_XByIndex_UnboundedStart{},
End: &pb.XSortedSetFetchRequest_XByIndex_UnboundedEnd{},
},
}

if r.StartRank != nil {

by_index.ByIndex.Start = &pb.XSortedSetFetchRequest_XByIndex_InclusiveStartIndex{
InclusiveStartIndex: *r.StartRank,
}
}

if r.EndRank != nil {
by_index.ByIndex.End = &pb.XSortedSetFetchRequest_XByIndex_ExclusiveEndIndex{
ExclusiveEndIndex: *r.EndRank,
}
}

grpcReq.Range = &by_index

r.grpcRequest = grpcReq

return nil
}

func (r *SortedSetFetchByRankRequest) makeGrpcRequest(metadata context.Context, client scsDataClient) (grpcResponse, error) {
resp, err := client.grpcClient.SortedSetFetch(metadata, r.grpcRequest)
if err != nil {
return nil, err
}

r.grpcResponse = resp

return resp, nil
}

func (r *SortedSetFetchByRankRequest) interpretGrpcResponse() error {
switch grpcResp := r.grpcResponse.SortedSet.(type) {
case *pb.XSortedSetFetchResponse_Found:
r.response = responses.NewSortedSetFetchHit(sortedSetByRankGrpcElementToModel(grpcResp.Found.GetValuesWithScores().Elements))
case *pb.XSortedSetFetchResponse_Missing:
r.response = &responses.SortedSetFetchMiss{}
default:
return errUnexpectedGrpcResponse(r, r.grpcResponse)
}
return nil
}

func sortedSetByRankGrpcElementToModel(grpcSetElements []*pb.XSortedSetElement) []responses.SortedSetBytesElement {
var returnList []responses.SortedSetBytesElement
for _, element := range grpcSetElements {
returnList = append(returnList, responses.SortedSetBytesElement{
Value: element.Value,
Score: element.Score,
})
}
return returnList
}
Loading

0 comments on commit 0a12ba3

Please sign in to comment.