🔧 refactor(http): use thread-safe lazy-initialized HTTP client with connection pooling

- Replace global _httpClient variable by a sync.Once-based lazy initialization
- Add getHTTPClient() function to safely initialize client with connection pooling settings (MaxIdleConnsPerHost, Max Con ns/Conn per host)
- Set connection pool size based on obidefault.ParallelWorkers()

This ensures safe concurrent access and better resource management in multi-threaded Lua environments.
This commit is contained in:
Eric Coissac
2026-04-13 16:27:01 +02:00
parent 083a92e13d
commit 137f49d1d1
+20 -2
View File
@@ -4,16 +4,34 @@ import (
"io" "io"
"net/http" "net/http"
"strings" "strings"
"sync"
"time" "time"
"git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obidefault"
lua "github.com/yuin/gopher-lua" lua "github.com/yuin/gopher-lua"
) )
const httpClientTimeout = 30 * time.Second const httpClientTimeout = 30 * time.Second
var _httpClient = &http.Client{ var (
_httpClient *http.Client
_httpClientOnce sync.Once
)
func getHTTPClient() *http.Client {
_httpClientOnce.Do(func() {
conns := 2 * obidefault.ParallelWorkers()
_httpClient = &http.Client{
Transport: &http.Transport{
MaxIdleConnsPerHost: conns,
MaxConnsPerHost: conns,
IdleConnTimeout: 90 * time.Second,
},
Timeout: httpClientTimeout, Timeout: httpClientTimeout,
} }
})
return _httpClient
}
// RegisterHTTP registers the http module in the Lua state as a global, // RegisterHTTP registers the http module in the Lua state as a global,
// consistent with obicontext and BioSequence. // consistent with obicontext and BioSequence.
@@ -46,7 +64,7 @@ func luaHTTPPost(L *lua.LState) int {
} }
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
resp, err := _httpClient.Do(req) resp, err := getHTTPClient().Do(req)
if err != nil { if err != nil {
L.Push(lua.LNil) L.Push(lua.LNil)
L.Push(lua.LString(err.Error())) L.Push(lua.LString(err.Error()))