Fix gemini candidate starvation
build-push / docker (push) Successful in 4m7s

This commit is contained in:
GHStaK
2026-03-17 16:06:59 +09:00
parent 139e8f8781
commit 91ee37593c
4 changed files with 70 additions and 7 deletions
+19 -4
View File
@@ -53,6 +53,8 @@ type SearchExecutionMeta struct {
PartialDueToDeadline bool `json:"partialDueToDeadline"`
}
const searchEnrichmentReserve = 4 * time.Second
func NewSearchService(baseURL, googleVideoEngine, webEngine string) *SearchService {
if googleVideoEngine == "" {
googleVideoEngine = "google videos"
@@ -84,9 +86,11 @@ func (s *SearchService) SearchMediaWithDeadline(queries []string, enabledPlatfor
if s.BaseURL == "" {
return nil, meta, fmt.Errorf("searxng base url is not configured")
}
collectionDeadline, enrichmentDeadline := splitSearchDeadlines(deadline)
s.debug("search_service:start", map[string]any{
"queries": queries,
"enabledPlatforms": enabledPlatforms,
"deadlineSet": !deadline.IsZero(),
})
seen := map[string]bool{}
@@ -99,7 +103,7 @@ func (s *SearchService) SearchMediaWithDeadline(queries []string, enabledPlatfor
primaryQueries := baseQueries[:minInt(len(baseQueries), 4)]
runSearchPass := func(bases []string, onlyMissing bool) {
for _, base := range bases {
if !deadline.IsZero() && time.Now().After(deadline) {
if !collectionDeadline.IsZero() && time.Now().After(collectionDeadline) {
meta.PartialDueToDeadline = true
s.debug("search_service:deadline_reached", map[string]any{"stage": "runSearchPass", "base": base})
return
@@ -109,7 +113,7 @@ func (s *SearchService) SearchMediaWithDeadline(queries []string, enabledPlatfor
continue
}
for _, collector := range s.collectors {
if !deadline.IsZero() && time.Now().After(deadline) {
if !collectionDeadline.IsZero() && time.Now().After(collectionDeadline) {
meta.PartialDueToDeadline = true
s.debug("search_service:deadline_reached", map[string]any{"stage": "collectorLoop", "collector": collector.Name()})
return
@@ -133,7 +137,7 @@ func (s *SearchService) SearchMediaWithDeadline(queries []string, enabledPlatfor
"searchQueries": searchQueries,
})
for _, searchQuery := range searchQueries {
if !deadline.IsZero() && time.Now().After(deadline) {
if !collectionDeadline.IsZero() && time.Now().After(collectionDeadline) {
meta.PartialDueToDeadline = true
s.debug("search_service:deadline_reached", map[string]any{"stage": "queryLoop", "collector": collector.Name(), "query": searchQuery})
return
@@ -192,11 +196,22 @@ func (s *SearchService) SearchMediaWithDeadline(queries []string, enabledPlatfor
"hadError": lastErr != nil,
"partialDueToDeadline": meta.PartialDueToDeadline,
})
enriched, enrichMeta := s.EnrichResultsWithDeadline(results, deadline)
enriched, enrichMeta := s.EnrichResultsWithDeadline(results, enrichmentDeadline)
meta.PartialDueToDeadline = meta.PartialDueToDeadline || enrichMeta.PartialDueToDeadline
return enriched, meta, nil
}
func splitSearchDeadlines(deadline time.Time) (time.Time, time.Time) {
if deadline.IsZero() {
return time.Time{}, time.Time{}
}
remaining := time.Until(deadline)
if remaining <= searchEnrichmentReserve {
return deadline, deadline
}
return deadline.Add(-searchEnrichmentReserve), deadline
}
func (s *SearchService) EnrichResults(results []SearchResult) []SearchResult {
enriched, _ := s.EnrichResultsWithDeadline(results, time.Time{})
return enriched
+24
View File
@@ -182,6 +182,30 @@ func TestSearchServiceFetchCacheRoundTrip(t *testing.T) {
}
}
func TestSplitSearchDeadlinesReservesEnrichmentWindow(t *testing.T) {
deadline := time.Now().Add(20 * time.Second)
collectionDeadline, enrichmentDeadline := splitSearchDeadlines(deadline)
if enrichmentDeadline.IsZero() {
t.Fatal("expected enrichment deadline to be preserved")
}
if !collectionDeadline.Before(enrichmentDeadline) {
t.Fatalf("expected collection deadline before enrichment deadline, got %v >= %v", collectionDeadline, enrichmentDeadline)
}
if gap := enrichmentDeadline.Sub(collectionDeadline); gap < searchEnrichmentReserve-500*time.Millisecond {
t.Fatalf("expected reserve close to %v, got %v", searchEnrichmentReserve, gap)
}
}
func TestSplitSearchDeadlinesDoesNotReserveWhenDeadlineIsTooClose(t *testing.T) {
deadline := time.Now().Add(2 * time.Second)
collectionDeadline, enrichmentDeadline := splitSearchDeadlines(deadline)
if !collectionDeadline.Equal(enrichmentDeadline) {
t.Fatalf("expected identical deadlines when budget is too tight, got %v and %v", collectionDeadline, enrichmentDeadline)
}
}
func TestSearchServiceSkipsArtgridAPIAfter403(t *testing.T) {
var apiRequests atomic.Int32
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {