Skip to content

Commit 0fd2841

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 acf8f76 commit 0fd2841

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
@@ -41,6 +41,7 @@ go_library(
4141
"//pkg/util/protoutil",
4242
"//pkg/util/uuid",
4343
"@com_github_cockroachdb_errors//:errors",
44+
"@com_github_cockroachdb_errors//errorspb",
4445
"@com_github_cockroachdb_errors//extgrpc",
4546
"@com_github_cockroachdb_pebble//:pebble",
4647
"@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"
@@ -1914,10 +1916,50 @@ func init() {
19141916
errors.RegisterWrapperDecoder(typeName, decode)
19151917
}
19161918

1919+
func encodeKeyCollisionError(
1920+
_ context.Context, err error,
1921+
) (msgPrefix string, safe []string, details proto.Message) {
1922+
t := err.(*KeyCollisionError)
1923+
details = &errorspb.StringsPayload{
1924+
Details: []string{
1925+
base64.StdEncoding.EncodeToString(t.Key),
1926+
base64.StdEncoding.EncodeToString(t.Value),
1927+
},
1928+
}
1929+
msgPrefix = "ingested key collides with an existing one"
1930+
return msgPrefix, nil, details
1931+
}
1932+
1933+
func decodeKeyCollisionError(_ context.Context, _ string, _ []string, payload proto.Message) error {
1934+
m, ok := payload.(*errorspb.StringsPayload)
1935+
if !ok || len(m.Details) < 2 {
1936+
// If this ever happens, this means some version of the library
1937+
// (presumably future) changed the payload type, and we're
1938+
// receiving this here. In this case, give up and let
1939+
// DecodeError use the opaque type.
1940+
return nil
1941+
}
1942+
key, decodeErr := base64.StdEncoding.DecodeString(m.Details[0])
1943+
if decodeErr != nil {
1944+
return nil //nolint:returnerrcheck
1945+
}
1946+
value, decodeErr := base64.StdEncoding.DecodeString(m.Details[1])
1947+
if decodeErr != nil {
1948+
return nil //nolint:returnerrcheck
1949+
}
1950+
return &KeyCollisionError{
1951+
Key: key,
1952+
Value: value,
1953+
}
1954+
}
1955+
19171956
func init() {
19181957
errors.RegisterLeafDecoder(errors.GetTypeKey((*MissingRecordError)(nil)), func(_ context.Context, _ string, _ []string, _ proto.Message) error {
19191958
return &MissingRecordError{}
19201959
})
1960+
collisionErrorKey := errors.GetTypeKey((*KeyCollisionError)(nil))
1961+
errors.RegisterLeafEncoder(collisionErrorKey, encodeKeyCollisionError)
1962+
errors.RegisterLeafDecoder(collisionErrorKey, decodeKeyCollisionError)
19211963
errorutilpath := reflect.TypeOf(errorutil.TempSentinel{}).PkgPath()
19221964
errors.RegisterTypeMigration(errorutilpath, "*errorutil.descriptorNotFound", &DescNotFoundError{})
19231965
}

0 commit comments

Comments
 (0)