@@ -7,6 +7,7 @@ package kvpb
7
7
8
8
import (
9
9
"context"
10
+ "encoding/base64"
10
11
"fmt"
11
12
"reflect"
12
13
"slices"
@@ -21,6 +22,7 @@ import (
21
22
"github.com/cockroachdb/cockroach/pkg/util/protoutil"
22
23
"github.com/cockroachdb/cockroach/pkg/util/uuid"
23
24
"github.com/cockroachdb/errors"
25
+ "github.com/cockroachdb/errors/errorspb"
24
26
_ "github.com/cockroachdb/errors/extgrpc" // register EncodeError support for gRPC Status
25
27
"github.com/cockroachdb/pebble"
26
28
"github.com/cockroachdb/redact"
@@ -1914,10 +1916,50 @@ func init() {
1914
1916
errors .RegisterWrapperDecoder (typeName , decode )
1915
1917
}
1916
1918
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
+
1917
1956
func init () {
1918
1957
errors .RegisterLeafDecoder (errors .GetTypeKey ((* MissingRecordError )(nil )), func (_ context.Context , _ string , _ []string , _ proto.Message ) error {
1919
1958
return & MissingRecordError {}
1920
1959
})
1960
+ collisionErrorKey := errors .GetTypeKey ((* KeyCollisionError )(nil ))
1961
+ errors .RegisterLeafEncoder (collisionErrorKey , encodeKeyCollisionError )
1962
+ errors .RegisterLeafDecoder (collisionErrorKey , decodeKeyCollisionError )
1921
1963
errorutilpath := reflect .TypeOf (errorutil.TempSentinel {}).PkgPath ()
1922
1964
errors .RegisterTypeMigration (errorutilpath , "*errorutil.descriptorNotFound" , & DescNotFoundError {})
1923
1965
}
0 commit comments