{"record":{"id":"fce74bdc09c150dc","repo":"fish2018/pansou","slug":"s-d-w-fce74b","errorCode":null,"errorMessage":"[%s] 请求失败，重试%d次后仍失败: %w","messagePattern":"\\[(.+?)\\] 请求失败，重试(.+?)次后仍失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/ouge/ouge.go","lineNumber":423,"sourceCode":"\tfor i := 0; i < maxRetries; i++ {\n\t\tresp, err := client.Do(req)\n\t\tif err == nil {\n\t\t\tif resp.StatusCode == http.StatusOK {\n\t\t\t\treturn resp, nil\n\t\t\t}\n\t\t\tresp.Body.Close()\n\t\t\tlastErr = fmt.Errorf(\"HTTP状态码: %d\", resp.StatusCode)\n\t\t} else {\n\t\t\tlastErr = err\n\t\t}\n\t\t\n\t\t// JSON API快速重试：只等待很短时间\n\t\tif i < maxRetries-1 {\n\t\t\ttime.Sleep(100 * time.Millisecond) // 从秒级改为100毫秒\n\t\t}\n\t}\n\t\n\treturn nil, fmt.Errorf(\"[%s] 请求失败，重试%d次后仍失败: %w\", p.Name(), maxRetries, lastErr)\n}\n\n// GetPerformanceStats 获取性能统计信息\nfunc (p *OugeAsyncPlugin) GetPerformanceStats() map[string]interface{} {\n\ttotalRequests := atomic.LoadInt64(&searchRequests)\n\ttotalTime := atomic.LoadInt64(&totalSearchTime)\n\t\n\tvar avgTime float64\n\tif totalRequests > 0 {\n\t\tavgTime = float64(totalTime) / float64(totalRequests) / 1e6 // 转换为毫秒\n\t}\n\t\n\treturn map[string]interface{}{\n\t\t\"search_requests\":    totalRequests,\n\t\t\"avg_search_time_ms\": avgTime,\n\t\t\"total_search_time_ns\": totalTime,\n\t}\n}","sourceCodeStart":405,"sourceCodeEnd":441,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/ouge/ouge.go#L405-L441","documentation":"Final failure of doRequestWithRetry: after maxRetries attempts (with 100ms sleeps between them) the request never succeeded, so the last error is wrapped with the plugin name and the retry count via %w. Callers receive this from searchImpl as the cause of error 470.","triggerScenarios":"All attempts in the retry loop fail — persistent network errors, timeouts, or repeated non-200 statuses (error 474) — then the loop exits and this error is returned.","commonSituations":"The API host is fully down or DNS-blackholed; aggressive rate limiting survives the 100ms backoff; firewall blocks outbound HTTPS; the 100ms fast-retry policy is too short for a temporarily degraded upstream.","solutions":["Look at the wrapped cause (errors.Unwrap) to distinguish network failure from status failure","Wait and retry later with a longer backoff than the built-in 100ms","Test reachability of https://woog.nxog.eu.org/ independently (curl, DNS lookup)","If rate limiting, reduce request frequency or add jitter/proxy rotation before retrying"],"exampleFix":"// before\nif err != nil { return err }\n// after\nvar retried *RetryExhaustedError\nif errors.As(err, &retried) {\n    time.Sleep(2 * time.Second)\n    return secondAttempt()\n}","handlingStrategy":"fallback","validationCode":"func hostUp(host string) bool {\n    c, err := net.DialTimeout(\"tcp\", host+\":443\", 3*time.Second)\n    if err != nil { return false }\n    c.Close()\n    return true\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"重试\") { // retries exhausted\n        return alternatePluginSearch(keyword) // fallback source\n    }\n    return err\n}","preventionTips":["Don't hammer immediately after this error — the built-in backoff is only 100ms","Add exponential backoff with jitter at the caller level","Maintain a fallback plugin/source for resilience","Alert on persistent retry exhaustion — it means the upstream is down, not flaky"],"tags":["http","retry-exhausted","network","plugin"],"backgroundTag":"http-request-failed","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}