Skip to content

Commit

Permalink
feat: Add ACLLog to rueidiscompat (#744)
Browse files Browse the repository at this point in the history
* refactor: move ClientInfo to message layer for reusability

* feat: Add ACLLog to rueidiscompat

* refactor: move ClientInfo and ACLLogEntry from message.go
  • Loading branch information
blueBlue0102 authored Feb 9, 2025
1 parent 93e9af3 commit e3091a3
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 13 deletions.
8 changes: 7 additions & 1 deletion rueidiscompat/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ type CoreCmdable interface {
GeoHash(ctx context.Context, key string, members ...string) *StringSliceCmd

ACLDryRun(ctx context.Context, username string, command ...any) *StringCmd
// TODO ACLLog(ctx context.Context, count int64) *ACLLogCmd
ACLLog(ctx context.Context, count int64) *ACLLogCmd
// TODO ACLLogReset(ctx context.Context) *StatusCmd

ModuleLoadex(ctx context.Context, conf *ModuleLoadexConfig) *StringCmd
Expand Down Expand Up @@ -3202,6 +3202,12 @@ func (c *Compat) ACLDryRun(ctx context.Context, username string, command ...any)
return newStringCmd(resp)
}

func (c *Compat) ACLLog(ctx context.Context, count int64) *ACLLogCmd {
cmd := c.client.B().AclLog().Count(count).Build()
resp := c.client.Do(ctx, cmd)
return newACLLogCmd(resp)
}

func (c *Compat) doPrimaries(ctx context.Context, fn func(c rueidis.Client) error) error {
if c.pOnly {
return fn(c.client)
Expand Down
109 changes: 97 additions & 12 deletions rueidiscompat/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -4694,19 +4694,13 @@ func (cmd *ClientInfoCmd) Result() (*ClientInfo, error) {
return cmd.val, cmd.err
}

// fmt.Sscanf() cannot handle null values
func (cmd *ClientInfoCmd) from(res rueidis.RedisResult) {
txt, err := res.ToString()
if err != nil {
cmd.SetErr(err)
return
}
func stringToClientInfo(txt string) (*ClientInfo, error) {
info := &ClientInfo{}
var err error
for _, s := range strings.Split(strings.TrimPrefix(strings.TrimSpace(txt), "txt:"), " ") {
kv := strings.Split(s, "=")
if len(kv) != 2 {
cmd.SetErr(fmt.Errorf("redis: unexpected client info data (%s)", s))
return
return nil, fmt.Errorf("redis: unexpected client info data (%s)", s)
}
key, val := kv[0], kv[1]

Expand Down Expand Up @@ -4773,8 +4767,7 @@ func (cmd *ClientInfoCmd) from(res rueidis.RedisResult) {
case 'T':
info.Flags |= ClientNoTouch
default:
cmd.SetErr(fmt.Errorf("redis: unexpected client info flags(%s)", string(val[i])))
return
return nil, fmt.Errorf("redis: unexpected client info flags(%s)", string(val[i]))
}
}
case "db":
Expand Down Expand Up @@ -4825,13 +4818,105 @@ func (cmd *ClientInfoCmd) from(res rueidis.RedisResult) {
info.LibVer = val
}

if err != nil {
return nil, err
}
}
return info, nil
}

// fmt.Sscanf() cannot handle null values
func (cmd *ClientInfoCmd) from(res rueidis.RedisResult) {
txt, err := res.ToString()
if err != nil {
cmd.SetErr(err)
return
}
info, err := stringToClientInfo(txt)
if err != nil {
cmd.SetErr(err)
return
}

cmd.SetVal(info)
}

type ACLLogEntry struct {
Count int64
Reason string
Context string
Object string
Username string
AgeSeconds float64
ClientInfo *ClientInfo
EntryID int64
TimestampCreated int64
TimestampLastUpdated int64
}

type ACLLogCmd struct {
baseCmd[[]*ACLLogEntry]
}

func (cmd *ACLLogCmd) from(res rueidis.RedisResult) {
arr, err := res.ToArray()
if err != nil {
cmd.SetErr(err)
return
}

logEntries := make([]*ACLLogEntry, 0, len(arr))
for _, msg := range arr {
log, err := msg.AsMap()
if err != nil {
cmd.SetErr(err)
return
}
entry := ACLLogEntry{}

for key, attr := range log {
switch key {
case "count":
entry.Count, err = attr.AsInt64()
case "reason":
entry.Reason, err = attr.ToString()
case "context":
entry.Context, err = attr.ToString()
case "object":
entry.Object, err = attr.ToString()
case "username":
entry.Username, err = attr.ToString()
case "age-seconds":
entry.AgeSeconds, err = attr.AsFloat64()
case "client-info":
txt, txtErr := attr.ToString()
if txtErr == nil {
entry.ClientInfo, err = stringToClientInfo(txt)
} else {
err = txtErr
}
case "entry-id":
entry.EntryID, err = attr.AsInt64()
case "timestamp-created":
entry.TimestampCreated, err = attr.AsInt64()
case "timestamp-last-updated":
entry.TimestampLastUpdated, err = attr.AsInt64()
}
}

if err != nil {
cmd.SetErr(err)
return
}
logEntries = append(logEntries, &entry)
}
cmd.SetVal(logEntries)
}

cmd.SetVal(info)
func newACLLogCmd(res rueidis.RedisResult) *ACLLogCmd {
cmd := &ACLLogCmd{}
cmd.from(res)
return cmd
}

// ModuleLoadexConfig struct is used to specify the arguments for the MODULE LOADEX command of redis.
Expand Down
6 changes: 6 additions & 0 deletions rueidiscompat/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -2089,6 +2089,12 @@ func (c *Pipeline) ACLDryRun(ctx context.Context, username string, command ...an
return ret
}

func (c *Pipeline) ACLLog(ctx context.Context, count int64) *ACLLogCmd {
ret := c.comp.ACLLog(ctx, count)
c.rets = append(c.rets, ret)
return ret
}

func (c *Pipeline) TFunctionLoad(ctx context.Context, lib string) *StatusCmd {
ret := c.comp.TFunctionLoad(ctx, lib)
c.rets = append(c.rets, ret)
Expand Down

0 comments on commit e3091a3

Please sign in to comment.