Skip to content

Commit eca0577

Browse files
javachefacebook-github-bot
authored andcommitted
Give devsupport networking its own dispatcher and pool (#58094)
Summary: `DevSupportHttpClient` derived its clients from the app's shared `OkHttpClient` with `newBuilder()`, which shares the underlying `Dispatcher` and `ConnectionPool`. Dev support keeps several long-lived WebSockets open to the dev server — the packager connection and the inspector among them — and a WebSocket occupies a running-call slot for its entire lifetime, because `RealWebSocket.loopReader` runs inside `RealCall.AsyncCall.execute`. OkHttp allows five concurrent calls per host by default, so those sockets throttle, and eventually stall, every other request to the dev server: `BundleDownloader` fetching the bundle itself, `PackagerStatusCheck`, and any application request that happens to target the same host. Give the devsupport clients a `Dispatcher` and a `ConnectionPool` of their own, still configured from the shared client so an `OkHttpClientFactory` override continues to apply. The per-host limit is raised on that dispatcher as well — without it the WebSockets would simply starve bundle traffic on the new dispatcher instead of the app's. Changelog: [Android][Fixed] - Stop dev server WebSockets from throttling bundle downloads and other dev server requests Reviewed By: cortinico Differential Revision: D117196401
1 parent 90a539c commit eca0577

1 file changed

Lines changed: 24 additions & 2 deletions

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/DevSupportHttpClient.kt

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,39 @@ package com.facebook.react.devsupport.inspector
1111

1212
import com.facebook.react.modules.network.OkHttpClientProvider
1313
import java.util.concurrent.TimeUnit
14+
import okhttp3.ConnectionPool
15+
import okhttp3.Dispatcher
1416
import okhttp3.OkHttpClient
1517

1618
/**
17-
* Shared [OkHttpClient] instances for devsupport networking. Uses a single connection pool and
18-
* dispatcher across all dev support HTTP and WebSocket usage.
19+
* Shared [OkHttpClient] instances for devsupport networking. Configured from the app's client, so a
20+
* [com.facebook.react.modules.network.OkHttpClientFactory] override still applies, but with a
21+
* connection pool and dispatcher of their own, shared across all dev support HTTP and WebSocket
22+
* usage and nothing else.
23+
*
24+
* The dispatcher must not be the app's. A WebSocket occupies a running-call slot on it for its
25+
* whole lifetime — `RealWebSocket.loopReader` runs inside `RealCall.AsyncCall.execute` — and dev
26+
* support keeps several open to one host: the packager connection, the inspector, and whatever else
27+
* the app connects. OkHttp's default [Dispatcher.maxRequestsPerHost] is 5, so on the app's
28+
* dispatcher those sockets throttle, and eventually stall, every other request to the dev server —
29+
* including [com.facebook.react.devsupport.BundleDownloader] fetching the bundle itself.
1930
*/
2031
internal object DevSupportHttpClient {
32+
// Enough that the long-lived WebSockets cannot crowd out bundle and asset traffic: the dev
33+
// server is the only host this client talks to, so the per-host limit is the effective one.
34+
private const val MAX_CONCURRENT_REQUESTS = 32
35+
2136
/** Client for HTTP requests: connect=5s, write=disabled, read=disabled. */
2237
internal val httpClient: OkHttpClient =
2338
OkHttpClientProvider.getOkHttpClient()
2439
.newBuilder()
40+
.dispatcher(
41+
Dispatcher().apply {
42+
maxRequests = MAX_CONCURRENT_REQUESTS
43+
maxRequestsPerHost = MAX_CONCURRENT_REQUESTS
44+
},
45+
)
46+
.connectionPool(ConnectionPool())
2547
.connectTimeout(5, TimeUnit.SECONDS)
2648
.writeTimeout(0, TimeUnit.MILLISECONDS)
2749
.readTimeout(0, TimeUnit.MINUTES)

0 commit comments

Comments
 (0)