Skip to content

Commit adf0928

Browse files
committed
fix(server_job): forcibly cancel requests
This should help prevent requests getting stuck and the thinking spinner staying up (because job_count is still > )
1 parent 3f6ccff commit adf0928

File tree

2 files changed

+43
-4
lines changed

2 files changed

+43
-4
lines changed

lua/opencode/core.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ function M.stop()
177177
if state.is_running() then
178178
vim.notify('Aborting current request...', vim.log.levels.WARN)
179179
state.api_client:abort_session(state.active_session.id):wait()
180+
181+
-- Forcibly reject any pending requests as it seems like they
182+
-- can sometimes get stuck
183+
server_job.cancel_all_requests()
180184
end
181185
require('opencode.ui.footer').clear()
182186
input_window.set_content('')

lua/opencode/server_job.lua

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ local Promise = require('opencode.promise')
44
local opencode_server = require('opencode.opencode_server')
55

66
local M = {}
7+
M.requests = {}
78

89
--- @param response {status: integer, body: string}
910
--- @param cb fun(err: any, result: any)
@@ -17,8 +18,6 @@ local function handle_api_response(response, cb)
1718
end
1819
end
1920

20-
M.requests = {}
21-
2221
function M.get_unresolved_requests()
2322
local unresolved = {}
2423

@@ -75,8 +74,29 @@ function M.call_api(url, method, body)
7574
opts.body = body and vim.json.encode(body) or '{}'
7675
end
7776

78-
-- FIXME: remove tracking code when thinking bug is fixed
79-
table.insert(M.requests, { opts, call_promise })
77+
-- For promise tracking, remove promises that complete from requests
78+
local request_entry = { opts, call_promise }
79+
table.insert(M.requests, request_entry)
80+
81+
local function remove_from_requests()
82+
vim.notify('removing from requests')
83+
for i, entry in ipairs(M.requests) do
84+
if entry == request_entry then
85+
table.remove(M.requests, i)
86+
break
87+
end
88+
end
89+
end
90+
91+
call_promise:and_then(function(result)
92+
remove_from_requests()
93+
return result
94+
end)
95+
96+
call_promise:catch(function(err)
97+
remove_from_requests()
98+
error(err)
99+
end)
80100

81101
curl.request(opts)
82102
return call_promise
@@ -117,6 +137,20 @@ function M.stream_api(url, method, body, on_chunk)
117137
return curl.request(opts)
118138
end
119139

140+
---Forcibly reject any pending requests (they sometimes get stuck
141+
---after an api abort)
142+
function M.cancel_all_requests()
143+
for _, entry in ipairs(M.requests) do
144+
local promise = entry[2]
145+
if not promise:is_resolved() then
146+
pcall(promise.reject, promise, 'Request cancelled')
147+
end
148+
end
149+
150+
M.requests = {}
151+
state.job_count = 0
152+
end
153+
120154
function M.ensure_server()
121155
if state.opencode_server_job and state.opencode_server_job:is_running() then
122156
return state.opencode_server_job
@@ -125,6 +159,7 @@ function M.ensure_server()
125159
local promise = Promise.new()
126160
state.opencode_server_job = opencode_server.new()
127161

162+
---@diagnostic disable-next-line: missing-fields
128163
state.opencode_server_job:spawn({
129164
on_ready = function(_, base_url)
130165
promise:resolve(state.opencode_server_job)

0 commit comments

Comments
 (0)