Skip to content

Commit 9d56ac3

Browse files
committed
Merge branch 'release/0.06'
2 parents fc6c14a + fc94105 commit 9d56ac3

File tree

5 files changed

+170
-76
lines changed

5 files changed

+170
-76
lines changed

README.md

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ local rc = require("resty.redis.connector").new({
3939
connect_timeout = 50,
4040
read_timeout = 5000,
4141
keepalive_timeout = 30000,
42-
42+
4343
host = "127.0.0.1",
4444
port = 6379,
4545
db = 2,
@@ -53,7 +53,7 @@ local redis, err = rc:connect()
5353
local ok, err = rc:set_keepalive(redis)
5454
```
5555

56-
`connect` can be used to override defaults given in `new`
56+
[connect](#connect) can be used to override some defaults given in [new](#new), which are pertinent to this connection only.
5757

5858

5959
```lua
@@ -71,7 +71,9 @@ local redis, err = rc:connect({
7171

7272
## DSN format
7373

74-
If the `params.url` field is present then it will be parsed, overriding values supplied in the parameters table.
74+
If the `params.url` field is present then it will be parsed to set the other params. Any manually specified params will override values given in the DSN.
75+
76+
*Note: this is a behaviour change as of v0.06. Previously, the DSN values would take precedence.*
7577

7678
### Direct Redis connections
7779

@@ -87,11 +89,7 @@ When connecting via Redis Sentinel, the format is as follows:
8789

8890
`sentinel://PASSWORD@MASTER_NAME:ROLE/DB`
8991

90-
Again, `PASSWORD` and `DB` are optional. `ROLE` must be any of `m`, `s` or `a`, meaning:
91-
92-
* `m`: master
93-
* `s`: slave
94-
* `a`: any (first tries the master, but will failover to a slave if required)
92+
Again, `PASSWORD` and `DB` are optional. `ROLE` must be either `m` or `s` for master / slave respectively.
9593

9694
A table of `sentinels` must also be supplied. e.g.
9795

@@ -106,11 +104,11 @@ local redis, err = rc:connect{
106104

107105
## Proxy Mode
108106

109-
Enable the `connection_is_proxied` parameter if connecting to Redis through a proxy service (e.g. Twemproxy).
110-
These proxies generally only support a limited sub-set of Redis commands, those which do not require state and do not affect multiple keys.
107+
Enable the `connection_is_proxied` parameter if connecting to Redis through a proxy service (e.g. Twemproxy).
108+
These proxies generally only support a limited sub-set of Redis commands, those which do not require state and do not affect multiple keys.
111109
Databases and transactions are also not supported.
112110

113-
Proxy mode will disable switching to a DB on connect.
111+
Proxy mode will disable switching to a DB on connect.
114112
Unsupported commands (defaults to those not supported by Twemproxy) will return `nil, err` immediately rather than being sent to the proxy, which can result in dropped connections.
115113

116114
`discard` will not be sent when adding connections to the keepalive pool
@@ -138,7 +136,7 @@ If configured as a table of commands, the command methods will be replaced by a
138136
db = 0,
139137

140138
master_name = "mymaster",
141-
role = "master", -- master | slave | any
139+
role = "master", -- master | slave
142140
sentinels = {},
143141

144142
connection_is_proxied = false,
@@ -174,6 +172,13 @@ Creates the Redis Connector object, overring default params with the ones given.
174172

175173
Attempts to create a connection, according to the [params](#parameters) supplied, falling back to defaults given in `new` or the predefined defaults. If a connection cannot be made, returns `nil` and a string describing the reason.
176174

175+
Note that `params` given here do not change the connector's own configuration, and are only used to alter this particular connection operation. As such, the following parameters have no meaning when given in `connect`.
176+
177+
* `keepalive_poolsize`
178+
* `keepalive_timeout`
179+
* `connection_is_proxied`
180+
* `disabled_commands`
181+
177182

178183
### set_keepalive
179184

lib/resty/redis/connector.lua

Lines changed: 61 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ local DEFAULTS = setmetatable({
100100
url = "", -- DSN url
101101

102102
master_name = "mymaster",
103-
role = "master", -- master | slave | any
103+
role = "master", -- master | slave
104104
sentinels = {},
105105

106106
-- Redis proxies typically don't support full Redis capabilities
@@ -124,31 +124,12 @@ local default_disabled_commands = {
124124

125125

126126
local _M = {
127-
_VERSION = '0.05',
127+
_VERSION = '0.06',
128128
}
129129

130130
local mt = { __index = _M }
131131

132132

133-
function _M.new(config)
134-
local ok, config = pcall(tbl_copy_merge_defaults, config, DEFAULTS)
135-
if not ok then
136-
return nil, config -- err
137-
else
138-
-- In proxied Redis mode disable default commands
139-
if config.connection_is_proxied == true and
140-
not next(config.disabled_commands) then
141-
142-
config.disabled_commands = default_disabled_commands
143-
end
144-
145-
return setmetatable({
146-
config = setmetatable(config, fixed_field_metatable)
147-
}, mt)
148-
end
149-
end
150-
151-
152133
local function parse_dsn(params)
153134
local url = params.url
154135
if url and url ~= "" then
@@ -170,29 +151,58 @@ local function parse_dsn(params)
170151
-- password may not be present
171152
if #m < 5 then tbl_remove(fields, 1) end
172153

173-
local roles = { m = "master", s = "slave", a = "any" }
154+
local roles = { m = "master", s = "slave" }
155+
156+
local parsed_params = {}
174157

175158
for i,v in ipairs(fields) do
176-
params[v] = m[i + 1]
159+
parsed_params[v] = m[i + 1]
177160
if v == "role" then
178-
params[v] = roles[params[v]]
161+
parsed_params[v] = roles[parsed_params[v]]
179162
end
180163
end
181-
end
182164

183-
return true, nil
165+
return tbl_copy_merge_defaults(params, parsed_params)
166+
end
184167
end
185168
_M.parse_dsn = parse_dsn
186169

187170

188-
function _M.connect(self, params)
189-
local params = tbl_copy_merge_defaults(params, self.config)
171+
function _M.new(config)
172+
-- Fill out gaps in config with any dsn params
173+
if config and config.url then
174+
local err
175+
config, err = parse_dsn(config)
176+
if not ok then ngx_log(ngx_ERR, err) end
177+
end
190178

191-
if params.url then
192-
local ok, err = parse_dsn(params)
179+
local ok, config = pcall(tbl_copy_merge_defaults, config, DEFAULTS)
180+
if not ok then
181+
return nil, config -- err
182+
else
183+
-- In proxied Redis mode disable default commands
184+
if config.connection_is_proxied == true and
185+
not next(config.disabled_commands) then
186+
187+
config.disabled_commands = default_disabled_commands
188+
end
189+
190+
return setmetatable({
191+
config = setmetatable(config, fixed_field_metatable)
192+
}, mt)
193+
end
194+
end
195+
196+
197+
function _M.connect(self, params)
198+
if params and params.url then
199+
local err
200+
params, err = parse_dsn(params)
193201
if not ok then ngx_log(ngx_ERR, err) end
194202
end
195203

204+
params = tbl_copy_merge_defaults(params, self.config)
205+
196206
if #params.sentinels > 0 then
197207
return self:connect_via_sentinel(params)
198208
else
@@ -222,7 +232,7 @@ function _M.connect_via_sentinel(self, params)
222232
return nil, err, previous_errors
223233
end
224234

225-
if role == "master" or role == "any" then
235+
if role == "master" then
226236
local master, err = get_master(sentnl, master_name)
227237
if master then
228238
master.db = db
@@ -238,31 +248,32 @@ function _M.connect_via_sentinel(self, params)
238248
end
239249
end
240250
end
241-
end
242251

243-
-- We either wanted a slave, or are failing over to a slave "any"
244-
local slaves, err = get_slaves(sentnl, master_name)
245-
sentnl:set_keepalive()
252+
else
253+
-- We want a slave
254+
local slaves, err = get_slaves(sentnl, master_name)
255+
sentnl:set_keepalive()
246256

247-
if not slaves then
248-
return nil, err
249-
end
257+
if not slaves then
258+
return nil, err
259+
end
250260

251-
-- Put any slaves on 127.0.0.1 at the front
252-
tbl_sort(slaves, sort_by_localhost)
261+
-- Put any slaves on 127.0.0.1 at the front
262+
tbl_sort(slaves, sort_by_localhost)
253263

254-
if db or password then
255-
for i,slave in ipairs(slaves) do
256-
slave.db = db
257-
slave.password = password
264+
if db or password then
265+
for i,slave in ipairs(slaves) do
266+
slave.db = db
267+
slave.password = password
268+
end
258269
end
259-
end
260270

261-
local slave, err, previous_errors = self:try_hosts(slaves)
262-
if not slave then
263-
return nil, err, previous_errors
264-
else
265-
return slave
271+
local slave, err, previous_errors = self:try_hosts(slaves)
272+
if not slave then
273+
return nil, err, previous_errors
274+
else
275+
return slave
276+
end
266277
end
267278
end
268279

lib/resty/redis/sentinel.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ end
1010

1111

1212
local _M = {
13-
_VERSION = '0.05'
13+
_VERSION = '0.06'
1414
}
1515

1616

lua-resty-redis-connector-0.05-0.rockspec renamed to lua-resty-redis-connector-0.06-0.rockspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package = "lua-resty-redis-connector"
2-
version = "0.05-0"
2+
version = "0.06-0"
33
source = {
44
url = "git://github.com/pintsized/lua-resty-redis-connector",
5-
tag = "v0.05"
5+
tag = "v0.06"
66
}
77
description = {
88
summary = "Connection utilities for lua-resty-redis.",

t/connector.t

Lines changed: 89 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ location /t {
223223
path = "unix://tmp/redis.sock",
224224
}):connect()
225225

226-
assert(not redis and err == "no such file or directory",
227-
"bad domain socket should fail")
226+
assert(not redis and err == "no such file or directory",
227+
"bad domain socket should fail")
228228
}
229229
}
230230
--- request
@@ -241,13 +241,13 @@ location /t {
241241
content_by_lua_block {
242242
local rc = require("resty.redis.connector")
243243

244-
local params = {
245-
url = "redis://foo@127.0.0.1:$TEST_NGINX_REDIS_PORT/4"
246-
}
244+
local user_params = {
245+
url = "redis://foo@127.0.0.1:$TEST_NGINX_REDIS_PORT/4"
246+
}
247247

248-
local ok, err = rc.parse_dsn(params)
249-
assert(ok and not err,
250-
"url should parse without error: " .. tostring(err))
248+
local params, err = rc.parse_dsn(user_params)
249+
assert(params and not err,
250+
"url should parse without error: " .. tostring(err))
251251

252252
assert(params.host == "127.0.0.1", "host should be localhost")
253253
assert(tonumber(params.port) == $TEST_NGINX_REDIS_PORT,
@@ -256,12 +256,12 @@ location /t {
256256
assert(params.password == "foo", "password should be foo")
257257

258258

259-
local params = {
259+
local user_params = {
260260
url = "sentinel://foo@foomaster:s/2"
261261
}
262262

263-
local ok, err = rc.parse_dsn(params)
264-
assert(ok and not err,
263+
local params, err = rc.parse_dsn(user_params)
264+
assert(params and not err,
265265
"url should parse without error: " .. tostring(err))
266266

267267
assert(params.master_name == "foomaster", "master_name should be foomaster")
@@ -282,3 +282,81 @@ location /t {
282282
GET /t
283283
--- no_error_log
284284
[error]
285+
286+
287+
=== TEST 9: params override dsn components
288+
--- http_config eval: $::HttpConfig
289+
--- config
290+
location /t {
291+
lua_socket_log_errors Off;
292+
content_by_lua_block {
293+
local rc = require("resty.redis.connector")
294+
295+
local user_params = {
296+
url = "redis://foo@127.0.0.1:6381/4",
297+
db = 2,
298+
password = "bar",
299+
host = "example.com",
300+
}
301+
302+
local params, err = rc.parse_dsn(user_params)
303+
assert(params and not err,
304+
"url should parse without error: " .. tostring(err))
305+
306+
assert(tonumber(params.db) == 2, "db should be 2")
307+
assert(params.password == "bar", "password should be bar")
308+
assert(params.host == "example.com", "host should be example.com")
309+
310+
assert(tonumber(params.port) == 6381, "ort should still be 6381")
311+
312+
}
313+
}
314+
--- request
315+
GET /t
316+
--- no_error_log
317+
[error]
318+
319+
320+
=== TEST 9: Integration test for parse_dsn
321+
--- http_config eval: $::HttpConfig
322+
--- config
323+
location /t {
324+
lua_socket_log_errors Off;
325+
content_by_lua_block {
326+
local user_params = {
327+
url = "redis://foo.example:$TEST_NGINX_REDIS_PORT/4",
328+
db = 2,
329+
host = "127.0.0.1",
330+
}
331+
332+
local rc, err = require("resty.redis.connector").new(user_params)
333+
assert(rc and not err, "new should return positively")
334+
335+
local redis, err = rc:connect()
336+
assert(redis and not err, "connect should return positively")
337+
assert(redis:set("cat", "dog") and redis:get("cat") == "dog")
338+
339+
local redis, err = rc:connect({
340+
url = "redis://foo.example:$TEST_NGINX_REDIS_PORT/4",
341+
db = 2,
342+
host = "127.0.0.1",
343+
})
344+
assert(redis and not err, "connect should return positively")
345+
assert(redis:set("cat", "dog") and redis:get("cat") == "dog")
346+
347+
348+
local rc2, err = require("resty.redis.connector").new()
349+
local redis, err = rc2:connect({
350+
url = "redis://foo.example:$TEST_NGINX_REDIS_PORT/4",
351+
db = 2,
352+
host = "127.0.0.1",
353+
})
354+
assert(redis and not err, "connect should return positively")
355+
assert(redis:set("cat", "dog") and redis:get("cat") == "dog")
356+
357+
}
358+
}
359+
--- request
360+
GET /t
361+
--- no_error_log
362+
[error]

0 commit comments

Comments
 (0)