Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle documents being deleted before processing their requests #2313

Merged
merged 1 commit into from
Jul 16, 2024

Conversation

vinistock
Copy link
Member

Motivation

We sometimes get Errno::ENOENT in our telemetry and I believe I finally figured out why.

Consider this sequence of events:

  1. Someone opens a file and the editor fires a bunch of requests
  2. All of those requests are placed into the incoming queue
  3. Then the user deletes the file
  4. The server will receive a textDocument/didClose notification. This is handled immediately, removing the document from the store
  5. Then the worker picks up a request for the deleted file. Maybe it fell behind processing because the file was large or something caused it to lag
  6. Since the document is no longer present in the store, it will try to read it from disk, but the file no longer exists either so it then raises ENOENT

Implementation

I believe we have two options:

Stop processing textDocument/didClose synchronously and throw it in the incoming queue. This will guarantee that we only close the document after processing all requests received for it. However, we will waste time processing requests for a file that was already deleted

The second option is what I implemented: we raise a specific error for when documents no longer exist and avoid reporting those to our telemetry.

Automated Tests

Added a test that reproduces the behaviour. Notice that it's difficult to control the order of execution of messages, so the test itself is not 100% reliable, but it does catch the bug.

@vinistock vinistock added bugfix This PR will fix an existing bug server This pull request should be included in the server gem's release notes labels Jul 15, 2024
@vinistock vinistock self-assigned this Jul 15, 2024
@vinistock vinistock requested a review from a team as a code owner July 15, 2024 21:22
@vinistock vinistock requested review from andyw8 and st0012 July 15, 2024 21:22
},
})

# Close the file in a thread to increase the chance that it gets closed during the processing of the 10 document
Copy link
Contributor

@andyw8 andyw8 Jul 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I worry that these tests being non-deterministic may cause some pain in future (e.g. intermittent failures). Could we test server.rb by stubbing something to raise NonExistingDocumentError?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that will be testing the behaviour we want though. We want to ensure that requests that have been enqueued for a file that gets deleted won't break in unexpected ways.

Stubbing a method in server to raise is not really replicating that.

@vinistock vinistock force-pushed the vs/fix_removed_doc_concurrency_issue branch from b111830 to 0de178a Compare July 16, 2024 21:06
@vinistock vinistock enabled auto-merge (squash) July 16, 2024 21:06
@vinistock vinistock merged commit 124be35 into main Jul 16, 2024
33 checks passed
@vinistock vinistock deleted the vs/fix_removed_doc_concurrency_issue branch July 16, 2024 21:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugfix This PR will fix an existing bug server This pull request should be included in the server gem's release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants