Skip to content

Commit 4e92552

Browse files
authored
fix: the last chunk containing only newlines will cause a delay in event handling (api7#156)
1 parent 2b14429 commit 4e92552

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

lib/resty/etcd/v3.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ local function request_chunk(self, method, path, opts, timeout)
709709
body = body .. chunk
710710
end
711711

712-
if not utils.is_empty_str(chunk) and str_byte(chunk, -1) == str_byte("\n") then
712+
if #chunk > 0 and str_byte(chunk, -1) == str_byte("\n") then
713713
break
714714
end
715715

t/v3/key.t

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,3 +660,76 @@ qr/1:.*"created":true.*
660660
2:.*"value":"bcd4".*"value":"bcd4a".*
661661
timeout/
662662
--- timeout: 5
663+
664+
665+
666+
=== TEST 15: An event is divided into multiple http chunks and the last chunk contains only the separator (newline)
667+
--- http_config eval: $::HttpConfig
668+
--- config
669+
location /version {
670+
content_by_lua_block {
671+
ngx.say('{"etcdserver":"3.4.0","etcdcluster":"3.4.0"}')
672+
}
673+
}
674+
675+
location /v3/watch {
676+
content_by_lua_block {
677+
-- payload get from tcpdump while running TEST 3 and split the event response into two chunks
678+
679+
ngx.say('{"result":{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"271","raft_term":"7"},"created":true}}')
680+
ngx.flush()
681+
ngx.sleep(0.1)
682+
683+
-- send event without trailing new line
684+
ngx.print('{"result":{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"272","raft_term":"7"},"events":[{"kv":{"key":"L3Rlc3Q=","create_revision":"156","mod_revision":"272","version":"44","value":"ImJjZDMi"}}]}}')
685+
ngx.flush()
686+
-- send trailing new line
687+
ngx.print('\n')
688+
ngx.flush()
689+
690+
-- ensure client timeout
691+
ngx.sleep(1)
692+
}
693+
}
694+
695+
location /t {
696+
content_by_lua_block {
697+
local etcd, err = require("resty.etcd").new({
698+
protocol = "v3",
699+
http_host = {
700+
"http://127.0.0.1:" .. ngx.var.server_port,
701+
},
702+
})
703+
check_res(etcd, err)
704+
705+
local cur_time = ngx.now()
706+
local body_chunk_fun, err = etcd:watch("/test", {timeout = 0.5})
707+
if not body_chunk_fun then
708+
ngx.say("failed to watch: ", err)
709+
end
710+
711+
local idx = 0
712+
while true do
713+
local chunk, err = body_chunk_fun()
714+
715+
if not chunk then
716+
if err then
717+
ngx.say(err)
718+
end
719+
break
720+
end
721+
722+
idx = idx + 1
723+
ngx.say(idx, ": ", require("cjson").encode(chunk.result))
724+
end
725+
}
726+
}
727+
--- request
728+
GET /t
729+
--- no_error_log
730+
[error]
731+
--- response_body_like eval
732+
qr/1:.*"created":true.*
733+
2:.*"value":"bcd3".*
734+
timeout/
735+
--- timeout: 5

0 commit comments

Comments
 (0)