@@ -151,16 +151,17 @@ type session struct {
151151 dirs * Directories
152152
153153 // Only set once the user has authenticated
154- user * sessionUser
154+ user * userSession
155155 userMu * sync.RWMutex
156156}
157157
158- type sessionUser struct {
158+ type userSession struct {
159159 objDir directory.DirectorySubspace
160160 metaDir directory.DirectorySubspace
161161 uidDir directory.DirectorySubspace
162162 reverseUIDDir directory.DirectorySubspace
163163 listDir directory.DirectorySubspace
164+ zsetDir directory.DirectorySubspace
164165
165166 user * types.User
166167}
@@ -247,6 +248,18 @@ func (s *session) uidKey(id string) (fdb.Key, error) {
247248 return s .user .uidDir .Pack (tuple.Tuple {id }), nil
248249}
249250
251+ // Returns the FDB directory
252+ func (s * session ) sortedSetScoreDir (key string ) (directory.DirectorySubspace , error ) {
253+ s .userMu .RLock ()
254+ defer s .userMu .RUnlock ()
255+
256+ if s .user == nil {
257+ return nil , fmt .Errorf ("authentication is required" )
258+ }
259+
260+ return s .user .zsetDir .CreateOrOpen (s .fdb , []string {key }, nil )
261+ }
262+
250263// Returns the FDB key of an object in the per-user uid directory
251264func (s * session ) reverseUIDKey (id string ) (fdb.Key , error ) {
252265 s .userMu .RLock ()
@@ -382,6 +395,14 @@ func (s *session) handleCommand(ctx context.Context, cmd *resp.Command) string {
382395 res , err = s .handleSetUnion (ctx , cmd .Args )
383396 case "sdiff" :
384397 res , err = s .handleSetDiff (ctx , cmd .Args )
398+ case "zadd" :
399+ res , err = s .handleZAdd (ctx , cmd .Args )
400+ case "zcount" :
401+ res , err = s .handleZCount (ctx , cmd .Args )
402+ case "zremrangebyscore" :
403+ res , err = s .handleZRemRangeByScore (ctx , cmd .Args )
404+ case "zcard" :
405+ res , err = s .handleSetCard (ctx , cmd .Args )
385406 case "llen" :
386407 res , err = s .handleLLen (ctx , cmd .Args )
387408 case "lpush" :
@@ -552,61 +573,43 @@ func userIsAdmin(user *types.User) bool {
552573 return false
553574}
554575
555- func (s * session ) getMeta (ctx context.Context , tx fdb.ReadTransaction , id string , meta proto. Message ) (bool , fdb.Key , error ) {
576+ func (s * session ) getMeta (ctx context.Context , tx fdb.ReadTransaction , id string ) (fdb.Key , * types. ObjectMeta , error ) {
556577 ctx , span := s .tracer .Start (ctx , "getMeta" ) // nolint
557578 defer span .End ()
558579
559580 metaKey , err := s .metaKey (id )
560581 if err != nil {
561582 span .RecordError (err )
562- return false , nil , fmt .Errorf ("failed to get meta key: %w" , err )
583+ return nil , nil , fmt .Errorf ("failed to get meta key: %w" , err )
563584 }
564585
565586 metaBuf , err := tx .Get (metaKey ).Get ()
566587 if err != nil {
567588 span .RecordError (err )
568- return false , metaKey , fmt .Errorf ("failed to get object meta: %w" , err )
589+ return nil , nil , fmt .Errorf ("failed to get object meta: %w" , err )
569590 }
570591
571592 if len (metaBuf ) == 0 {
572593 metrics .SpanOK (span )
573- return false , metaKey , nil
574- }
575-
576- if err = proto .Unmarshal (metaBuf , meta ); err != nil {
577- span .RecordError (err )
578- return false , metaKey , fmt .Errorf ("failed to proto unmarshal object meta: %w" , err )
594+ return metaKey , nil , nil
579595 }
580596
581- metrics .SpanOK (span )
582- return true , metaKey , nil
583- }
584-
585- // Returns the associated metadata for an object of any type. Returns nil if it not exist.
586- func (s * session ) getObjectMeta (ctx context.Context , tx fdb.ReadTransaction , id string ) (fdb.Key , * types.ObjectMeta , error ) {
587- ctx , span := s .tracer .Start (ctx , "getObjectMeta" )
588- defer span .End ()
589-
590597 meta := & types.ObjectMeta {}
591- exists , key , err := s .getMeta (ctx , tx , id , meta )
592- if err != nil {
598+ if err = proto .Unmarshal (metaBuf , meta ); err != nil {
593599 span .RecordError (err )
594- return nil , nil , err
595- }
596- if ! exists {
597- meta = nil
600+ return nil , nil , fmt .Errorf ("failed to proto unmarshal object meta: %w" , err )
598601 }
599602
600603 metrics .SpanOK (span )
601- return key , meta , nil
604+ return metaKey , meta , nil
602605}
603606
604607// Returns the associated metadata for an object. Returns nil if the object does not exist.
605608func (s * session ) getListMeta (ctx context.Context , tx fdb.ReadTransaction , id string ) (fdb.Key , * types.ListMeta , error ) {
606609 ctx , span := s .tracer .Start (ctx , "getListMeta" )
607610 defer span .End ()
608611
609- key , objMeta , err := s .getObjectMeta (ctx , tx , id )
612+ key , objMeta , err := s .getMeta (ctx , tx , id )
610613 if err != nil {
611614 span .RecordError (err )
612615 return nil , nil , fmt .Errorf ("failed to get object meta: %w" , err )
@@ -698,12 +701,13 @@ func (s *session) allocateNewUID(ctx context.Context, tx fdb.Transaction) (uint6
698701 return newUID , nil
699702}
700703
701- // Returns the UID for the given member string, creating a new one if it does not exist
702- func (s * session ) getOrAllocateUID (ctx context.Context , tx fdb.Transaction , member string ) (uint64 , error ) {
704+ // Returns the UID for the given member string, creating a new one if it does not exist. If peek is true, it
705+ // will refuse to create a new UID if one does not already exist.
706+ func (s * session ) getOrAllocateUID (ctx context.Context , tx fdb.Transaction , member * types.SetMember ) (uint64 , error ) {
703707 ctx , span := s .tracer .Start (ctx , "getOrAllocateUID" )
704708 defer span .End ()
705709
706- memberToUIDKey , err := s .reverseUIDKey (member )
710+ memberToUIDKey , err := s .reverseUIDKey (member . Member )
707711 if err != nil {
708712 span .RecordError (err )
709713 return 0 , fmt .Errorf ("failed to get uid key: %w" , err )
@@ -718,13 +722,13 @@ func (s *session) getOrAllocateUID(ctx context.Context, tx fdb.Transaction, memb
718722
719723 if len (val ) == 0 {
720724 // allocate a new UID for this member string
721- uid , err : = s .allocateNewUID (ctx , tx )
725+ member . Uid , err = s .allocateNewUID (ctx , tx )
722726 if err != nil {
723727 span .RecordError (err )
724728 return 0 , fmt .Errorf ("failed to allocate new uid: %w" , err )
725729 }
726730
727- uidStr := strconv .FormatUint (uid , 10 )
731+ uidStr := strconv .FormatUint (member . Uid , 10 )
728732 uidToMemberKey , err := s .uidKey (uidStr )
729733 if err != nil {
730734 span .RecordError (err )
@@ -733,7 +737,9 @@ func (s *session) getOrAllocateUID(ctx context.Context, tx fdb.Transaction, memb
733737
734738 // store the bi-directional mapping
735739 tx .Set (memberToUIDKey , []byte (uidStr ))
736- tx .Set (uidToMemberKey , []byte (member ))
740+ if err := setProtoItem (tx , uidToMemberKey , member ); err != nil {
741+ return 0 , fmt .Errorf ("failed to set uid to member: %w" , err )
742+ }
737743
738744 val = []byte (uidStr )
739745 }
@@ -780,30 +786,29 @@ func (s *session) peekUID(ctx context.Context, tx fdb.ReadTransaction, member st
780786 return uid , nil
781787}
782788
783- func (s * session ) memberFromUID (ctx context.Context , tx fdb.ReadTransaction , uid uint64 ) (string , error ) {
789+ func (s * session ) memberFromUID (ctx context.Context , tx fdb.ReadTransaction , uid uint64 ) (* types. SetMember , error ) {
784790 ctx , span := s .tracer .Start (ctx , "memberFromUID" ) // nolint
785791 defer span .End ()
786792
787793 key , err := s .uidKey (strconv .FormatUint (uid , 10 ))
788794 if err != nil {
789795 span .RecordError (err )
790- return "" , fmt .Errorf ("failed to get uid key: %w" , err )
796+ return nil , fmt .Errorf ("failed to get uid key: %w" , err )
791797 }
792798
793- member , err := tx .Get (key ).Get ()
799+ member := & types.SetMember {}
800+ exists , err := getProtoItem (tx , key , member )
794801 if err != nil {
795- span .RecordError (err )
796- return "" , fmt .Errorf ("failed to get member for UID %d: %w" , uid , err )
802+ return nil , err
797803 }
798-
799- if len (member ) == 0 {
804+ if ! exists {
800805 err := fmt .Errorf ("uid %d not found" , uid )
801806 span .RecordError (err )
802- return "" , err
807+ return nil , err
803808 }
804809
805810 metrics .SpanOK (span )
806- return string ( member ) , nil
811+ return member , nil
807812}
808813
809814func parseVariadicArguments (args []resp.Value ) ([]string , error ) {
0 commit comments