Skip to content

Commit ba8c270

Browse files
authored
Merge pull request #3971 from Shopify/02-20-clean_up_cancelled_requests_after_processing_them
Clean up cancelled requests after processing them
2 parents 8eb4fac + ae85b99 commit ba8c270

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

lib/ruby_lsp/base_server.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,18 +165,20 @@ def handle_incoming_message(message)
165165

166166
# Check if the request was cancelled before trying to process it
167167
@global_state.synchronize do
168-
if id && @cancelled_requests.include?(id)
168+
if id && @cancelled_requests.delete(id)
169169
send_message(Error.new(
170170
id: id,
171171
code: Constant::ErrorCodes::REQUEST_CANCELLED,
172172
message: "Request #{id} was cancelled",
173173
))
174-
@cancelled_requests.delete(id)
174+
175175
return
176176
end
177177
end
178178

179179
process_message(message)
180+
# Ensure we remove the request if it got cancelled while it was being processed
181+
@cancelled_requests.delete(id)
180182
end
181183

182184
#: ((Result | Error | Notification | Request) message) -> void

test/server_test.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,54 @@ def test_cancelling_requests_returns_expected_error_code
888888
assert_equal("Request 1 was cancelled", error.message)
889889
end
890890

891+
def test_requests_cancelled_during_processing_are_deleted_from_cancelled_requests_list
892+
uri = URI("file:///foo.rb")
893+
894+
@server.process_message({
895+
method: "textDocument/didOpen",
896+
params: {
897+
textDocument: {
898+
uri: uri,
899+
text: "class Foo\nend",
900+
version: 1,
901+
languageId: "ruby",
902+
},
903+
},
904+
})
905+
906+
started_processing = Queue.new
907+
can_finish = Queue.new
908+
909+
original = @server.method(:text_document_definition)
910+
911+
# Simulate the request starting to process, but taking long to finish. It will only finish once there's something in
912+
# the `can_finish` queue
913+
@server.define_singleton_method(:text_document_definition) do |message|
914+
started_processing << true
915+
can_finish.pop
916+
original.call(message)
917+
end
918+
919+
@server.push_message({
920+
id: 1,
921+
method: "textDocument/definition",
922+
params: {
923+
textDocument: { uri: uri },
924+
position: { line: 0, character: 6 },
925+
},
926+
})
927+
928+
# Only cancel the request once we know it started processing
929+
started_processing.pop
930+
@server.process_message({ method: "$/cancelRequest", params: { id: 1 } })
931+
# Only allow the request to finish once we know it got cancelled
932+
can_finish << true
933+
934+
# Verify we still receive a response and that we cleaned up the cancelled list
935+
find_message(RubyLsp::Result, id: 1)
936+
assert_empty(@server.instance_variable_get(:@cancelled_requests))
937+
end
938+
891939
def test_unsaved_changes_are_indexed_when_computing_automatic_features
892940
uri = URI("file:///foo.rb")
893941
index = @server.global_state.index

0 commit comments

Comments
 (0)