@@ -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"
@@ -1839,10 +1841,50 @@ func init() {
1839
1841
errors .RegisterWrapperDecoder (typeName , decode )
1840
1842
}
1841
1843
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
+
1842
1881
func init () {
1843
1882
errors .RegisterLeafDecoder (errors .GetTypeKey ((* MissingRecordError )(nil )), func (_ context.Context , _ string , _ []string , _ proto.Message ) error {
1844
1883
return & MissingRecordError {}
1845
1884
})
1885
+ collisionErrorKey := errors .GetTypeKey ((* KeyCollisionError )(nil ))
1886
+ errors .RegisterLeafEncoder (collisionErrorKey , encodeKeyCollisionError )
1887
+ errors .RegisterLeafDecoder (collisionErrorKey , decodeKeyCollisionError )
1846
1888
errorutilpath := reflect .TypeOf (errorutil.TempSentinel {}).PkgPath ()
1847
1889
errors .RegisterTypeMigration (errorutilpath , "*errorutil.descriptorNotFound" , & DescNotFoundError {})
1848
1890
}
0 commit comments