Redis Lua脚本未按预期工作

作为练习,我正在为 Redis 编写一个 Lua 脚本,基本上执行 JavaScript 方法 Array#copyWithin()

引用 MDN 中的话,

copyWithin() 方法将数组内从第二个参数和第三个参数所指的位置浅拷贝到其它位置,可以替换原有内容。第一个参数表示开始拷贝的目标位置。

这是我到目前为止编写的脚本:

local list = redis.call('lrange', KEYS [1], 0-1local target = tonumber(ARGV [1])
local startIndex = tonumber(ARGV [2])
local len =#list
local endIndex = len

--处理负的startIndex
if startIndex <0 then
    startIndex = len + startIndex
end

--如果提供了第三个参数,则从中获取endIndex
if#ARGV> 2 then
    local arg = tonumber(ARGV [3])
    if arg> = 0 then
        if arg <endIndex then
            endIndex = arg
        end
    别的
        if len + arg> = 0 then
            endIndex = len + arg
        别的
            endIndex = 0
        end
    end
end

--包含将被复制的元素的数组
local targeted_elements = {}

--从列表中填充元素
for i = 1,(endIndex-startIndex + 1do
    targeted_elements [i] = list [startIndex + i]
end

--确保不会发生范围溢出时将额外元素推到数组的末端
local target_end =#targeted_elements

if target + target_end> len then
    target_end = len-target
end

--替换Redis中列表的所有更改元素
for i = 1,target_end do
    redis.call('lset', KEYS [1], target +(i-1),targeted_elements [i])
end

在测试期间,第一个测试用例成功清除了:

测试用例:将 [1、2、3、4、5] 转换为 [4、5、3、4、5],使用 copyWithin(0, 3)

LRANGE MyList 0 -1
> [1、2、3、4、5]

EVALSHA "sha1 of script" 1 MyList 0 3
(基本上与 `[1、2、3、4、5].copyWithin(0,3)` 相同)
>

LRANGE MyList 0 -1
> [4、5、3、4、5]

然而,第二个测试用例并没有那么顺利。

测试用例:将 [1、2、3、4、5] 转换为 [4、2、3、4、5],使用 copyWithin(0,3,4)

LRANGE MyList 0 -1
> [1、2、3、4、5]

EVALSHA "sha1 of script" 1 MyList 0 3 4
(基本上与 `[1、2、3、4、5].copyWithin(0,3,4)` 相同)
>

LRANGE MyList 0 -1
> [4、5、3、4、5]

经过一些调试,我发现 targeted_elements 的值在两种情况下均为 {4,5},而在第二种情况下应为 {4}

循环中有可疑的地方吗? 任何帮助将是伟大的。

点赞
用户3613282
用户3613282

我通过修改脚本中以下部分来解决这个问题:

--Fill elements from the list
for i=1, (endIndex-startIndex+1) do
    targeted_elements[i] = list[startIndex+i]
end

修改成了这样:

--Fill elements from the list
    for i=1, (endIndex-startIndex) do
        targeted_elements[i] = list[startIndex+i]
    end

for 表达式中的 +1 为数组添加了一个额外的元素。它在第一种情况下起作用,因为所选部分是 3, 5,所以 5-3+1=3,这意味着应选择 3 个元素。但由于只剩下 2 个元素,所以该情况仍然有效。

而对于第二种情况,4-3+1=2,这意味着选择了 2 个元素,而不是 1 个元素。

2015-08-02 12:51:37