Skip to content

Commit 2e41b79

Browse files
authored
bugfix: miss to uncommit the last limiter in resty.limit.traffic's list (#54)
1 parent 2c5a231 commit 2e41b79

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

lib/resty/limit/traffic.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ function _M.combine(limiters, keys, states)
4242
-- we intentionally ignore any errors returned below.
4343
limiters[j]:uncommit(keys[j])
4444
end
45+
limiters[n]:uncommit(keys[n])
4546
return nil, err
4647
end
4748
if states then

t/traffic.t

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,3 +280,79 @@ state lim3: 2
280280
--- no_error_log
281281
[error]
282282
[lua]
283+
284+
285+
286+
=== TEST 5: sanity (uncommit() the previous limiters and the last limiter if a limiter rejects while committing a state)
287+
--- http_config eval: $::HttpConfig
288+
--- config
289+
location = /t {
290+
content_by_lua_block {
291+
local limit_traffic = require "resty.limit.traffic"
292+
293+
local limit_mock = {}
294+
limit_mock.__index = limit_mock
295+
296+
function limit_mock.new(_, _, reject_on_commit)
297+
return setmetatable({
298+
counters = {},
299+
reject_on_commit = reject_on_commit,
300+
}, limit_mock)
301+
end
302+
303+
function limit_mock:incoming(key, commit)
304+
local count = self.counters[key] or 0
305+
306+
count = count + 1
307+
308+
if commit then
309+
self.counters[key] = count
310+
311+
if self.reject_on_commit then
312+
return nil, "rejected by mock limiter"
313+
end
314+
end
315+
316+
return count
317+
end
318+
319+
function limit_mock:uncommit(key)
320+
local count = self.counters[key] or 0
321+
if count > 0 then
322+
count = count - 1
323+
end
324+
325+
self.counters[key] = count
326+
end
327+
328+
local lim1 = limit_mock.new(nil, 2)
329+
local lim2 = limit_mock.new(nil, 2, true)
330+
local lim3 = limit_mock.new(nil, 2)
331+
local lim4 = limit_mock.new(nil, 2)
332+
333+
local limiters = {lim1, lim2, lim3, lim4}
334+
335+
local keys = {"foo", "bar", "baz", "bat"}
336+
337+
local delay, err = limit_traffic.combine(limiters, keys)
338+
if not delay then
339+
ngx.say(err)
340+
end
341+
342+
ngx.say("state lim1: ", lim1:incoming(keys[1])) -- should be 1 because previous combine() call was uncommitted
343+
ngx.say("state lim2: ", lim2:incoming(keys[2]))
344+
ngx.say("state lim3: ", lim3:incoming(keys[3])) -- should be 1 because previous combine() call was uncommitted
345+
ngx.say("state lim4: ", lim4:incoming(keys[4])) -- should be 1 because previous combine() call was uncommitted
346+
}
347+
}
348+
--- request
349+
GET /t
350+
--- response_body
351+
rejected by mock limiter
352+
state lim1: 1
353+
state lim2: 2
354+
state lim3: 1
355+
state lim4: 1
356+
--- no_error_log
357+
[error]
358+
[lua]

0 commit comments

Comments
 (0)