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

feat(client): add timeout to fetchResource to prevent hangs #2322

Merged
merged 1 commit into from
Jan 13, 2025

Conversation

jyyi1
Copy link
Contributor

@jyyi1 jyyi1 commented Jan 10, 2025

This PR adds a timeout to the fetchResource function. Previously, fetchResource could hang indefinitely if the requested resource was unavailable or extremely slow to respond. (You can use this key to test: https://httpstat.us/204?sleep=120000#Timeout)

Problems without the timeout

  • Windows & Linux: In desktop environments, NodeJS's default thread pool size is 4 (UV_THREADPOOL_SIZE). This restricts the number of concurrent native API (N-API) calls, (for example, fetchResource). If more than four fetchResource calls were blocked indefinitely, it would exhaust the thread pool, preventing other N-API calls from executing. Notably, this blocked the closeVPN call triggered by the "Quit" action, making users unable to quit the application.
  • All platforms: On all platforms, an indefinitely hanging http.Get call within fetchResource would consume system resources unnecessarily, potentially leading to performance degradation or even instability in extreme cases.

Note

This solution is more like a mitigation, not a complete fix, for the NodeJS thread pool limitation.

Further improvements might involve implementing a more sophisticated queuing mechanism or increasing the thread pool size (if feasible).

@jyyi1 jyyi1 marked this pull request as ready for review January 10, 2025 23:17
@jyyi1 jyyi1 requested a review from a team as a code owner January 10, 2025 23:17
@jyyi1 jyyi1 requested review from fortuna and sbruens January 10, 2025 23:17
Copy link
Collaborator

@fortuna fortuna left a comment

Choose a reason for hiding this comment

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

Thanks for fixing this!


"github.com/Jigsaw-Code/outline-apps/client/go/outline/platerrors"
)

const fetchTimeout = 10 * time.Second
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ideally the TS code would specify this, but this is a good mitigation.

Copy link
Contributor Author

@jyyi1 jyyi1 Jan 10, 2025

Choose a reason for hiding this comment

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

Ideally, TS code should combine fetchResource and the next establishVPN into a single "transaction", so both operations can be cancelled by a single context object (for example, when a user wants to connect to another server, we should cancel all existing fetchResource and establishVPN operations).

@@ -100,3 +101,29 @@ func TestFetchResource_BodyReadError(t *testing.T) {
require.Equal(t, platerrors.FetchConfigFailed, perr.Code)
require.Error(t, perr.Cause)
}

func TestFetchResource_Timeout(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice test!

@jyyi1 jyyi1 merged commit 19aab4e into master Jan 13, 2025
40 checks passed
@jyyi1 jyyi1 deleted the junyi/add-fetch-resource-timeout branch January 13, 2025 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants