ioredis-toolkit 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
-- create.lua (version 1)
|
|
2
2
|
-- Atomically creates a session record, registers it in the user index
|
|
3
|
-
-- (ZSET, score =
|
|
4
|
-
--
|
|
3
|
+
-- (ZSET, score = microsecond-resolution Redis server time, used purely
|
|
4
|
+
-- for eviction ordering - see below), optionally claims an idempotency
|
|
5
|
+
-- key, and enforces maxSessionsPerUser with bounded oldest-first eviction.
|
|
5
6
|
--
|
|
6
7
|
-- KEYS[1] = session record key
|
|
7
8
|
-- KEYS[2] = user session index key (ZSET)
|
|
@@ -44,7 +45,21 @@ if redis.call('EXISTS', key) == 1 then
|
|
|
44
45
|
end
|
|
45
46
|
|
|
46
47
|
redis.call('SET', key, ARGV[1], 'EX', tonumber(ARGV[4]))
|
|
47
|
-
|
|
48
|
+
|
|
49
|
+
-- The user index score is used purely for oldest-first eviction ordering
|
|
50
|
+
-- (never as the record's createdAt, which is app-stamped seconds inside the
|
|
51
|
+
-- envelope). Redis breaks equal ZSET scores by lexicographic member order,
|
|
52
|
+
-- not insertion order, so scoring by second-granularity createdAt would
|
|
53
|
+
-- make eviction pick an arbitrary (jti-lexicographic) session rather than
|
|
54
|
+
-- the actual oldest one whenever a user creates more than one session in
|
|
55
|
+
-- the same wall-clock second - a realistic case under normal traffic, not
|
|
56
|
+
-- just a burst edge case. Redis is single-threaded, so two scripts touching
|
|
57
|
+
-- the same user slot never observe the same TIME() reading in practice;
|
|
58
|
+
-- microsecond-resolution server time therefore gives a strictly monotonic,
|
|
59
|
+
-- clock-skew-free ordering key for this user's index.
|
|
60
|
+
local t = redis.call('TIME')
|
|
61
|
+
local orderScore = tonumber(t[1]) + (tonumber(t[2]) / 1000000)
|
|
62
|
+
redis.call('ZADD', index, orderScore, ARGV[2])
|
|
48
63
|
|
|
49
64
|
local evicted = {}
|
|
50
65
|
local limit = tonumber(ARGV[5])
|
|
@@ -37,7 +37,8 @@ if env.v ~= 2 then
|
|
|
37
37
|
return 6
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
local
|
|
40
|
+
local t = redis.call('TIME')
|
|
41
|
+
local now = tonumber(t[1])
|
|
41
42
|
|
|
42
43
|
-- Retry-safe replay detection BEFORE rejecting consumed records.
|
|
43
44
|
-- The rotation nonce uniquely identifies the rotation: when the consumed
|
|
@@ -102,6 +103,8 @@ end
|
|
|
102
103
|
|
|
103
104
|
redis.call('SET', KEYS[2], cjson.encode(nextEnv), 'EX', nextTtl)
|
|
104
105
|
redis.call('ZREM', KEYS[3], ARGV[7])
|
|
105
|
-
|
|
106
|
+
-- Microsecond-resolution ordering score - see create.lua for why
|
|
107
|
+
-- second-granularity scores break oldest-first eviction ordering.
|
|
108
|
+
redis.call('ZADD', KEYS[3], tonumber(t[1]) + (tonumber(t[2]) / 1000000), ARGV[3])
|
|
106
109
|
|
|
107
110
|
return { 1, ARGV[3] }
|
|
@@ -44,7 +44,8 @@ if env.v ~= 1 then
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
local s = env.s
|
|
47
|
-
local
|
|
47
|
+
local t = redis.call('TIME')
|
|
48
|
+
local now = tonumber(t[1])
|
|
48
49
|
|
|
49
50
|
-- Retry-safe replay detection BEFORE rejecting consumed records.
|
|
50
51
|
-- The rotation nonce uniquely identifies the rotation: when the consumed
|
|
@@ -114,6 +115,8 @@ end
|
|
|
114
115
|
|
|
115
116
|
redis.call('SET', KEYS[2], cjson.encode(nextEnv), 'EX', nextTtl)
|
|
116
117
|
redis.call('ZREM', KEYS[3], ARGV[6])
|
|
117
|
-
|
|
118
|
+
-- Microsecond-resolution ordering score - see create.lua for why
|
|
119
|
+
-- second-granularity scores break oldest-first eviction ordering.
|
|
120
|
+
redis.call('ZADD', KEYS[3], tonumber(t[1]) + (tonumber(t[2]) / 1000000), ARGV[2])
|
|
118
121
|
|
|
119
122
|
return { 1, ARGV[2] }
|
package/package.json
CHANGED