From 51dfbaec8ed02e8ab6c17dc127cbaa7c8d35ecf4 Mon Sep 17 00:00:00 2001 From: Connor Poole Date: Wed, 19 Oct 2022 06:55:31 +0000 Subject: [PATCH] fix: allow hscan to continue past first failure --- internal/hscan/hscan.go | 11 ++++++++++- internal/hscan/hscan_test.go | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/internal/hscan/hscan.go b/internal/hscan/hscan.go index 852c8bd5..77477eaf 100644 --- a/internal/hscan/hscan.go +++ b/internal/hscan/hscan.go @@ -67,6 +67,9 @@ func Struct(dst interface{}) (StructValue, error) { // Scan scans the results from a key-value Redis map result set to a destination struct. // The Redis keys are matched to the struct's field with the `redis` tag. +// This method will attempt to unmarshal each field and will return an error if any of the +// fields cannot be unmarshalled. The destination struct will have the failed fields set to +// their zero value. func Scan(dst interface{}, keys []interface{}, vals []interface{}) error { if len(keys) != len(vals) { return errors.New("args should have the same number of keys and vals") @@ -77,6 +80,8 @@ func Scan(dst interface{}, keys []interface{}, vals []interface{}) error { return err } + scanErrors := []error{} + // Iterate through the (key, value) sequence. for i := 0; i < len(vals); i++ { key, ok := keys[i].(string) @@ -90,10 +95,14 @@ func Scan(dst interface{}, keys []interface{}, vals []interface{}) error { } if err := strct.Scan(key, val); err != nil { - return err + scanErrors = append(scanErrors, err) } } + if len(scanErrors) > 0 { + return fmt.Errorf("scan errors: %v", scanErrors) + } + return nil } diff --git a/internal/hscan/hscan_test.go b/internal/hscan/hscan_test.go index ab4c0e1d..c51bd193 100644 --- a/internal/hscan/hscan_test.go +++ b/internal/hscan/hscan_test.go @@ -175,4 +175,21 @@ var _ = Describe("Scan", func() { Expect(Scan(&d, i{"bool"}, i{""})).To(HaveOccurred()) Expect(Scan(&d, i{"bool"}, i{"123"})).To(HaveOccurred()) }) + + It("does not stop scanning on first failure", func() { + var d data + + keys := i{"bool", "string", "int"} + vals := i{"-1", "foobar", "123"} + + err := Scan(&d, keys, vals) + Expect(err).To(HaveOccurred()) + + Expect(d).To(Equal(data{ + Bool: false, + String: "foobar", + Int: 123, + })) + + }) })