From 930c324869e872b163705c91021a00b2a7b66a7f Mon Sep 17 00:00:00 2001 From: Abdullah Barrak Date: Thu, 10 Feb 2022 12:05:00 +0300 Subject: [PATCH 1/3] 1316: support resilient redis mode for cache utils MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tests passing: ``` $ make busted-util /usr/local/openresty/luajit/bin/rover exec bin/busted "spec/threescale_utils_spec.lua" ●●● 3 successes / 0 failures / 0 errors / 0 pending : 0.02537 seconds ``` --- gateway/src/apicast/threescale_utils.lua | 34 +++++++++++++++++++----- spec/threescale_utils_spec.lua | 22 +++++++++++++++ 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/gateway/src/apicast/threescale_utils.lua b/gateway/src/apicast/threescale_utils.lua index d634178f0..61d08143a 100644 --- a/gateway/src/apicast/threescale_utils.lua +++ b/gateway/src/apicast/threescale_utils.lua @@ -124,7 +124,7 @@ function _M.connect_redis(options) local opts = {} local url = options and options.url or env.get('REDIS_URL') - + local resilient = options.resilient if url then url = resty_url.split(url, 'redis') @@ -152,14 +152,22 @@ function _M.connect_redis(options) local ok, err = red:connect(_M.resolve(host, port)) if not ok then - return nil, _M.error("failed to connect to redis on ", host, ":", port, ": ", err) + if not resilient then + return nil, _M.error("failed to connect to redis on ", host, ":", port, ": ", err) + else + return nil, _M.error_silently("failed to connect to redis on ", host, ":", port, ": ", err) + end end if opts.password then ok = red:auth(opts.password) if not ok then - return nil, _M.error("failed to auth on redis ", host, ":", port) + if not resilient then + return nil, _M.error("failed to auth on redis ", host, ":", port) + else + return nil, _M.error_silently("failed to auth on redis ", host, ":", port) + end end end @@ -167,7 +175,11 @@ function _M.connect_redis(options) ok = red:select(opts.db) if not ok then - return nil, _M.error("failed to select db ", opts.db, " on redis ", host, ":", port) + if not resilient then + return nil, _M.error("failed to select db ", opts.db, " on redis ", host, ":", port) + else + return nil, _M.error_silently("failed to select db ", opts.db, " on redis ", host, ":", port) + end end end @@ -187,17 +199,25 @@ function _M.match_xml_element(xml, element, value) return string.find(xml, pattern, xml_header_len, xml_header_len, true) end --- error and exit -function _M.error(...) +-- error without exit +function _M.error_silently(...) if ngx.get_phase() == 'timer' then return table.concat(table.pack(...)) else ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR ngx.say(...) - ngx.exit(ngx.status) end end +-- error and exit +function _M.error(...) + local err = _M.error_silently(...) + if err then + return err + end + ngx.exit(ngx.status) +end + function _M.missing_args(text) ngx.say(text) ngx.exit(ngx.HTTP_OK) diff --git a/spec/threescale_utils_spec.lua b/spec/threescale_utils_spec.lua index 04ca1cf36..e9c273806 100644 --- a/spec/threescale_utils_spec.lua +++ b/spec/threescale_utils_spec.lua @@ -10,5 +10,27 @@ describe('3scale utils', function() assert.equal('one two three', error) end) + + it('.error fails the nginx chain', function() + stub(ngx, 'get_phase', function() return 'init' end) + stub(ngx, 'say', function(...) return nil end) + local exit = spy.on(ngx, 'exit', function(s) return 'exited!' end) + + local error = _M.error('cache issue ' .. 'host:' .. 6379) + + assert.spy(ngx.exit).was_called(1) + assert.spy(ngx.say).was.called_with('cache issue ' .. 'host:' .. 6379) + end) + + it('.error_silently logs the error without exiting chain', function() + stub(ngx, 'get_phase', function() return 'init' end) + stub(ngx, 'say', function(...) return nil end) + + local exit = spy.on(ngx, 'exit', function(s) return 'exited!' end) + local error = _M.error_silently('redis is not reachable') + + assert.spy(ngx.exit).was_not_called() + assert.spy(ngx.say).was.called_with('redis is not reachable') + end) end) end) From 4b2a62673f6523aa873fe4fd5926e18f9866f568 Mon Sep 17 00:00:00 2001 From: Abdullah Barrak Date: Thu, 17 Feb 2022 11:22:56 +0300 Subject: [PATCH 2/3] 1316: rename & refactor conditions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unit Tests: ``` $ make busted-util EXTRA_CFLAGS="-DHAVE_EVP_KDF_CTX=1" /usr/local/openresty/luajit/bin/rover install --roverfile=gateway/Roverfile > /dev/null /usr/local/openresty/luajit/bin/rover exec bin/busted "spec/threescale_utils_spec.lua" ●●● 3 successes / 0 failures / 0 errors / 0 pending : 0.039009 seconds ``` --- gateway/src/apicast/threescale_utils.lua | 34 ++++++++++-------------- spec/threescale_utils_spec.lua | 4 +-- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/gateway/src/apicast/threescale_utils.lua b/gateway/src/apicast/threescale_utils.lua index 61d08143a..a5e118b3d 100644 --- a/gateway/src/apicast/threescale_utils.lua +++ b/gateway/src/apicast/threescale_utils.lua @@ -151,35 +151,29 @@ function _M.connect_redis(options) red:set_timeout(opts.timeout) local ok, err = red:connect(_M.resolve(host, port)) - if not ok then - if not resilient then - return nil, _M.error("failed to connect to redis on ", host, ":", port, ": ", err) - else - return nil, _M.error_silently("failed to connect to redis on ", host, ":", port, ": ", err) - end + if not ok and not resilient then + return nil, _M.error("failed to connect to redis on ", host, ":", port, ": ", err) + elseif not ok and resilient then + return nil, _M.error_gracefully("failed to connect to redis on ", host, ":", port, ": ", err) end if opts.password then ok = red:auth(opts.password) - if not ok then - if not resilient then - return nil, _M.error("failed to auth on redis ", host, ":", port) - else - return nil, _M.error_silently("failed to auth on redis ", host, ":", port) - end + if not ok and not resilient then + return nil, _M.error("failed to auth on redis ", host, ":", port) + elseif not ok and resilient then + return nil, _M.error_gracefully("failed to auth on redis ", host, ":", port) end end if opts.db then ok = red:select(opts.db) - if not ok then - if not resilient then - return nil, _M.error("failed to select db ", opts.db, " on redis ", host, ":", port) - else - return nil, _M.error_silently("failed to select db ", opts.db, " on redis ", host, ":", port) - end + if not ok and not resilient then + return nil, _M.error("failed to select db ", opts.db, " on redis ", host, ":", port) + elseif not ok and resilient then + return nil, _M.error_gracefully("failed to select db ", opts.db, " on redis ", host, ":", port) end end @@ -200,7 +194,7 @@ function _M.match_xml_element(xml, element, value) end -- error without exit -function _M.error_silently(...) +function _M.error_gracefully(...) if ngx.get_phase() == 'timer' then return table.concat(table.pack(...)) else @@ -211,7 +205,7 @@ end -- error and exit function _M.error(...) - local err = _M.error_silently(...) + local err = _M.error_gracefully(...) if err then return err end diff --git a/spec/threescale_utils_spec.lua b/spec/threescale_utils_spec.lua index e9c273806..fe45c326b 100644 --- a/spec/threescale_utils_spec.lua +++ b/spec/threescale_utils_spec.lua @@ -22,12 +22,12 @@ describe('3scale utils', function() assert.spy(ngx.say).was.called_with('cache issue ' .. 'host:' .. 6379) end) - it('.error_silently logs the error without exiting chain', function() + it('.error_gracefully logs the error without exiting chain', function() stub(ngx, 'get_phase', function() return 'init' end) stub(ngx, 'say', function(...) return nil end) local exit = spy.on(ngx, 'exit', function(s) return 'exited!' end) - local error = _M.error_silently('redis is not reachable') + local error = _M.error_gracefully('redis is not reachable') assert.spy(ngx.exit).was_not_called() assert.spy(ngx.say).was.called_with('redis is not reachable') From 9bfbeb8e73c562c6b5353545af397304b5491bdf Mon Sep 17 00:00:00 2001 From: Abdullah Barrak Date: Sun, 27 Feb 2022 03:00:52 +0300 Subject: [PATCH 3/3] 1316: polish --- gateway/src/apicast/threescale_utils.lua | 31 +++++++++++++++--------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/gateway/src/apicast/threescale_utils.lua b/gateway/src/apicast/threescale_utils.lua index a5e118b3d..6c1559313 100644 --- a/gateway/src/apicast/threescale_utils.lua +++ b/gateway/src/apicast/threescale_utils.lua @@ -151,29 +151,36 @@ function _M.connect_redis(options) red:set_timeout(opts.timeout) local ok, err = red:connect(_M.resolve(host, port)) - if not ok and not resilient then - return nil, _M.error("failed to connect to redis on ", host, ":", port, ": ", err) - elseif not ok and resilient then - return nil, _M.error_gracefully("failed to connect to redis on ", host, ":", port, ": ", err) + + if not ok then + if not resilient then + return nil, _M.error("failed to connect to redis on ", host, ":", port, ": ", err) + else + return nil, _M.error_gracefully("failed to connect to redis on ", host, ":", port, ": ", err) + end end if opts.password then ok = red:auth(opts.password) - if not ok and not resilient then - return nil, _M.error("failed to auth on redis ", host, ":", port) - elseif not ok and resilient then - return nil, _M.error_gracefully("failed to auth on redis ", host, ":", port) + if not ok then + if not resilient then + return nil, _M.error("failed to auth on redis ", host, ":", port) + else + return nil, _M.error_gracefully("failed to auth on redis ", host, ":", port) + end end end if opts.db then ok = red:select(opts.db) - if not ok and not resilient then - return nil, _M.error("failed to select db ", opts.db, " on redis ", host, ":", port) - elseif not ok and resilient then - return nil, _M.error_gracefully("failed to select db ", opts.db, " on redis ", host, ":", port) + if not ok then + if not resilient then + return nil, _M.error("failed to select db ", opts.db, " on redis ", host, ":", port) + else + return nil, _M.error_gracefully("failed to select db ", opts.db, " on redis ", host, ":", port) + end end end