Skip to content

Commit a038dda

Browse files
committed
kvpb: register error decoder for KeyCollisionError
This will allow the error to be properly serialized and unredacted if it's sent across the network. Release note: None
1 parent 45a39f7 commit a038dda

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

pkg/kv/kvpb/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ go_library(
4444
"//pkg/util/protoutil",
4545
"//pkg/util/uuid",
4646
"@com_github_cockroachdb_errors//:errors",
47+
"@com_github_cockroachdb_errors//errorspb",
4748
"@com_github_cockroachdb_errors//extgrpc",
4849
"@com_github_cockroachdb_pebble//:pebble",
4950
"@com_github_cockroachdb_redact//:redact",

pkg/kv/kvpb/errors.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package kvpb
77

88
import (
99
"context"
10+
"encoding/base64"
1011
"fmt"
1112
"reflect"
1213
"slices"
@@ -21,6 +22,7 @@ import (
2122
"github.com/cockroachdb/cockroach/pkg/util/protoutil"
2223
"github.com/cockroachdb/cockroach/pkg/util/uuid"
2324
"github.com/cockroachdb/errors"
25+
"github.com/cockroachdb/errors/errorspb"
2426
_ "github.com/cockroachdb/errors/extgrpc" // register EncodeError support for gRPC Status
2527
"github.com/cockroachdb/pebble"
2628
"github.com/cockroachdb/redact"
@@ -1839,10 +1841,50 @@ func init() {
18391841
errors.RegisterWrapperDecoder(typeName, decode)
18401842
}
18411843

1844+
func encodeKeyCollisionError(
1845+
_ context.Context, err error,
1846+
) (msgPrefix string, safe []string, details proto.Message) {
1847+
t := err.(*KeyCollisionError)
1848+
details = &errorspb.StringsPayload{
1849+
Details: []string{
1850+
base64.StdEncoding.EncodeToString(t.Key),
1851+
base64.StdEncoding.EncodeToString(t.Value),
1852+
},
1853+
}
1854+
msgPrefix = "ingested key collides with an existing one"
1855+
return msgPrefix, nil, details
1856+
}
1857+
1858+
func decodeKeyCollisionError(_ context.Context, _ string, _ []string, payload proto.Message) error {
1859+
m, ok := payload.(*errorspb.StringsPayload)
1860+
if !ok || len(m.Details) < 2 {
1861+
// If this ever happens, this means some version of the library
1862+
// (presumably future) changed the payload type, and we're
1863+
// receiving this here. In this case, give up and let
1864+
// DecodeError use the opaque type.
1865+
return nil
1866+
}
1867+
key, decodeErr := base64.StdEncoding.DecodeString(m.Details[0])
1868+
if decodeErr != nil {
1869+
return nil //nolint:returnerrcheck
1870+
}
1871+
value, decodeErr := base64.StdEncoding.DecodeString(m.Details[1])
1872+
if decodeErr != nil {
1873+
return nil //nolint:returnerrcheck
1874+
}
1875+
return &KeyCollisionError{
1876+
Key: key,
1877+
Value: value,
1878+
}
1879+
}
1880+
18421881
func init() {
18431882
errors.RegisterLeafDecoder(errors.GetTypeKey((*MissingRecordError)(nil)), func(_ context.Context, _ string, _ []string, _ proto.Message) error {
18441883
return &MissingRecordError{}
18451884
})
1885+
collisionErrorKey := errors.GetTypeKey((*KeyCollisionError)(nil))
1886+
errors.RegisterLeafEncoder(collisionErrorKey, encodeKeyCollisionError)
1887+
errors.RegisterLeafDecoder(collisionErrorKey, decodeKeyCollisionError)
18461888
errorutilpath := reflect.TypeOf(errorutil.TempSentinel{}).PkgPath()
18471889
errors.RegisterTypeMigration(errorutilpath, "*errorutil.descriptorNotFound", &DescNotFoundError{})
18481890
}

0 commit comments

Comments
 (0)