Skip to content

Commit 60517af

Browse files
committed
feature: shdict:incr(): added the "exptime" argument to set the expiry
of values when they are first created via the "init" argument.
1 parent f7a1f94 commit 60517af

File tree

3 files changed

+269
-10
lines changed

3 files changed

+269
-10
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ install:
5959
- git clone https://github.com/openresty/openresty.git ../openresty
6060
- git clone https://github.com/openresty/openresty-devel-utils.git
6161
- git clone https://github.com/simpl/ngx_devel_kit.git ../ndk-nginx-module
62-
- git clone https://github.com/openresty/lua-nginx-module.git ../lua-nginx-module
62+
- git clone -b feat/incr-exptime-ffi https://github.com/thibaultcha/lua-nginx-module.git ../lua-nginx-module
6363
- git clone https://github.com/openresty/no-pool-nginx.git ../no-pool-nginx
6464
- git clone https://github.com/openresty/echo-nginx-module.git ../echo-nginx-module
6565
- git clone https://github.com/openresty/lua-resty-lrucache.git

lib/resty/core/shdict.lua

+24-9
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ ffi.cdef[[
2929

3030
int ngx_http_lua_ffi_shdict_incr(void *zone, const unsigned char *key,
3131
size_t key_len, double *value, char **err, int has_init, double init,
32-
int *forcible);
32+
long init_ttl, int *forcible);
3333

3434
int ngx_http_lua_ffi_shdict_store(void *zone, int op,
3535
const unsigned char *key, size_t key_len, int value_type,
@@ -337,7 +337,7 @@ local function shdict_get_stale(zone, key)
337337
end
338338

339339

340-
local function shdict_incr(zone, key, value, init)
340+
local function shdict_incr(zone, key, value, init, init_ttl)
341341
zone = check_zone(zone)
342342

343343
if key == nil then
@@ -361,8 +361,6 @@ local function shdict_incr(zone, key, value, init)
361361
end
362362
num_value[0] = value
363363

364-
local has_init
365-
366364
if init then
367365
local typ = type(init)
368366
if typ ~= "number" then
@@ -372,22 +370,39 @@ local function shdict_incr(zone, key, value, init)
372370
return error("bad init arg: number expected, got " .. typ)
373371
end
374372
end
373+
end
375374

376-
has_init = 1
375+
if init_ttl ~= nil then
376+
local typ = type(init_ttl)
377+
if typ ~= "number" then
378+
init_ttl = tonumber(init_ttl)
379+
380+
if not init_ttl then
381+
error("bad init_ttl arg: number expected, got " .. typ, 2)
382+
end
383+
end
384+
385+
if init_ttl < 0 then
386+
error('bad "init_ttl" argument', 2)
387+
end
388+
389+
if not init then
390+
error('must provide "init" when providing "init_ttl"', 2)
391+
end
377392

378393
else
379-
has_init = 0
380-
init = 0
394+
init_ttl = 0
381395
end
382396

383397
local rc = C.ngx_http_lua_ffi_shdict_incr(zone, key, key_len, num_value,
384-
errmsg, has_init, init,
398+
errmsg, init and 1 or 0,
399+
init or 0, init_ttl * 1000,
385400
forcible)
386401
if rc ~= 0 then -- ~= NGX_OK
387402
return nil, ffi_str(errmsg[0])
388403
end
389404

390-
if has_init == 0 then
405+
if not init then
391406
return tonumber(num_value[0])
392407
end
393408

t/shdict.t

+244
Original file line numberDiff line numberDiff line change
@@ -1284,3 +1284,247 @@ free_page_bytes: (?:0|32768)
12841284
[error]
12851285
[alert]
12861286
[crit]
1287+
1288+
1289+
1290+
=== TEST 39: incr bad init_ttl argument
1291+
--- http_config eval: $::HttpConfig
1292+
--- config
1293+
location = /t {
1294+
content_by_lua_block {
1295+
local dogs = ngx.shared.dogs
1296+
local pok, err = pcall(dogs.incr, dogs, "foo", 1, 0, -1)
1297+
if not pok then
1298+
ngx.say("not ok: ", err)
1299+
return
1300+
end
1301+
1302+
ngx.say("ok")
1303+
}
1304+
}
1305+
--- request
1306+
GET /t
1307+
--- response_body
1308+
not ok: bad "init_ttl" argument
1309+
--- no_error_log
1310+
[error]
1311+
[alert]
1312+
[crit]
1313+
1314+
1315+
1316+
=== TEST 40: incr init_ttl argument is not a number
1317+
--- http_config eval: $::HttpConfig
1318+
--- config
1319+
location = /t {
1320+
content_by_lua_block {
1321+
local dogs = ngx.shared.dogs
1322+
local pok, err = pcall(dogs.incr, dogs, "foo", 1, 0, "bar")
1323+
if not pok then
1324+
ngx.say("not ok: ", err)
1325+
return
1326+
end
1327+
1328+
ngx.say("ok")
1329+
}
1330+
}
1331+
--- request
1332+
GET /t
1333+
--- response_body
1334+
not ok: bad init_ttl arg: number expected, got string
1335+
--- no_error_log
1336+
[error]
1337+
[alert]
1338+
[crit]
1339+
1340+
1341+
1342+
=== TEST 41: incr init_ttl argument without init
1343+
--- http_config eval: $::HttpConfig
1344+
--- config
1345+
location = /t {
1346+
content_by_lua_block {
1347+
local dogs = ngx.shared.dogs
1348+
local pok, err = pcall(dogs.incr, dogs, "foo", 1, nil, 0.001)
1349+
if not pok then
1350+
ngx.say("not ok: ", err)
1351+
return
1352+
end
1353+
1354+
ngx.say("ok")
1355+
}
1356+
}
1357+
--- request
1358+
GET /t
1359+
--- response_body
1360+
not ok: must provide "init" when providing "init_ttl"
1361+
--- no_error_log
1362+
[error]
1363+
[alert]
1364+
[crit]
1365+
1366+
1367+
1368+
=== TEST 42: incr key with init_ttl (key exists)
1369+
--- http_config eval: $::HttpConfig
1370+
--- config
1371+
location = /t {
1372+
content_by_lua_block {
1373+
local dogs = ngx.shared.dogs
1374+
dogs:set("foo", 32)
1375+
1376+
local res, err = dogs:incr("foo", 10502, 0, 0.001)
1377+
ngx.say("incr: ", res, " ", err)
1378+
ngx.say("foo = ", dogs:get("foo"))
1379+
1380+
ngx.sleep(0.002)
1381+
1382+
ngx.say("foo after incr init_ttl = ", dogs:get("foo"))
1383+
}
1384+
}
1385+
--- request
1386+
GET /t
1387+
--- response_body
1388+
incr: 10534 nil
1389+
foo = 10534
1390+
foo after incr init_ttl = 10534
1391+
--- no_error_log
1392+
[error]
1393+
[alert]
1394+
[crit]
1395+
1396+
1397+
1398+
=== TEST 43: incr key with init and init_ttl (key not exists)
1399+
--- http_config eval: $::HttpConfig
1400+
--- config
1401+
location = /t {
1402+
content_by_lua_block {
1403+
local dogs = ngx.shared.dogs
1404+
dogs:flush_all()
1405+
1406+
local res, err = dogs:incr("foo", 10502, 1, 0.001)
1407+
ngx.say("incr: ", res, " ", err)
1408+
ngx.say("foo = ", dogs:get("foo"))
1409+
1410+
ngx.sleep(0.002)
1411+
1412+
ngx.say("foo after init_ttl = ", dogs:get("foo"))
1413+
}
1414+
}
1415+
--- request
1416+
GET /t
1417+
--- response_body
1418+
incr: 10503 nil
1419+
foo = 10503
1420+
foo after init_ttl = nil
1421+
--- no_error_log
1422+
[error]
1423+
[alert]
1424+
[crit]
1425+
1426+
1427+
1428+
=== TEST 44: incr key with init and init_ttl as string (key not exists)
1429+
--- http_config eval: $::HttpConfig
1430+
--- config
1431+
location = /t {
1432+
content_by_lua_block {
1433+
local dogs = ngx.shared.dogs
1434+
dogs:flush_all()
1435+
1436+
local res, err = dogs:incr("foo", 10502, 1, "0.001")
1437+
ngx.say("incr: ", res, " ", err)
1438+
ngx.say("foo = ", dogs:get("foo"))
1439+
1440+
ngx.sleep(0.002)
1441+
1442+
ngx.say("foo after init_ttl = ", dogs:get("foo"))
1443+
}
1444+
}
1445+
--- request
1446+
GET /t
1447+
--- response_body
1448+
incr: 10503 nil
1449+
foo = 10503
1450+
foo after init_ttl = nil
1451+
--- no_error_log
1452+
[error]
1453+
[alert]
1454+
[crit]
1455+
1456+
1457+
1458+
=== TEST 45: incr key with init and init_ttl (key expired and size matched)
1459+
--- http_config eval: $::HttpConfig
1460+
--- config
1461+
location = /t {
1462+
content_by_lua_block {
1463+
local dogs = ngx.shared.dogs
1464+
for i = 1, 20 do
1465+
dogs:set("bar" .. i, i, 0.002)
1466+
end
1467+
dogs:set("foo", 32, 0.002)
1468+
ngx.sleep(0.003)
1469+
1470+
local res, err = dogs:incr("foo", 10502, 0, 0.001)
1471+
ngx.say("incr: ", res, " ", err)
1472+
ngx.say("foo = ", dogs:get("foo"))
1473+
1474+
ngx.sleep(0.002)
1475+
1476+
ngx.say("foo after init_ttl = ", dogs:get("foo"))
1477+
}
1478+
}
1479+
--- request
1480+
GET /t
1481+
--- response_body
1482+
incr: 10502 nil
1483+
foo = 10502
1484+
foo after init_ttl = nil
1485+
--- no_error_log
1486+
[error]
1487+
[alert]
1488+
[crit]
1489+
1490+
1491+
1492+
=== TEST 46: incr key with init and init_ttl (forcibly override other valid entries)
1493+
--- http_config eval: $::HttpConfig
1494+
--- config
1495+
location = /t {
1496+
content_by_lua_block {
1497+
local dogs = ngx.shared.dogs
1498+
dogs:flush_all()
1499+
1500+
local long_prefix = string.rep("1234567890", 100)
1501+
for i = 1, 1000 do
1502+
local success, err, forcible = dogs:set(long_prefix .. i, i)
1503+
if forcible then
1504+
dogs:delete(long_prefix .. i)
1505+
break
1506+
end
1507+
end
1508+
1509+
local res, err, forcible = dogs:incr(long_prefix .. "bar", 10502, 0)
1510+
ngx.say("incr: ", res, " ", err, " ", forcible)
1511+
1512+
local res, err, forcible = dogs:incr(long_prefix .. "foo", 10502, 0, 0.001)
1513+
ngx.say("incr: ", res, " ", err, " ", forcible)
1514+
ngx.say("foo = ", dogs:get(long_prefix .. "foo"))
1515+
1516+
ngx.sleep(0.002)
1517+
ngx.say("foo after init_ttl = ", dogs:get("foo"))
1518+
}
1519+
}
1520+
--- request
1521+
GET /t
1522+
--- response_body
1523+
incr: 10502 nil false
1524+
incr: 10502 nil true
1525+
foo = 10502
1526+
foo after init_ttl = nil
1527+
--- no_error_log
1528+
[error]
1529+
[alert]
1530+
[crit]

0 commit comments

Comments
 (0)