From 0748dce36c1f83f9668a5ee36702ca0377ccebf7 Mon Sep 17 00:00:00 2001 From: Francis Belanger Date: Thu, 10 Sep 2026 11:31:34 -0400 Subject: [PATCH] fix: suppress warning on intentional stream shutdown --- lua/opencode/curl.lua | 4 +++- lua/opencode/server_job.lua | 4 ++-- tests/unit/curl_spec.lua | 28 +++++++++++++++++++++++++++- tests/unit/server_job_spec.lua | 25 ++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/lua/opencode/curl.lua b/lua/opencode/curl.lua index 4f82e6f6..3365d01b 100644 --- a/lua/opencode/curl.lua +++ b/lua/opencode/curl.lua @@ -160,6 +160,7 @@ function M.request(opts) local buffer = '' -- job.pid is not cleared on process exit local is_running = true + local shutdown_requested = false local job_opts = { stdout = function(err, chunk) @@ -204,7 +205,7 @@ function M.request(opts) end if opts.on_exit then - opts.on_exit(result.code, result.signal) + opts.on_exit(result.code, result.signal, shutdown_requested) end end) @@ -216,6 +217,7 @@ function M.request(opts) shutdown = function() -- Flip state before kill so callers immediately observe shutdown. is_running = false + shutdown_requested = true if job and job.pid then pcall(function() job:kill(15) -- SIGTERM diff --git a/lua/opencode/server_job.lua b/lua/opencode/server_job.lua index 95f0ffa6..8726456a 100644 --- a/lua/opencode/server_job.lua +++ b/lua/opencode/server_job.lua @@ -140,8 +140,8 @@ function M.stream_api(url, method, body, on_chunk) end log.notify('Error in streaming request: ' .. vim.inspect(err), vim.log.levels.ERROR) end, - on_exit = function(code, signal) - if code ~= 0 then + on_exit = function(code, signal, shutdown_requested) + if code ~= 0 and not shutdown_requested then log.notify('Streaming request exited with code ' .. tostring(code), vim.log.levels.WARN) end end, diff --git a/tests/unit/curl_spec.lua b/tests/unit/curl_spec.lua index 8205f40e..7fac7edb 100644 --- a/tests/unit/curl_spec.lua +++ b/tests/unit/curl_spec.lua @@ -89,8 +89,10 @@ describe('curl stream handle lifecycle', function() it('marks stream handle as stopped on shutdown', function() local killed = false + local on_complete - vim.system = function(_, _, _) + vim.system = function(_, _, cb) + on_complete = cb return { pid = 123, kill = function() @@ -105,8 +107,32 @@ describe('curl stream handle lifecycle', function() }) handle.shutdown() + on_complete({ code = 1, signal = 15 }) assert.is_true(killed) assert.is_false(handle.is_running()) end) + + it('reports whether stream exit followed an intentional shutdown', function() + local on_complete + local shutdown_requested + + vim.system = function(_, _, cb) + on_complete = cb + return { pid = 123, kill = function() end } + end + + local handle = curl.request({ + url = 'http://127.0.0.1:1/event', + stream = function() end, + on_exit = function(_, _, requested) + shutdown_requested = requested + end, + }) + + handle.shutdown() + on_complete({ code = 1, signal = 15 }) + + assert.is_true(shutdown_requested) + end) end) diff --git a/tests/unit/server_job_spec.lua b/tests/unit/server_job_spec.lua index c2b990be..9ab0e43a 100644 --- a/tests/unit/server_job_spec.lua +++ b/tests/unit/server_job_spec.lua @@ -1,22 +1,25 @@ local server_job = require('opencode.server_job') local Promise = require('opencode.promise') - local curl = require('opencode.curl') local assert = require('luassert') +local log = require('opencode.log') describe('server_job', function() local original_curl_request local opencode_server = require('opencode.opencode_server') local original_new + local original_log_notify before_each(function() original_curl_request = curl.request original_new = opencode_server.new + original_log_notify = log.notify end) after_each(function() curl.request = original_curl_request opencode_server.new = original_new + log.notify = original_log_notify end) it('exposes expected public functions', function() @@ -80,6 +83,26 @@ describe('server_job', function() assert.same({ 'part1', 'part2' }, collected) end) + it('does not warn when stream shutdown is intentional', function() + local on_exit + local notifications = {} + log.notify = function(message, level) + notifications[#notifications + 1] = { message, level } + end + curl.request = function(opts) + on_exit = opts.on_exit + return { pid = 1 } + end + + server_job.stream_api('http://localhost:1234/stream', 'GET', nil, function() end) + + on_exit(1, 15, true) + assert.same({}, notifications) + + on_exit(1, 15, false) + assert.same({ { 'Streaming request exited with code 1', vim.log.levels.WARN } }, notifications) + end) + it('ensure_server spawns a new opencode server only once', function() local spawn_count = 0 local fake = {