Skip to content

Commit 00989f8

Browse files
authored
feat: support setting function modules for xrpc (#2)
1 parent e516475 commit 00989f8

File tree

3 files changed

+179
-5
lines changed

3 files changed

+179
-5
lines changed

lib/resty/healthcheck.lua

+17-4
Original file line numberDiff line numberDiff line change
@@ -890,12 +890,14 @@ end
890890
-- Runs a single healthcheck probe
891891
function checker:run_single_check(ip, port, hostname, hostheader)
892892
if self.checks.active.type == "xrpc" then
893-
local ok, status = self.checks.active.xrpc_handler({
893+
local handler = self.checks.active.xrpc_handler
894+
local node = {
894895
host = ip,
895896
port = port,
896897
domain = hostname,
897-
}, self.xrpc_conf)
898-
898+
}
899+
local conf = self.checks.active.xrpc_conf
900+
local ok, status = handler(node, conf)
899901
if not ok then
900902
return self:report_failure(ip, port, hostname, "active")
901903
end
@@ -1294,6 +1296,8 @@ local function fill_in_settings(opts, defaults, ctx)
12941296
if type(v) == "table" then
12951297
if default[1] then -- do not recurse on arrays
12961298
obj[k] = v
1299+
elseif default == NO_DEFAULT then
1300+
obj[k] = deepcopy(v)
12971301
else
12981302
ctx[#ctx + 1] = k
12991303
obj[k] = fill_in_settings(v, default, ctx)
@@ -1326,8 +1330,9 @@ local defaults = {
13261330
concurrency = 10,
13271331
http_path = "/",
13281332
https_verify_certificate = true,
1333+
xrpc_function_module = NO_DEFAULT,
13291334
xrpc_handler = NO_DEFAULT,
1330-
xrpc_conf = {},
1335+
xrpc_conf = NO_DEFAULT,
13311336
healthy = {
13321337
interval = 0, -- 0 = disabled by default
13331338
http_statuses = { 200, 302 },
@@ -1455,6 +1460,14 @@ function _M.new(opts)
14551460
end
14561461

14571462
if self.checks.active.type == "xrpc" then
1463+
local module = self.checks.active.xrpc_function_module
1464+
if module then
1465+
local ok, handler = pcall(require, module)
1466+
if not ok then
1467+
return nil, "failed to load xrpc handler module: " .. handler
1468+
end
1469+
self.checks.active.xrpc_handler = handler
1470+
end
14581471
assert(self.checks.active.xrpc_handler, "required option 'checks.active.xrpc_handler' is missing")
14591472
assert(self.checks.active.unhealthy.failures < 255, "checks.active.unhealthy.tcp_failures must be at most 254")
14601473
end

t/report_xrpc_status.t

+144-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ workers(1);
66
my $pwd = cwd();
77

88
our $HttpConfig = qq{
9-
lua_package_path "$pwd/lib/?.lua;;";
9+
lua_package_path "$pwd/lib/?.lua;$pwd/t/?.lua;;";
1010
lua_shared_dict test_shm 8m;
1111
lua_shared_dict my_worker_events 8m;
1212
};
@@ -499,3 +499,146 @@ event: target status '(127.0.0.1:2119)' from 'true' to 'false'
499499
healthy SUCCESS increment (1/2)
500500
healthy SUCCESS increment (2/2)
501501
event: target status '(127.0.0.1:2119)' from 'false' to 'true'
502+
503+
504+
505+
=== TEST 8: start xrpc healthcheck with xrpc_conf
506+
--- http_config eval
507+
qq{
508+
$::HttpConfig
509+
510+
server {
511+
listen 2119;
512+
location = /status {
513+
return 200;
514+
}
515+
}
516+
}
517+
--- config
518+
location = /t {
519+
content_by_lua_block {
520+
local we = require "resty.worker.events"
521+
assert(we.configure{ shm = "my_worker_events", interval = 0.1 })
522+
local healthcheck = require("resty.healthcheck")
523+
local checker = healthcheck.new({
524+
name = "testing",
525+
shm_name = "test_shm",
526+
type = "xrpc",
527+
checks = {
528+
active = {
529+
healthy = {
530+
interval = 0.5, -- we don't want active checks
531+
successes = 2,
532+
},
533+
unhealthy = {
534+
interval = 0.5, -- we don't want active checks
535+
failures = 2,
536+
},
537+
xrpc_conf = {
538+
timeout = 1000,
539+
},
540+
xrpc_handler = function(node, conf)
541+
ngx.log(ngx.INFO, "node.host: ", node.host, ", node.port: ", node.port)
542+
ngx.log(ngx.INFO, "conf.timeout: ", conf.timeout)
543+
end
544+
},
545+
},
546+
})
547+
ngx.sleep(0.1) -- wait for initial timers to run once
548+
checker:add_target("127.0.0.1", 2119, nil, true)
549+
ngx.sleep(1)
550+
}
551+
}
552+
--- request
553+
GET /t
554+
--- timeout: 10
555+
--- error_log
556+
node.host: 127.0.0.1, node.port: 2119
557+
conf.timeout: 1000
558+
559+
560+
561+
=== TEST 9: start xrpc healthcheck with xrpc_function_module
562+
--- http_config eval
563+
qq{
564+
$::HttpConfig
565+
566+
lua_shared_dict request_counters 1m;
567+
568+
server {
569+
listen 2119;
570+
571+
location /status {
572+
content_by_lua_block {
573+
local uri = ngx.var.request_uri
574+
local counter = ngx.shared.request_counters
575+
576+
counter:incr(uri, 1, 0)
577+
578+
local current_count = counter:get(uri) or 0
579+
580+
if current_count < 4 or current_count > 8 then
581+
ngx.status = 200
582+
ngx.say("OK")
583+
else
584+
ngx.status = 500
585+
ngx.say("ERROR")
586+
end
587+
}
588+
}
589+
}
590+
}
591+
--- config
592+
location = /t {
593+
content_by_lua_block {
594+
local we = require "resty.worker.events"
595+
assert(we.configure{ shm = "my_worker_events", interval = 0.1 })
596+
local healthcheck = require("resty.healthcheck")
597+
local checker, err = healthcheck.new({
598+
name = "testing",
599+
shm_name = "test_shm",
600+
type = "xrpc",
601+
checks = {
602+
active = {
603+
healthy = {
604+
interval = 0.5, -- we don't want active checks
605+
successes = 2,
606+
},
607+
unhealthy = {
608+
interval = 0.5, -- we don't want active checks
609+
failures = 2,
610+
},
611+
xrpc_function_module = "util.http_handler",
612+
},
613+
},
614+
})
615+
if not checker then
616+
ngx.log(ngx.ERR, "failed to create healthcheck: ", err)
617+
return
618+
end
619+
ngx.sleep(0.1) -- wait for initial timers to run once
620+
checker:add_target("127.0.0.1", 2119, nil, true)
621+
ngx.sleep(0.5)
622+
ngx.say(checker:get_target_status("127.0.0.1", 2119, nil)) -- true
623+
ngx.sleep(3.1)
624+
ngx.say(checker:get_target_status("127.0.0.1", 2119, nil)) -- false
625+
ngx.sleep(4.2)
626+
ngx.say(checker:get_target_status("127.0.0.1", 2119, nil)) -- true
627+
}
628+
}
629+
--- request
630+
GET /t
631+
--- timeout: 10
632+
--- response_body
633+
true
634+
false
635+
true
636+
--- error_log
637+
checking healthy targets: nothing to do
638+
checking unhealthy targets: nothing to do
639+
unhealthy XRPC increment (1/2) for '(127.0.0.1:2119)'
640+
unhealthy XRPC increment (2/2) for '(127.0.0.1:2119)'
641+
event: target status '(127.0.0.1:2119)' from 'true' to 'false'
642+
healthy SUCCESS increment (1/2)
643+
healthy SUCCESS increment (2/2)
644+
event: target status '(127.0.0.1:2119)' from 'false' to 'true'

t/util/http_handler.lua

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
local http = require('resty.http')
2+
local json = require('cjson')
3+
4+
return function (node, conf)
5+
ngx.log(ngx.INFO, "http_handler node: ", json.encode(node), " conf: ", json.encode(conf))
6+
conf = conf or {}
7+
local httpc = http.new()
8+
local uri = "http://" .. node.host .. ":" .. node.port
9+
local res, err = httpc:request_uri(uri, {
10+
method = conf.method or "GET",
11+
path = conf.path or "/status",
12+
})
13+
if not res then
14+
ngx.log(ngx.ERR, "failed to request: ", err)
15+
return false
16+
end
17+
return true, res.status
18+
end

0 commit comments

Comments
 (0)