diff options
author | Martin Polden <mpolden@mpolden.no> | 2023-03-16 14:55:22 +0100 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2023-03-23 12:13:16 +0100 |
commit | e45060cb75d78c10feae13b9344722d6fe99ffe8 (patch) | |
tree | fb530b21b3e95e0bd553b588e3200d9c9d7289a2 /client | |
parent | 5d83a7b7c3ecd8dc5f1bd4e307cb75d9b69bc170 (diff) |
Model result of a feeding operation
Diffstat (limited to 'client')
-rw-r--r-- | client/go/internal/vespa/feed/feed.go | 35 | ||||
-rw-r--r-- | client/go/internal/vespa/feed/http.go | 42 | ||||
-rw-r--r-- | client/go/internal/vespa/feed/http_test.go | 9 |
3 files changed, 74 insertions, 12 deletions
diff --git a/client/go/internal/vespa/feed/feed.go b/client/go/internal/vespa/feed/feed.go new file mode 100644 index 00000000000..d042544ae75 --- /dev/null +++ b/client/go/internal/vespa/feed/feed.go @@ -0,0 +1,35 @@ +package feed + +type Status int + +const ( + // StatusSuccess indicates a successful document operation. + StatusSuccess Status = iota + // StatusConditionNotMet indicates that the document operation itself was successful, but did not satisfy its + // test-and-set condition. + StatusConditionNotMet + // StatusVespaFailure indicates that Vespa failed to process the document operation. + StatusVespaFailure + // StatusTransportFailure indicates that there was failure in the transport layer error while sending the document + // operation to Vespa. + StatusTransportFailure + // StatusError is a catch-all status for any other error that might occur. + StatusError +) + +// Result represents the result of a feeding operation. +type Result struct { + Id DocumentId + Status Status + Message string + Trace string + Err error +} + +// Success returns whether status s is considered a success. +func (s Status) Success() bool { return s == StatusSuccess || s == StatusConditionNotMet } + +// Feeder is the interface for code that perform a document operation and return its result. +type Feeder interface { + Send(Document) Result +} diff --git a/client/go/internal/vespa/feed/http.go b/client/go/internal/vespa/feed/http.go index f0b7eb42aa6..8fd892c4f46 100644 --- a/client/go/internal/vespa/feed/http.go +++ b/client/go/internal/vespa/feed/http.go @@ -2,6 +2,8 @@ package feed import ( "bytes" + "encoding/json" + "fmt" "net/http" "net/url" "strconv" @@ -24,9 +26,6 @@ type ClientOptions struct { TraceLevel *int } -// Result represents the result of a feeding operation -type Result struct{} - func NewClient(options ClientOptions, httpClient util.HTTPClient) *Client { return &Client{options: options, httpClient: httpClient} } @@ -46,20 +45,47 @@ func (c *Client) queryParams() url.Values { } // Send given document the URL configured in this client. -func (c *Client) Send(document Document) (Result, error) { +func (c *Client) Send(document Document) Result { method, url, err := document.FeedURL(c.options.BaseURL, c.queryParams()) if err != nil { - return Result{}, err + return Result{Status: StatusError, Err: err} } body := document.Body() req, err := http.NewRequest(method, url.String(), bytes.NewReader(body)) if err != nil { - return Result{}, err + return Result{Status: StatusError, Err: err} } resp, err := c.httpClient.Do(req, c.options.Timeout) if err != nil { - return Result{}, err + return Result{Status: StatusTransportFailure, Err: err} } defer resp.Body.Close() - return Result{}, nil + return createResult(resp) +} + +func createResult(resp *http.Response) Result { + result := Result{} + switch resp.StatusCode { + case 200: + result.Status = StatusSuccess + case 412: + result.Status = StatusConditionNotMet + case 502, 504, 507: + result.Status = StatusVespaFailure + default: + result.Status = StatusTransportFailure + } + var body struct { + Message string `json:"message"` + Trace json.RawMessage `json:"trace"` + } + jsonDec := json.NewDecoder(resp.Body) + if err := jsonDec.Decode(&body); err != nil { + result.Status = StatusError + result.Err = fmt.Errorf("failed to decode json response: %w", err) + return result + } + result.Message = body.Message + result.Trace = string(body.Trace) + return result } diff --git a/client/go/internal/vespa/feed/http_test.go b/client/go/internal/vespa/feed/http_test.go index 5c9378ab5f7..3a00e6fffc9 100644 --- a/client/go/internal/vespa/feed/http_test.go +++ b/client/go/internal/vespa/feed/http_test.go @@ -14,13 +14,14 @@ import ( func TestClientSend(t *testing.T) { doc := Document{Create: true, UpdateId: "id:ns:type::doc1", Fields: json.RawMessage(`{"foo": "123"}`)} httpClient := mock.HTTPClient{} - client := NewClient(ClientOptions{ + var client Feeder = NewClient(ClientOptions{ BaseURL: "https://example.com:1337", Timeout: time.Duration(5 * time.Second), }, &httpClient) - _, err := client.Send(doc) - if err != nil { - t.Fatalf("got unexpected error %q", err) + httpClient.NextResponseString(200, `{"message":"All good!"}`) + res := client.Send(doc) + if res.Err != nil { + t.Fatalf("got unexpected error %q", res.Err) } r := httpClient.LastRequest if r.Method != http.MethodPut { |