Skip to content

Commit e3091a3

Browse files
authored
feat: Add ACLLog to rueidiscompat (#744)
* refactor: move ClientInfo to message layer for reusability * feat: Add ACLLog to rueidiscompat * refactor: move ClientInfo and ACLLogEntry from message.go
1 parent 93e9af3 commit e3091a3

File tree

3 files changed

+110
-13
lines changed

3 files changed

+110
-13
lines changed

rueidiscompat/adapter.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ type CoreCmdable interface {
415415
GeoHash(ctx context.Context, key string, members ...string) *StringSliceCmd
416416

417417
ACLDryRun(ctx context.Context, username string, command ...any) *StringCmd
418-
// TODO ACLLog(ctx context.Context, count int64) *ACLLogCmd
418+
ACLLog(ctx context.Context, count int64) *ACLLogCmd
419419
// TODO ACLLogReset(ctx context.Context) *StatusCmd
420420

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

3205+
func (c *Compat) ACLLog(ctx context.Context, count int64) *ACLLogCmd {
3206+
cmd := c.client.B().AclLog().Count(count).Build()
3207+
resp := c.client.Do(ctx, cmd)
3208+
return newACLLogCmd(resp)
3209+
}
3210+
32053211
func (c *Compat) doPrimaries(ctx context.Context, fn func(c rueidis.Client) error) error {
32063212
if c.pOnly {
32073213
return fn(c.client)

rueidiscompat/command.go

+97-12
Original file line numberDiff line numberDiff line change
@@ -4694,19 +4694,13 @@ func (cmd *ClientInfoCmd) Result() (*ClientInfo, error) {
46944694
return cmd.val, cmd.err
46954695
}
46964696

4697-
// fmt.Sscanf() cannot handle null values
4698-
func (cmd *ClientInfoCmd) from(res rueidis.RedisResult) {
4699-
txt, err := res.ToString()
4700-
if err != nil {
4701-
cmd.SetErr(err)
4702-
return
4703-
}
4697+
func stringToClientInfo(txt string) (*ClientInfo, error) {
47044698
info := &ClientInfo{}
4699+
var err error
47054700
for _, s := range strings.Split(strings.TrimPrefix(strings.TrimSpace(txt), "txt:"), " ") {
47064701
kv := strings.Split(s, "=")
47074702
if len(kv) != 2 {
4708-
cmd.SetErr(fmt.Errorf("redis: unexpected client info data (%s)", s))
4709-
return
4703+
return nil, fmt.Errorf("redis: unexpected client info data (%s)", s)
47104704
}
47114705
key, val := kv[0], kv[1]
47124706

@@ -4773,8 +4767,7 @@ func (cmd *ClientInfoCmd) from(res rueidis.RedisResult) {
47734767
case 'T':
47744768
info.Flags |= ClientNoTouch
47754769
default:
4776-
cmd.SetErr(fmt.Errorf("redis: unexpected client info flags(%s)", string(val[i])))
4777-
return
4770+
return nil, fmt.Errorf("redis: unexpected client info flags(%s)", string(val[i]))
47784771
}
47794772
}
47804773
case "db":
@@ -4825,13 +4818,105 @@ func (cmd *ClientInfoCmd) from(res rueidis.RedisResult) {
48254818
info.LibVer = val
48264819
}
48274820

4821+
if err != nil {
4822+
return nil, err
4823+
}
4824+
}
4825+
return info, nil
4826+
}
4827+
4828+
// fmt.Sscanf() cannot handle null values
4829+
func (cmd *ClientInfoCmd) from(res rueidis.RedisResult) {
4830+
txt, err := res.ToString()
4831+
if err != nil {
4832+
cmd.SetErr(err)
4833+
return
4834+
}
4835+
info, err := stringToClientInfo(txt)
4836+
if err != nil {
4837+
cmd.SetErr(err)
4838+
return
4839+
}
4840+
4841+
cmd.SetVal(info)
4842+
}
4843+
4844+
type ACLLogEntry struct {
4845+
Count int64
4846+
Reason string
4847+
Context string
4848+
Object string
4849+
Username string
4850+
AgeSeconds float64
4851+
ClientInfo *ClientInfo
4852+
EntryID int64
4853+
TimestampCreated int64
4854+
TimestampLastUpdated int64
4855+
}
4856+
4857+
type ACLLogCmd struct {
4858+
baseCmd[[]*ACLLogEntry]
4859+
}
4860+
4861+
func (cmd *ACLLogCmd) from(res rueidis.RedisResult) {
4862+
arr, err := res.ToArray()
4863+
if err != nil {
4864+
cmd.SetErr(err)
4865+
return
4866+
}
4867+
4868+
logEntries := make([]*ACLLogEntry, 0, len(arr))
4869+
for _, msg := range arr {
4870+
log, err := msg.AsMap()
4871+
if err != nil {
4872+
cmd.SetErr(err)
4873+
return
4874+
}
4875+
entry := ACLLogEntry{}
4876+
4877+
for key, attr := range log {
4878+
switch key {
4879+
case "count":
4880+
entry.Count, err = attr.AsInt64()
4881+
case "reason":
4882+
entry.Reason, err = attr.ToString()
4883+
case "context":
4884+
entry.Context, err = attr.ToString()
4885+
case "object":
4886+
entry.Object, err = attr.ToString()
4887+
case "username":
4888+
entry.Username, err = attr.ToString()
4889+
case "age-seconds":
4890+
entry.AgeSeconds, err = attr.AsFloat64()
4891+
case "client-info":
4892+
txt, txtErr := attr.ToString()
4893+
if txtErr == nil {
4894+
entry.ClientInfo, err = stringToClientInfo(txt)
4895+
} else {
4896+
err = txtErr
4897+
}
4898+
case "entry-id":
4899+
entry.EntryID, err = attr.AsInt64()
4900+
case "timestamp-created":
4901+
entry.TimestampCreated, err = attr.AsInt64()
4902+
case "timestamp-last-updated":
4903+
entry.TimestampLastUpdated, err = attr.AsInt64()
4904+
}
4905+
}
4906+
48284907
if err != nil {
48294908
cmd.SetErr(err)
48304909
return
48314910
}
4911+
logEntries = append(logEntries, &entry)
48324912
}
4913+
cmd.SetVal(logEntries)
4914+
}
48334915

4834-
cmd.SetVal(info)
4916+
func newACLLogCmd(res rueidis.RedisResult) *ACLLogCmd {
4917+
cmd := &ACLLogCmd{}
4918+
cmd.from(res)
4919+
return cmd
48354920
}
48364921

48374922
// ModuleLoadexConfig struct is used to specify the arguments for the MODULE LOADEX command of redis.

rueidiscompat/pipeline.go

+6
Original file line numberDiff line numberDiff line change
@@ -2089,6 +2089,12 @@ func (c *Pipeline) ACLDryRun(ctx context.Context, username string, command ...an
20892089
return ret
20902090
}
20912091

2092+
func (c *Pipeline) ACLLog(ctx context.Context, count int64) *ACLLogCmd {
2093+
ret := c.comp.ACLLog(ctx, count)
2094+
c.rets = append(c.rets, ret)
2095+
return ret
2096+
}
2097+
20922098
func (c *Pipeline) TFunctionLoad(ctx context.Context, lib string) *StatusCmd {
20932099
ret := c.comp.TFunctionLoad(ctx, lib)
20942100
c.rets = append(c.rets, ret)

0 commit comments

Comments
 (0)