File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -326,6 +326,15 @@ func (ml *ModelLoader) checkIsLoaded(s string) *Model {
326326 }
327327
328328 xlog .Debug ("Model already loaded in memory" , "model" , s )
329+
330+ // Skip the gRPC health check if the model was recently verified.
331+ // This avoids serializing concurrent requests behind ml.mu while each
332+ // one does a network round-trip (especially costly in distributed mode).
333+ if m .IsRecentlyHealthy () {
334+ xlog .Debug ("Model health check cached, skipping gRPC probe" , "model" , s )
335+ return m
336+ }
337+
329338 client := m .GRPC (false , ml .wd )
330339
331340 xlog .Debug ("Checking model availability" , "model" , s )
@@ -352,5 +361,6 @@ func (ml *ModelLoader) checkIsLoaded(s string) *Model {
352361 }
353362 }
354363
364+ m .MarkHealthy ()
355365 return m
356366}
Original file line number Diff line number Diff line change @@ -2,16 +2,23 @@ package model
22
33import (
44 "sync"
5+ "time"
56
67 grpc "github.com/mudler/LocalAI/pkg/grpc"
78 process "github.com/mudler/go-processmanager"
89)
910
11+ // healthCheckTTL is the duration for which a successful health check is cached.
12+ // Subsequent checkIsLoaded calls within this window skip the gRPC round-trip,
13+ // avoiding serialization of concurrent requests behind ml.mu.Lock().
14+ const healthCheckTTL = 30 * time .Second
15+
1016type Model struct {
11- ID string `json:"id"`
12- address string
13- client grpc.Backend
14- process * process.Process
17+ ID string `json:"id"`
18+ address string
19+ client grpc.Backend
20+ process * process.Process
21+ lastHealthCheck time.Time
1522 sync.Mutex
1623}
1724
@@ -37,6 +44,20 @@ func (m *Model) Process() *process.Process {
3744 return m .process
3845}
3946
47+ // IsRecentlyHealthy returns true if the model passed a health check within the TTL.
48+ func (m * Model ) IsRecentlyHealthy () bool {
49+ m .Lock ()
50+ defer m .Unlock ()
51+ return ! m .lastHealthCheck .IsZero () && time .Since (m .lastHealthCheck ) < healthCheckTTL
52+ }
53+
54+ // MarkHealthy records the current time as the last successful health check.
55+ func (m * Model ) MarkHealthy () {
56+ m .Lock ()
57+ defer m .Unlock ()
58+ m .lastHealthCheck = time .Now ()
59+ }
60+
4061func (m * Model ) GRPC (parallel bool , wd * WatchDog ) grpc.Backend {
4162 if m .client != nil {
4263 return m .client
You can’t perform that action at this time.
0 commit comments