fix(collections): start agent pool after http server (#8981)

Otherwise if using collections with postgresql we create a deadlock, as
we need embeddings to be up

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
Ettore Di Giacinto
2026-03-12 19:25:49 +01:00
committed by GitHub
parent a738f8b0e4
commit 13bd0d9944
2 changed files with 53 additions and 14 deletions

View File

@@ -102,19 +102,24 @@ func (a *Application) start() error {
a.agentJobService = agentJobService
// Initialize agent pool service (LocalAGI integration)
if a.applicationConfig.AgentPool.Enabled {
aps, err := services.NewAgentPoolService(a.applicationConfig)
if err == nil {
if err := aps.Start(a.applicationConfig.Context); err != nil {
xlog.Error("Failed to start agent pool", "error", err)
} else {
a.agentPoolService = aps
}
} else {
xlog.Error("Failed to create agent pool service", "error", err)
}
}
return nil
}
// StartAgentPool initializes and starts the agent pool service (LocalAGI integration).
// This must be called after the HTTP server is listening, because backends like
// PostgreSQL need to call the embeddings API during collection initialization.
func (a *Application) StartAgentPool() {
if !a.applicationConfig.AgentPool.Enabled {
return
}
aps, err := services.NewAgentPoolService(a.applicationConfig)
if err != nil {
xlog.Error("Failed to create agent pool service", "error", err)
return
}
if err := aps.Start(a.applicationConfig.Context); err != nil {
xlog.Error("Failed to start agent pool", "error", err)
return
}
a.agentPoolService = aps
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"net"
"os"
"path/filepath"
"strings"
@@ -425,5 +426,38 @@ func (r *RunCMD) Run(ctx *cliContext.Context) error {
}
})
// Start the agent pool after the HTTP server is listening, because
// backends like PostgreSQL need to call the embeddings API during
// collection initialization.
go func() {
waitForServerReady(r.Address, app.ApplicationConfig().Context)
app.StartAgentPool()
}()
return appHTTP.Start(r.Address)
}
// waitForServerReady polls the given address until the HTTP server is
// accepting connections or the context is cancelled.
func waitForServerReady(address string, ctx context.Context) {
// Ensure the address has a host component for dialing.
// Echo accepts ":8080" but net.Dial needs a resolvable host.
host, port, err := net.SplitHostPort(address)
if err == nil && host == "" {
address = "127.0.0.1:" + port
}
for {
select {
case <-ctx.Done():
return
default:
}
conn, err := net.DialTimeout("tcp", address, 500*time.Millisecond)
if err == nil {
conn.Close()
return
}
time.Sleep(250 * time.Millisecond)
}
}