Skip to content

Commit cbde9ad

Browse files
twmbr-vasquez
authored andcommitted
rpk/serde: replace hamba/avro and linkedin/goavro with twmb/avro
Replace the two separate avro libraries (hamba/avro for schema reference resolution, linkedin/goavro for encoding/decoding) with the single twmb/avro library, which handles both. This changes union serialization behavior: linkedin/goavro used Avro-JSON encoding where unions are serialized as {"type": value} objects. twmb/avro marshals union values as the bare type directly. Similarly for deserialization, we will no longer read the old {"type": value} union form but instead expect the value directly. Schema reference resolution now uses an explicit SchemaCache rather than relying on hamba/avro's implicit global cache. This also removes the replace directive for the redpanda-data/go-avro fork. (cherry picked from commit 59dcf96)
1 parent eedb807 commit cbde9ad

6 files changed

Lines changed: 44 additions & 75 deletions

File tree

MODULE.bazel

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,14 +293,12 @@ use_repo(
293293
"com_github_fatih_color",
294294
"com_github_google_uuid",
295295
"com_github_goreleaser_nfpm_v2",
296-
"com_github_hamba_avro_v2",
297296
"com_github_hashicorp_go_multierror",
298297
"com_github_kballard_go_shellquote",
299298
"com_github_kr_pretty",
300299
"com_github_kr_text",
301300
"com_github_ladicle_tabwriter",
302301
"com_github_lestrrat_go_jwx_v2",
303-
"com_github_linkedin_goavro_v2",
304302
"com_github_lithammer_go_jump_consistent_hash",
305303
"com_github_lorenzosaino_go_sysctl",
306304
"com_github_mark3labs_mcp_go",
@@ -332,6 +330,7 @@ use_repo(
332330
"com_github_stretchr_testify",
333331
"com_github_tidwall_sjson",
334332
"com_github_tklauser_go_sysconf",
333+
"com_github_twmb_avro",
335334
"com_github_twmb_franz_go",
336335
"com_github_twmb_franz_go_pkg_kadm",
337336
"com_github_twmb_franz_go_pkg_kfake",

src/go/rpk/go.mod

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
module github.com/redpanda-data/redpanda/src/go/rpk
22

3-
go 1.25.7
4-
5-
// add the git commit hash as the target version and `go mod tidy` will transform it into pseudo-version
6-
replace github.com/hamba/avro/v2 => github.com/redpanda-data/go-avro/v2 v2.0.0-20240405204525-77b1144dc525
3+
go 1.26
74

85
require (
96
buf.build/gen/go/redpandadata/ai-gateway/connectrpc/go v1.19.1-20260203101113-1c7702ddb57a.2
@@ -32,12 +29,10 @@ require (
3229
github.com/docker/go-units v0.5.0
3330
github.com/fatih/color v1.18.0
3431
github.com/google/uuid v1.6.0
35-
github.com/hamba/avro/v2 v2.30.0
3632
github.com/hashicorp/go-multierror v1.1.1
3733
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
3834
github.com/kr/text v0.2.0
3935
github.com/lestrrat-go/jwx/v2 v2.1.6
40-
github.com/linkedin/goavro/v2 v2.14.1
4136
github.com/lithammer/go-jump-consistent-hash v1.0.2
4237
github.com/lorenzosaino/go-sysctl v0.3.1
4338
github.com/mark3labs/mcp-go v0.44.0
@@ -63,6 +58,7 @@ require (
6358
github.com/stretchr/testify v1.11.1
6459
github.com/tidwall/sjson v1.2.5
6560
github.com/tklauser/go-sysconf v0.3.15
61+
github.com/twmb/avro v1.0.1
6662
github.com/twmb/franz-go v1.20.4
6763
github.com/twmb/franz-go/pkg/kadm v1.17.1
6864
github.com/twmb/franz-go/pkg/kfake v0.0.0-20251024215757-aea970d4d0d2
@@ -98,7 +94,6 @@ require (
9894
github.com/bahlo/generic-list-go v0.2.0 // indirect
9995
github.com/buger/jsonparser v1.1.2 // indirect
10096
github.com/cespare/xxhash/v2 v2.3.0 // indirect
101-
github.com/cloudflare/cfssl v1.6.5 // indirect
10297
github.com/containerd/errdefs/pkg v0.3.0 // indirect
10398
github.com/containerd/log v0.1.0 // indirect
10499
github.com/davecgh/go-spew v1.1.1 // indirect
@@ -115,15 +110,14 @@ require (
115110
github.com/goccy/go-json v0.10.3 // indirect
116111
github.com/godbus/dbus/v5 v5.0.4 // indirect
117112
github.com/gogo/protobuf v1.3.2 // indirect
118-
github.com/golang/snappy v0.0.4 // indirect
119113
github.com/google/gnostic-models v0.7.0 // indirect
120114
github.com/hashicorp/errwrap v1.1.0 // indirect
121115
github.com/inconshreveable/mousetrap v1.1.0 // indirect
122116
github.com/invopop/jsonschema v0.13.0 // indirect
123117
github.com/jmespath/go-jmespath v0.4.0 // indirect
124118
github.com/josharian/intern v1.0.0 // indirect
125119
github.com/json-iterator/go v1.1.12 // indirect
126-
github.com/klauspost/compress v1.18.1 // indirect
120+
github.com/klauspost/compress v1.18.4 // indirect
127121
github.com/lestrrat-go/blackmagic v1.0.3 // indirect
128122
github.com/lestrrat-go/httpcc v1.0.1 // indirect
129123
github.com/lestrrat-go/httprc v1.0.6 // indirect
@@ -133,7 +127,6 @@ require (
133127
github.com/mattn/go-colorable v0.1.13 // indirect
134128
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
135129
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
136-
github.com/mitchellh/mapstructure v1.5.0 // indirect
137130
github.com/moby/docker-image-spec v1.3.1 // indirect
138131
github.com/moby/sys/atomicwriter v0.1.0 // indirect
139132
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect

src/go/rpk/go.sum

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
6868
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
6969
github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM=
7070
github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY=
71-
github.com/cloudflare/cfssl v1.6.5 h1:46zpNkm6dlNkMZH/wMW22ejih6gIaJbzL2du6vD7ZeI=
72-
github.com/cloudflare/cfssl v1.6.5/go.mod h1:Bk1si7sq8h2+yVEDrFJiz3d7Aw+pfjjJSZVaD+Taky4=
7371
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
7472
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
7573
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
@@ -133,9 +131,6 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
133131
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
134132
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
135133
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
136-
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
137-
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
138-
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
139134
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
140135
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
141136
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
@@ -170,8 +165,8 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU
170165
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
171166
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
172167
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
173-
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
174-
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
168+
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
169+
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
175170
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
176171
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
177172
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@@ -192,8 +187,6 @@ github.com/lestrrat-go/jwx/v2 v2.1.6 h1:hxM1gfDILk/l5ylers6BX/Eq1m/pnxe9NBwW6lVf
192187
github.com/lestrrat-go/jwx/v2 v2.1.6/go.mod h1:Y722kU5r/8mV7fYDifjug0r8FK8mZdw0K0GpJw/l8pU=
193188
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
194189
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
195-
github.com/linkedin/goavro/v2 v2.14.1 h1:/8VjDpd38PRsy02JS0jflAu7JZPfJcGTwqWgMkFS2iI=
196-
github.com/linkedin/goavro/v2 v2.14.1/go.mod h1:KXx+erlq+RPlGSPmLF7xGo6SAbh8sCQ53x064+ioxhk=
197190
github.com/lithammer/go-jump-consistent-hash v1.0.2 h1:w74N9XiMa4dWZdoVnfLbnDhfpGOMCxlrudzt2e7wtyk=
198191
github.com/lithammer/go-jump-consistent-hash v1.0.2/go.mod h1:4MD1WDikNGnb9D56hAtscaZaOWOiCG+lLbRR5ZN9JL0=
199192
github.com/lorenzosaino/go-sysctl v0.3.1 h1:3phX80tdITw2fJjZlwbXQnDWs4S30beNcMbw0cn0HtY=
@@ -218,8 +211,6 @@ github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI=
218211
github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs=
219212
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
220213
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
221-
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
222-
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
223214
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
224215
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
225216
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
@@ -270,8 +261,6 @@ github.com/redpanda-data/common-go/rpadmin v0.2.4 h1:XM7kfhKokWeLATX4dnLXczjd4sx
270261
github.com/redpanda-data/common-go/rpadmin v0.2.4/go.mod h1:uOAY10WXPtcDPU0aUdpkqHR+b1BqUvRhlvMf0vha73A=
271262
github.com/redpanda-data/common-go/rpsr v0.1.4 h1:d9lu5q5wyhZWBYR1GnZkq+eZGKU0qoaSwwybRS9Uk2k=
272263
github.com/redpanda-data/common-go/rpsr v0.1.4/go.mod h1:qVa7b0yaCRdZDn5dcZ9CazqVr4jYbgtOJUywI2X3G3I=
273-
github.com/redpanda-data/go-avro/v2 v2.0.0-20240405204525-77b1144dc525 h1:vskZrV6q8W8flL0Ud23AJUYAd8ZgTadO45+loFnG2G0=
274-
github.com/redpanda-data/go-avro/v2 v2.0.0-20240405204525-77b1144dc525/go.mod h1:3YqAM7pgS5vW/EH7naCjFqnAajSgi0f0CfMe1HGhLxQ=
275264
github.com/redpanda-data/protoc-gen-go-mcp v0.0.0-20250930092048-a98b94b5957a h1:jNHT6Fcy/rBAFnX8rjbwrJ+lSF2Ufa1jqmnCV6m6RKY=
276265
github.com/redpanda-data/protoc-gen-go-mcp v0.0.0-20250930092048-a98b94b5957a/go.mod h1:bGTBF/Nvx6NQ/R4Jje5lBjTpfWrazOna3udJwx4EAHE=
277266
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
@@ -315,7 +304,6 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
315304
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
316305
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
317306
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
318-
github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
319307
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
320308
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
321309
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
@@ -334,6 +322,8 @@ github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8O
334322
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
335323
github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
336324
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
325+
github.com/twmb/avro v1.0.1 h1:7/P/fvUYikst1jMMjFY4It+uJRStLdz1APPVf4/SgJQ=
326+
github.com/twmb/avro v1.0.1/go.mod h1:by7R2J8LxFEZsjRy8p7pHRfZn1f0hXVFrOkMfqz4W98=
337327
github.com/twmb/franz-go v1.20.4 h1:1wTvyLTOxS0oJh5ro/DVt2JHVdx7/kGNtmtFhbcr0O0=
338328
github.com/twmb/franz-go v1.20.4/go.mod h1:YCnepDd4gl6vdzG03I5Wa57RnCTIC6DVEyMpDX/J8UA=
339329
github.com/twmb/franz-go/pkg/kadm v1.17.1 h1:Bt02Y/RLgnFO2NP2HVP1kd2TFtGRiJZx+fSArjZDtpw=

src/go/rpk/pkg/serde/BUILD

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ go_library(
1414
"//src/go/rpk/pkg/serde/embed",
1515
"@com_github_bufbuild_protocompile//:protocompile",
1616
"@com_github_bufbuild_protocompile//linker",
17-
"@com_github_hamba_avro_v2//:avro",
18-
"@com_github_linkedin_goavro_v2//:goavro",
1917
"@com_github_santhosh_tekuri_jsonschema_v6//:jsonschema",
18+
"@com_github_twmb_avro//:avro",
2019
"@com_github_twmb_franz_go_pkg_sr//:sr",
2120
"@org_golang_google_protobuf//encoding/protojson",
2221
"@org_golang_google_protobuf//proto",

src/go/rpk/pkg/serde/avro.go

Lines changed: 32 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,25 @@ package serde
1111

1212
import (
1313
"context"
14+
"encoding/json"
1415
"fmt"
1516

16-
"github.com/hamba/avro/v2"
17-
"github.com/linkedin/goavro/v2"
17+
"github.com/twmb/avro"
1818
"github.com/twmb/franz-go/pkg/sr"
1919
)
2020

2121
// newAvroEncoder generates a serializer function that can encode the provided
2222
// record using the specified schema. If the schema includes references, it
2323
// retrieves them using the supplied client. The generated function returns the
2424
// record encoded in the protobuf wire format.
25-
func newAvroEncoder(codec *goavro.Codec, schemaID int) (serdeFunc, error) {
25+
func newAvroEncoder(schema *avro.Schema, schemaID int) (serdeFunc, error) {
2626
return func(record []byte) ([]byte, error) {
27-
native, _, err := codec.NativeFromTextual(record)
28-
if err != nil {
27+
var native any
28+
if err := json.Unmarshal(record, &native); err != nil {
2929
return nil, fmt.Errorf("unable to parse record with the provided schema: %v", err)
3030
}
3131

32-
binary, err := codec.BinaryFromNative(nil, native)
32+
binary, err := schema.Encode(native)
3333
if err != nil {
3434
return nil, fmt.Errorf("unable to binary encode the record: %v", err)
3535
}
@@ -47,66 +47,54 @@ func newAvroEncoder(codec *goavro.Codec, schemaID int) (serdeFunc, error) {
4747
// newAvroDecoder generates a deserializer function that decodes the given
4848
// avro-encoded record according to the schema. The generated function expects
4949
// the record bytes (without the wire format).
50-
func newAvroDecoder(codec *goavro.Codec) (serdeFunc, error) {
50+
func newAvroDecoder(schema *avro.Schema) (serdeFunc, error) {
5151
return func(record []byte) ([]byte, error) {
52-
native, _, err := codec.NativeFromBinary(record)
53-
if err != nil {
52+
var native any
53+
if _, err := schema.Decode(record, &native); err != nil {
5454
return nil, fmt.Errorf("unable to decode avro-encoded record: %v", err)
5555
}
56-
57-
return codec.TextualFromNative(nil, native)
56+
return json.Marshal(native)
5857
}, nil
5958
}
6059

61-
// generateAvroCodec will generate an AVRO codec, parsing the references if
62-
// there are any.
63-
func generateAvroCodec(ctx context.Context, cl *sr.Client, schema *sr.Schema) (*goavro.Codec, error) {
64-
schemaStr := schema.Schema
65-
if len(schema.References) > 0 {
66-
err := parseAvroReferences(ctx, cl, schema)
67-
if err != nil {
68-
return nil, fmt.Errorf("unable to parse references: %v", err)
69-
}
70-
71-
// We use hamba/avro to for the schema reference resolution.
72-
refCodec, err := avro.Parse(schema.Schema)
60+
// generateAvroSchema parses the schema and its references, returning a
61+
// compiled schema that can be used for encoding and decoding.
62+
func generateAvroSchema(ctx context.Context, cl *sr.Client, schema *sr.Schema) (*avro.Schema, error) {
63+
if len(schema.References) == 0 {
64+
s, err := avro.Parse(schema.Schema)
7365
if err != nil {
7466
return nil, fmt.Errorf("unable to parse schema: %v", err)
7567
}
76-
schemaStr = refCodec.String()
68+
return s, nil
7769
}
78-
codec, err := goavro.NewCodec(schemaStr)
70+
cache := avro.NewSchemaCache()
71+
if err := parseAvroReferences(ctx, cl, cache, schema); err != nil {
72+
return nil, fmt.Errorf("unable to parse references: %v", err)
73+
}
74+
s, err := cache.Parse(schema.Schema)
7975
if err != nil {
80-
return nil, fmt.Errorf("unable to generate codec for the given schema: %v", err)
76+
return nil, fmt.Errorf("unable to parse schema: %v", err)
8177
}
82-
return codec, nil
78+
return s, nil
8379
}
8480

85-
// parseAvroReferences uses hamba/avro Parse method to parse every reference. We
86-
// don't need to store the references since the library already cache these
87-
// schemas and use it later for handling references in the parent schema.
88-
func parseAvroReferences(ctx context.Context, cl *sr.Client, schema *sr.Schema) error {
89-
if len(schema.References) == 0 {
90-
_, err := avro.Parse(schema.Schema)
91-
if err != nil {
92-
return err
93-
}
94-
return nil
95-
}
81+
// parseAvroReferences recursively parses all schema references into the cache
82+
// so they are available when parsing the parent schema.
83+
func parseAvroReferences(ctx context.Context, cl *sr.Client, cache *avro.SchemaCache, schema *sr.Schema) error {
9684
for _, ref := range schema.References {
9785
r, err := cl.SchemaByVersion(ctx, ref.Subject, ref.Version)
9886
if err != nil {
9987
return err
10088
}
10189
refSchema := r.Schema
102-
err = parseAvroReferences(ctx, cl, &refSchema)
103-
if err != nil {
90+
if len(refSchema.References) > 0 {
91+
if err := parseAvroReferences(ctx, cl, cache, &refSchema); err != nil {
92+
return fmt.Errorf("unable to parse schema with subject %q and version %v: %v", ref.Subject, ref.Version, err)
93+
}
94+
}
95+
if _, err := cache.Parse(refSchema.Schema); err != nil {
10496
return fmt.Errorf("unable to parse schema with subject %q and version %v: %v", ref.Subject, ref.Version, err)
10597
}
10698
}
107-
_, err := avro.Parse(schema.Schema)
108-
if err != nil {
109-
return err
110-
}
11199
return nil
112100
}

src/go/rpk/pkg/serde/serde.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,15 @@ type Serde struct {
3434
func NewSerde(ctx context.Context, cl *sr.Client, schema *sr.Schema, schemaID int, protoFQN string) (*Serde, error) {
3535
switch schema.Type {
3636
case sr.TypeAvro:
37-
codec, err := generateAvroCodec(ctx, cl, schema)
37+
avroSchema, err := generateAvroSchema(ctx, cl, schema)
3838
if err != nil {
3939
return nil, fmt.Errorf("unable to parse avro schema: %v", err)
4040
}
41-
encFn, err := newAvroEncoder(codec, schemaID)
41+
encFn, err := newAvroEncoder(avroSchema, schemaID)
4242
if err != nil {
4343
return nil, fmt.Errorf("unable to build avro encoder: %v", err)
4444
}
45-
decFn, err := newAvroDecoder(codec)
45+
decFn, err := newAvroDecoder(avroSchema)
4646
if err != nil {
4747
return nil, fmt.Errorf("unable to build avro decoder: %v", err)
4848
}

0 commit comments

Comments
 (0)