diff --git a/redis/command_type.go b/redis/command_type.go index 0bd85d3..c0c7576 100644 --- a/redis/command_type.go +++ b/redis/command_type.go @@ -53,7 +53,7 @@ var replicaSafe = makeSet(strings.Split( "SCARD SDIFF SINTER SISMEMBER SMEMBERS SRANDMEMBER STRLEN SUNION "+ "ZCARD ZCOUNT ZLEXCOUNT ZRANGE ZRANGEBYLEX ZREVRANGEBYLEX "+ "ZRANGEBYSCORE ZRANK ZREVRANGE ZREVRANGEBYSCORE ZREVRANK ZSCORE "+ - "XPENDING XREVRANGE XREAD XLEN ", " ")) + "XPENDING XREVRANGE XREAD XLEN FCALL_RO", " ")) // ReplicaSafe returns true if command is readonly and "safe to run on replica". // Some commands like "scan" are not included, because their result could differ between diff --git a/redis/request.go b/redis/request.go index cd94898..33cf255 100644 --- a/redis/request.go +++ b/redis/request.go @@ -41,6 +41,8 @@ func (r Request) Key() (string, bool) { } var n int switch r.Cmd { + case "FCALL", "FCALL_RO": + n = 2 case "EVAL", "EVALSHA": n = 2 case "BITOP": @@ -63,6 +65,8 @@ func (r Request) KeyByte() ([]byte, bool) { } var n int switch r.Cmd { + case "FCALL", "FCALL_RO": + n = 2 case "EVAL", "EVALSHA": n = 2 case "BITOP": diff --git a/redis/request_test.go b/redis/request_test.go index 8437937..6a41f40 100644 --- a/redis/request_test.go +++ b/redis/request_test.go @@ -34,11 +34,59 @@ func TestRequestKey(t *testing.T) { assert.Equal(t, "2", k) assert.True(t, ok) + k, ok = Req("FCALL", "foo", 1, 2, 3).Key() + assert.Equal(t, "2", k) + assert.True(t, ok) + + k, ok = Req("FCALL_RO", "foo", 1, 2, 3).Key() + assert.Equal(t, "2", k) + assert.True(t, ok) + k, ok = Req("BITOP", "AND", 1, 2).Key() assert.Equal(t, "1", k) assert.True(t, ok) } +func TestRequestKeyByte(t *testing.T) { + var k []byte + var ok bool + + k, ok = Req("GET", 1).KeyByte() + assert.Equal(t, []byte("1"), k) + assert.True(t, ok) + + _, ok = Req("GET").Key() + assert.False(t, ok) + + k, ok = Req("SET", 1, 2).KeyByte() + assert.Equal(t, []byte("1"), k) + assert.True(t, ok) + + k, ok = Req("RANDOMKEY").KeyByte() + assert.Equal(t, []byte("RANDOMKEY"), k) + assert.False(t, ok) + + k, ok = Req("EVAL", "return KEY[1]", 1, 2, 3).KeyByte() + assert.Equal(t, []byte("2"), k) + assert.True(t, ok) + + k, ok = Req("EVALSHA", "1234abcdef", 1, 2, 3).KeyByte() + assert.Equal(t, []byte("2"), k) + assert.True(t, ok) + + k, ok = Req("FCALL", "foo", 1, 2, 3).KeyByte() + assert.Equal(t, []byte("2"), k) + assert.True(t, ok) + + k, ok = Req("FCALL_RO", "foo", 1, 2, 3).KeyByte() + assert.Equal(t, []byte("2"), k) + assert.True(t, ok) + + k, ok = Req("BITOP", "AND", 1, 2).KeyByte() + assert.Equal(t, []byte("1"), k) + assert.True(t, ok) +} + func TestArgToString(t *testing.T) { var k string var ok bool