fix: reuse shared HttpClient to prevent thread-leak OOM on model test

openAiCompatibleClientBuilder() was creating a new java.net.http.HttpClient
per request. Each instance spawns a selector thread and connection pool that
are never closed, exhausting the OS thread limit under frequent model-test
calls (e.g. DeepSeek provider).

Elevate the HttpClient to a static singleton so all OpenAI-compatible
provider requests share one connection pool and one selector thread.

Closes matevip/mateclaw#328
This commit is contained in:
倪程伟 2026-06-14 01:18:34 +08:00 committed by matevip
parent 515cba88ee
commit f361e0e917

View File

@ -66,6 +66,13 @@ public class ModelDiscoveryService {
private static final Duration TIMEOUT = Duration.ofSeconds(10);
// Shared HttpClient for OpenAI-compatible providers avoids creating a new
// native thread + connection pool per request (was causing thread-leak OOM).
private static final HttpClient SHARED_HTTP_CLIENT = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_1_1)
.connectTimeout(Duration.ofSeconds(30))
.build();
// Virtual-thread executor for parallel model probing (lightweight, short-lived)
private static final ExecutorService PROBE_EXECUTOR = Executors.newVirtualThreadPerTaskExecutor();
@ -962,10 +969,7 @@ public class ModelDiscoveryService {
* the upgrade negotiation.
*/
private RestClient.Builder openAiCompatibleClientBuilder() {
HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_1_1)
.build();
return RestClient.builder().requestFactory(new JdkClientHttpRequestFactory(httpClient));
return RestClient.builder().requestFactory(new JdkClientHttpRequestFactory(SHARED_HTTP_CLIENT));
}
@SuppressWarnings("unchecked")