Enhance worker configuration and error handling for AI summarizer
continuous-integration/drone/push Build is passing

- Added `TranslationEnabled` and `TranslationInterval` fields to the worker configuration to manage automatic translation scheduling.
- Updated the worker initialization to log when the translation worker is disabled.
- Improved error handling in the AI summarizer client by introducing `APIStatusError` for better context on API failures, replacing direct error messages with structured error responses.

This update enhances the configurability of the worker and improves error reporting for AI service interactions, contributing to better maintainability and user experience.
This commit is contained in:
Mazyar
2026-06-14 14:02:35 +03:30
parent 42d64c4ec6
commit ca35eb5f15
5 changed files with 89 additions and 22 deletions
+23 -16
View File
@@ -163,7 +163,7 @@ func (c *Client) ScrapeDocuments(ctx context.Context, reqBody ScrapeDocumentsReq
return nil, fmt.Errorf("%w: status 404, body: %s", ErrObjectNotFound, string(bodyBytes))
}
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
return nil, apiNonSuccessError(httpResp.StatusCode, bodyBytes)
}
var result ScrapeDocumentsResponse
@@ -180,6 +180,13 @@ func (c *Client) ScrapeDocuments(ctx context.Context, reqBody ScrapeDocumentsReq
return &result, nil
}
func apiNonSuccessError(statusCode int, bodyBytes []byte) error {
return &APIStatusError{
StatusCode: statusCode,
Body: string(bodyBytes),
}
}
// ScrapeDocumentsBatch calls POST /scrape/documents/batch.
func (c *Client) ScrapeDocumentsBatch(ctx context.Context, tenders []TenderRef) (*BatchAcceptedResponse, error) {
reqBody := ScrapeDocumentsBatchRequest{Tenders: tenders}
@@ -198,7 +205,7 @@ func (c *Client) PipelineSync(ctx context.Context) (*PipelineSyncResponse, error
defer httpResp.Body.Close()
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
return nil, apiNonSuccessError(httpResp.StatusCode, bodyBytes)
}
var result PipelineSyncResponse
@@ -233,7 +240,7 @@ func (c *Client) PipelineRun(ctx context.Context, reqBody PipelineRunRequest) (m
return nil, fmt.Errorf("%w: status 404, body: %s", ErrObjectNotFound, string(bodyBytes))
}
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
return nil, apiNonSuccessError(httpResp.StatusCode, bodyBytes)
}
var result map[string]interface{}
@@ -308,10 +315,10 @@ func (c *Client) GetPipelineStats(ctx context.Context, window string) (*Pipeline
defer httpResp.Body.Close()
if httpResp.StatusCode == http.StatusBadRequest {
return nil, fmt.Errorf("%w: status 400, body: %s", ErrAPINonSuccess, string(bodyBytes))
return nil, apiNonSuccessError(http.StatusBadRequest, bodyBytes)
}
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
return nil, apiNonSuccessError(httpResp.StatusCode, bodyBytes)
}
var result PipelineStatsResponse
@@ -334,7 +341,7 @@ func (c *Client) GetPipelineMinioStats(ctx context.Context) (PipelineMinioStatsR
defer httpResp.Body.Close()
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
return nil, apiNonSuccessError(httpResp.StatusCode, bodyBytes)
}
var result PipelineMinioStatsResponse
@@ -361,7 +368,7 @@ func (c *Client) postBatchAccepted(ctx context.Context, path string, reqBody any
defer httpResp.Body.Close()
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
return nil, apiNonSuccessError(httpResp.StatusCode, bodyBytes)
}
var result BatchAcceptedResponse
@@ -396,7 +403,7 @@ func (c *Client) triggerPipelineStarted(ctx context.Context, path, label string)
return nil, fmt.Errorf("%w: status 409, body: %s", ErrPipelineJobRunning, string(bodyBytes))
}
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
return nil, apiNonSuccessError(httpResp.StatusCode, bodyBytes)
}
var result PipelineStartedResponse
@@ -432,10 +439,10 @@ func (c *Client) getPipelineReportWithQuery(ctx context.Context, path, window st
defer httpResp.Body.Close()
if httpResp.StatusCode == http.StatusBadRequest {
return nil, fmt.Errorf("%w: status 400, body: %s", ErrAPINonSuccess, string(bodyBytes))
return nil, apiNonSuccessError(http.StatusBadRequest, bodyBytes)
}
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
return nil, apiNonSuccessError(httpResp.StatusCode, bodyBytes)
}
var result PipelineReportResponse
@@ -486,7 +493,7 @@ func (c *Client) FetchAnalyzeOnDemand(ctx context.Context, reqBody AnalyzeReques
return nil, fmt.Errorf("%w: status 404, body: %s", ErrObjectNotFound, string(bodyBytes))
}
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
return nil, apiNonSuccessError(httpResp.StatusCode, bodyBytes)
}
var result AnalyzeResponse
@@ -518,7 +525,7 @@ func (c *Client) StartOnboarding(ctx context.Context, reqBody OnboardingRequest)
defer httpResp.Body.Close()
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
return nil, apiNonSuccessError(httpResp.StatusCode, bodyBytes)
}
var result OnboardingResponse
@@ -551,7 +558,7 @@ func (c *Client) FetchRecommendations(ctx context.Context, reqBody RecommendRequ
defer httpResp.Body.Close()
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
return nil, apiNonSuccessError(httpResp.StatusCode, bodyBytes)
}
var result []RecommendedTender
@@ -578,7 +585,7 @@ func (c *Client) triggerPipelineAction(ctx context.Context, path, label string)
defer httpResp.Body.Close()
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
return nil, apiNonSuccessError(httpResp.StatusCode, bodyBytes)
}
var result PipelineActionResponse
@@ -650,7 +657,7 @@ func (c *Client) doPost(ctx context.Context, url string, jsonBody []byte) (*Summ
}
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
return nil, apiNonSuccessError(httpResp.StatusCode, bodyBytes)
}
var result SummarizeResponse
@@ -692,7 +699,7 @@ func (c *Client) doTranslatePost(ctx context.Context, url string, jsonBody []byt
}
if httpResp.StatusCode >= 400 {
return nil, fmt.Errorf("%w: status %d, body: %s", ErrAPINonSuccess, httpResp.StatusCode, string(bodyBytes))
return nil, apiNonSuccessError(httpResp.StatusCode, bodyBytes)
}
result, err := decodeTranslateResponse(bodyBytes)
+22 -1
View File
@@ -1,6 +1,9 @@
package ai_summarizer
import "errors"
import (
"errors"
"fmt"
)
// Common sentinel errors for the AI summarizer package.
var (
@@ -37,3 +40,21 @@ var (
// ErrPipelineJobRunning is returned when a single-flight pipeline job is already running (HTTP 409).
ErrPipelineJobRunning = errors.New("ai_summarizer: pipeline job already running")
)
// APIStatusError carries the HTTP status and response body from the Opplens AI service.
type APIStatusError struct {
StatusCode int
Body string
}
func (e *APIStatusError) Error() string {
if e == nil {
return ""
}
return fmt.Sprintf("ai_summarizer: API returned status %d, body: %s", e.StatusCode, e.Body)
}
// Is reports whether target is ErrAPINonSuccess.
func (e *APIStatusError) Is(target error) bool {
return target == ErrAPINonSuccess
}