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

Add client tracking and client trackinginfo commands #2868

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
91 changes: 91 additions & 0 deletions commands.go
Expand Up @@ -236,6 +236,12 @@ type StatefulCmdable interface {
SwapDB(ctx context.Context, index1, index2 int) *StatusCmd
ClientSetName(ctx context.Context, name string) *BoolCmd
ClientSetInfo(ctx context.Context, info LibraryInfo) *StatusCmd
ClientTracking(ctx context.Context, on bool, options *ClientTrackingOptions) *StatusCmd
ClientTrackingOn(ctx context.Context) *StatusCmd
ClientTrackingOff(ctx context.Context) *StatusCmd
ClientTrackingOnWithArgs(ctx context.Context, options *ClientTrackingOptions) *StatusCmd
ClientTrackingOffWithArgs(ctx context.Context, options *ClientTrackingOptions) *StatusCmd
ClientTrackingInfo(ctx context.Context) *MapStringInterfaceCmd
Hello(ctx context.Context, ver int, username, password, clientName string) *MapStringInterfaceCmd
}

Expand Down Expand Up @@ -319,6 +325,91 @@ func (c statefulCmdable) ClientSetInfo(ctx context.Context, info LibraryInfo) *S
return cmd
}

type ClientTrackingOptions struct {
ClientID int
Prefixes []interface{}
BCast bool
OptIn bool
OptOut bool
NoLoop bool
}

// Enables the tracking feature of the Redis server, that is used
// for server assisted client side caching.
// “on“ indicate for tracking on or tracking off. The dafualt is on.
// “clientid“ send invalidation messages to the connection with
// the specified ID.
// “bcast“ enable tracking in broadcasting mode. In this mode
// invalidation messages are reported for all the prefixes
// specified, regardless of the keys requested by the connection.
// “optin“ when broadcasting is NOT active, normally don't track
// keys in read only commands, unless they are called immediately
// after a CLIENT CACHING yes command.
// “optout“ when broadcasting is NOT active, normally track keys in
// read only commands, unless they are called immediately after a
// CLIENT CACHING no command.
// “noloop“ don't send notifications about keys modified by this
// connection itself.
// “prefixes“ for broadcasting, register a given key prefix, so that
// notifications will be provided only for keys starting with this string.
// For more innformation - https://redis.io/commands/client-tracking
func (c statefulCmdable) ClientTracking(ctx context.Context, on bool, options *ClientTrackingOptions) *StatusCmd {
args := []interface{}{"CLIENT", "TRACKING"}
if on {
args = append(args, "ON")
} else {
args = append(args, "OFF")
}
if options != nil {
if options.Prefixes != nil && !options.BCast {
panic("prefixes can only be used with BCast")
}
if options.ClientID != 0 {
args = append(args, "REDIRECT", options.ClientID)
}
for _, prefix := range options.Prefixes {
args = append(args, "PREFIX", prefix)
}
if options.BCast {
args = append(args, "BCAST")
}
if options.OptIn {
args = append(args, "OPTIN")
}
if options.OptOut {
args = append(args, "OPTOUT")
}
if options.NoLoop {
args = append(args, "NOLOOP")
}
}
cmd := NewStatusCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}

func (c statefulCmdable) ClientTrackingOn(ctx context.Context) *StatusCmd {
return c.ClientTracking(ctx, true, nil)
}

func (c statefulCmdable) ClientTrackingOff(ctx context.Context) *StatusCmd {
return c.ClientTracking(ctx, false, nil)
}

func (c statefulCmdable) ClientTrackingOnWithArgs(ctx context.Context, options *ClientTrackingOptions) *StatusCmd {
return c.ClientTracking(ctx, true, options)
}

func (c statefulCmdable) ClientTrackingOffWithArgs(ctx context.Context, options *ClientTrackingOptions) *StatusCmd {
return c.ClientTracking(ctx, false, options)
}

func (c statefulCmdable) ClientTrackingInfo(ctx context.Context) *MapStringInterfaceCmd {
cmd := NewMapStringInterfaceCmd(ctx, "CLIENT", "TRACKINGINFO")
_ = c(ctx, cmd)
return cmd
}

// Validate checks if only one field in the struct is non-nil.
func (info LibraryInfo) Validate() error {
if info.LibName != nil && info.LibVer != nil {
Expand Down
6 changes: 6 additions & 0 deletions commands_test.go
Expand Up @@ -243,6 +243,12 @@ var _ = Describe("Commands", func() {
Expect(get.Val()).To(Equal("theclientname"))
})

It("should ClientTrackingInfo", func() {
clientTrackingInfo, err := client.Conn().ClientTrackingInfo(ctx).Result()
Expect(err).NotTo(HaveOccurred())
Expect(clientTrackingInfo["prefixes"]).To(Equal([]interface{}{}))
})

It("should ClientSetInfo", func() {
pipe := client.Pipeline()

Expand Down