diff options
author | Martin Polden <mpolden@mpolden.no> | 2023-03-17 11:20:12 +0100 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2023-03-23 12:13:16 +0100 |
commit | 7e9bc236241a5b2b0261f897116de00b94e5a27f (patch) | |
tree | b8ccf44d3119da3ba520c318cfa8b44196935cfa /client | |
parent | e45060cb75d78c10feae13b9344722d6fe99ffe8 (diff) |
Parse document fully as part of decoding
Diffstat (limited to 'client')
-rw-r--r-- | client/go/internal/vespa/feed/document.go | 86 | ||||
-rw-r--r-- | client/go/internal/vespa/feed/document_test.go | 27 | ||||
-rw-r--r-- | client/go/internal/vespa/feed/http_test.go | 2 |
3 files changed, 67 insertions, 48 deletions
diff --git a/client/go/internal/vespa/feed/document.go b/client/go/internal/vespa/feed/document.go index 4d9ea23d9c0..72898529013 100644 --- a/client/go/internal/vespa/feed/document.go +++ b/client/go/internal/vespa/feed/document.go @@ -12,8 +12,19 @@ import ( var asciiSpace = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1} +type Operation int + +const ( + OperationPut = iota + OperationUpdate + OperationRemove +) + type Document struct { - Id string `json:"id"` + Id DocumentId + Operation Operation + + IdString string `json:"id"` PutId string `json:"put"` UpdateId string `json:"update"` RemoveId string `json:"remove"` @@ -22,48 +33,19 @@ type Document struct { Fields json.RawMessage `json:"fields"` } -func (d Document) operation() (string, DocumentId, error) { - operation := "" - id := "" - if d.Id != "" { - operation = "put" - id = d.Id - } else if d.PutId != "" { - operation = "put" - id = d.PutId - } else if d.UpdateId != "" { - operation = "update" - id = d.UpdateId - } else if d.RemoveId != "" { - operation = "remove" - id = d.RemoveId - } else { - return "", DocumentId{}, fmt.Errorf("invalid document: missing operation") - } - docId, err := ParseDocumentId(id) - if err != nil { - return "", DocumentId{}, err - } - return operation, docId, err -} - // FeedURL returns the HTTP method and URL to use for feeding this document. func (d Document) FeedURL(baseurl string, queryParams url.Values) (string, *url.URL, error) { u, err := url.Parse(baseurl) if err != nil { return "", nil, fmt.Errorf("invalid base url: %w", err) } - op, docId, err := d.operation() - if err != nil { - return "", nil, err - } httpMethod := "" - switch op { - case "put": + switch d.Operation { + case OperationPut: httpMethod = "POST" - case "update": + case OperationUpdate: httpMethod = "PUT" - case "remove": + case OperationRemove: httpMethod = "DELETE" } if d.Condition != "" { @@ -72,7 +54,7 @@ func (d Document) FeedURL(baseurl string, queryParams url.Values) (string, *url. if d.Create { queryParams.Set("create", "true") } - u.Path = docId.URLPath() + u.Path = d.Id.URLPath() u.RawQuery = queryParams.Encode() return httpMethod, u, nil } @@ -154,8 +136,38 @@ func (d *Decoder) decode() (Document, error) { return Document{}, err } doc := Document{} - err := d.dec.Decode(&doc) - return doc, err + if err := d.dec.Decode(&doc); err != nil { + return Document{}, err + } + if err := parseDocument(&doc); err != nil { + return Document{}, err + } + return doc, nil +} + +func parseDocument(d *Document) error { + id := "" + if d.IdString != "" { + d.Operation = OperationPut + id = d.IdString + } else if d.PutId != "" { + d.Operation = OperationPut + id = d.PutId + } else if d.UpdateId != "" { + d.Operation = OperationUpdate + id = d.UpdateId + } else if d.RemoveId != "" { + d.Operation = OperationRemove + id = d.RemoveId + } else { + return fmt.Errorf("invalid document: missing operation: %v", d) + } + docId, err := ParseDocumentId(id) + if err != nil { + return err + } + d.Id = docId + return nil } func NewDecoder(r io.Reader) *Decoder { diff --git a/client/go/internal/vespa/feed/document_test.go b/client/go/internal/vespa/feed/document_test.go index 0da5f44ab21..e409c55c90d 100644 --- a/client/go/internal/vespa/feed/document_test.go +++ b/client/go/internal/vespa/feed/document_test.go @@ -12,6 +12,13 @@ import ( func ptr[T any](v T) *T { return &v } +func mustParseDocument(d Document) Document { + if err := parseDocument(&d); err != nil { + panic(err) + } + return d +} + func TestParseDocumentId(t *testing.T) { tests := []struct { in string @@ -111,9 +118,9 @@ func testDocumentDecoder(t *testing.T, jsonLike string) { t.Helper() r := NewDecoder(strings.NewReader(jsonLike)) want := []Document{ - {PutId: "id:ns:type::doc1", Fields: json.RawMessage(`{"foo": "123"}`)}, - {PutId: "id:ns:type::doc2", Fields: json.RawMessage(`{"bar": "456"}`)}, - {RemoveId: "id:ns:type::doc1", Fields: json.RawMessage(nil)}, + mustParseDocument(Document{PutId: "id:ns:type::doc1", Fields: json.RawMessage(`{"foo": "123"}`)}), + mustParseDocument(Document{PutId: "id:ns:type::doc2", Fields: json.RawMessage(`{"bar": "456"}`)}), + mustParseDocument(Document{RemoveId: "id:ns:type::doc1", Fields: json.RawMessage(nil)}), } got := []Document{} for { @@ -220,25 +227,25 @@ func TestDocumentURL(t *testing.T) { url string }{ { - Document{ - Id: "id:ns:type::user", - }, + mustParseDocument(Document{ + IdString: "id:ns:type::user", + }), "POST", "https://example.com/document/v1/ns/type/docid/user?foo=ba%2Fr", }, { - Document{ + mustParseDocument(Document{ UpdateId: "id:ns:type::user", Create: true, Condition: "false", - }, + }), "PUT", "https://example.com/document/v1/ns/type/docid/user?condition=false&create=true&foo=ba%2Fr", }, { - Document{ + mustParseDocument(Document{ RemoveId: "id:ns:type::user", - }, + }), "DELETE", "https://example.com/document/v1/ns/type/docid/user?foo=ba%2Fr", }, diff --git a/client/go/internal/vespa/feed/http_test.go b/client/go/internal/vespa/feed/http_test.go index 3a00e6fffc9..9d9c1ed1c33 100644 --- a/client/go/internal/vespa/feed/http_test.go +++ b/client/go/internal/vespa/feed/http_test.go @@ -12,7 +12,7 @@ import ( ) func TestClientSend(t *testing.T) { - doc := Document{Create: true, UpdateId: "id:ns:type::doc1", Fields: json.RawMessage(`{"foo": "123"}`)} + doc := mustParseDocument(Document{Create: true, UpdateId: "id:ns:type::doc1", Fields: json.RawMessage(`{"foo": "123"}`)}) httpClient := mock.HTTPClient{} var client Feeder = NewClient(ClientOptions{ BaseURL: "https://example.com:1337", |