summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2023-03-17 11:20:12 +0100
committerMartin Polden <mpolden@mpolden.no>2023-03-23 12:13:16 +0100
commit7e9bc236241a5b2b0261f897116de00b94e5a27f (patch)
treeb8ccf44d3119da3ba520c318cfa8b44196935cfa /client
parente45060cb75d78c10feae13b9344722d6fe99ffe8 (diff)
Parse document fully as part of decoding
Diffstat (limited to 'client')
-rw-r--r--client/go/internal/vespa/feed/document.go86
-rw-r--r--client/go/internal/vespa/feed/document_test.go27
-rw-r--r--client/go/internal/vespa/feed/http_test.go2
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",