Skip to content

Commit 112cf7a

Browse files
authored
Migrate to hamba/avro (#346)
1 parent 911dee5 commit 112cf7a

6 files changed

Lines changed: 57 additions & 21 deletions

File tree

avro.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package kafka
22

3+
import (
4+
"encoding/json"
5+
6+
"github.com/hamba/avro/v2"
7+
)
8+
39
type AvroSerde struct {
410
Serdes
511
}
@@ -11,12 +17,19 @@ func (*AvroSerde) Serialize(data interface{}, schema *Schema) ([]byte, *Xk6Kafka
1117
return nil, err
1218
}
1319

14-
encodedData, _, originalErr := schema.Codec().NativeFromTextual(jsonBytes)
15-
if originalErr != nil {
16-
return nil, NewXk6KafkaError(failedToEncode, "Failed to encode data", originalErr)
20+
avroSchema := schema.Codec()
21+
if avroSchema == nil {
22+
return nil, NewXk6KafkaError(failedToEncode, "Failed to parse Avro schema", nil)
1723
}
1824

19-
bytesData, originalErr := schema.Codec().BinaryFromNative(nil, encodedData)
25+
// Parse JSON data into a map for marshaling
26+
var jsonData interface{}
27+
if jsonErr := json.Unmarshal(jsonBytes, &jsonData); jsonErr != nil {
28+
return nil, NewXk6KafkaError(failedToEncode, "Failed to parse JSON data", jsonErr)
29+
}
30+
31+
// Marshal to binary using hamba/avro
32+
bytesData, originalErr := avro.Marshal(avroSchema, jsonData)
2033
if originalErr != nil {
2134
return nil, NewXk6KafkaError(failedToEncodeToBinary,
2235
"Failed to encode data into binary",
@@ -28,7 +41,13 @@ func (*AvroSerde) Serialize(data interface{}, schema *Schema) ([]byte, *Xk6Kafka
2841

2942
// Deserialize deserializes a Avro binary into a JSON object.
3043
func (*AvroSerde) Deserialize(data []byte, schema *Schema) (interface{}, *Xk6KafkaError) {
31-
decodedData, _, err := schema.Codec().NativeFromBinary(data)
44+
avroSchema := schema.Codec()
45+
if avroSchema == nil {
46+
return nil, NewXk6KafkaError(failedToDecodeFromBinary, "Failed to parse Avro schema", nil)
47+
}
48+
49+
var decodedData interface{}
50+
err := avro.Unmarshal(avroSchema, data, &decodedData)
3251
if err != nil {
3352
return nil, NewXk6KafkaError(
3453
failedToDecodeFromBinary, "Failed to decode data", err)
@@ -37,6 +56,6 @@ func (*AvroSerde) Deserialize(data []byte, schema *Schema) (interface{}, *Xk6Kaf
3756
if data, ok := decodedData.(map[string]interface{}); ok {
3857
return data, nil
3958
} else {
40-
return nil, ErrInvalidDataType
59+
return decodedData, nil
4160
}
4261
}

avro_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ func TestSerializeAvroFailsOnValidation(t *testing.T) {
6262
actual, err := avroSerde.Serialize(map[string]interface{}{"value": "key"}, schema)
6363
assert.Nil(t, actual)
6464
assert.NotNil(t, err)
65-
assert.Equal(t, "Failed to encode data", err.Message)
66-
assert.Equal(t, failedToEncode, err.Code)
65+
assert.Equal(t, "Failed to encode data into binary", err.Message)
66+
assert.Equal(t, failedToEncodeToBinary, err.Code)
6767
}
6868

6969
// TestDeserializeAvro tests the deserialization of a JSON object from Avro binary.

go.mod

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ require (
88
github.com/aws/aws-sdk-go-v2 v1.39.0
99
github.com/aws/aws-sdk-go-v2/config v1.31.7
1010
github.com/grafana/sobek v0.0.0-20250723111835-dd8a13f0d439
11-
github.com/linkedin/goavro/v2 v2.14.0
11+
github.com/hamba/avro/v2 v2.29.0
1212
github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0
1313
github.com/riferrei/srclient v0.7.3
1414
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
@@ -41,15 +41,20 @@ require (
4141
github.com/go-logr/logr v1.4.3 // indirect
4242
github.com/go-logr/stdr v1.2.2 // indirect
4343
github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect
44+
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
4445
github.com/golang/snappy v1.0.0 // indirect
4546
github.com/google/pprof v0.0.0-20230728192033-2ba5b33183c6 // indirect
4647
github.com/google/uuid v1.6.0 // indirect
4748
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect
4849
github.com/josharian/intern v1.0.0 // indirect
50+
github.com/json-iterator/go v1.1.12 // indirect
4951
github.com/klauspost/compress v1.18.0 // indirect
52+
github.com/linkedin/goavro/v2 v2.13.1 // indirect
5053
github.com/mailru/easyjson v0.9.0 // indirect
5154
github.com/mattn/go-colorable v0.1.14 // indirect
5255
github.com/mattn/go-isatty v0.0.20 // indirect
56+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
57+
github.com/modern-go/reflect2 v1.0.2 // indirect
5358
github.com/mstoykov/atlas v0.0.0-20220811071828-388f114305dd // indirect
5459
github.com/mstoykov/k6-taskqueue-lib v0.1.3 // indirect
5560
github.com/pierrec/lz4/v4 v4.1.22 // indirect

go.sum

Lines changed: 14 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

schema_registry.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"net/http"
88

99
"github.com/grafana/sobek"
10-
"github.com/linkedin/goavro/v2"
10+
"github.com/hamba/avro/v2"
1111
"github.com/riferrei/srclient"
1212
"github.com/santhosh-tekuri/jsonschema/v5"
1313
"go.k6.io/k6/js/common"
@@ -50,7 +50,7 @@ type Schema struct {
5050
Version int `json:"version"`
5151
References []srclient.Reference `json:"references"`
5252
Subject string `json:"subject"`
53-
codec *goavro.Codec
53+
avroSchema avro.Schema
5454
jsonSchema *jsonschema.Schema
5555
}
5656

@@ -66,17 +66,17 @@ type WireFormat struct {
6666
Data []byte `json:"data"`
6767
}
6868

69-
// Codec ensures access to Codec
69+
// Codec ensures access to parsed Avro Schema
7070
// Will try to initialize a new one if it hasn't been initialized before
71-
// Will return nil if it can't initialize a codec from the schema
72-
func (s *Schema) Codec() *goavro.Codec {
73-
if s.codec == nil {
74-
codec, err := goavro.NewCodec(s.Schema)
71+
// Will return nil if it can't initialize a schema from the schema string
72+
func (s *Schema) Codec() avro.Schema {
73+
if s.avroSchema == nil {
74+
schema, err := avro.Parse(s.Schema)
7575
if err == nil {
76-
s.codec = codec
76+
s.avroSchema = schema
7777
}
7878
}
79-
return s.codec
79+
return s.avroSchema
8080
}
8181

8282
// JsonSchema ensures access to JsonSchema

serdes_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ func TestSerializeFails(t *testing.T) {
207207
},
208208
SchemaType: srclient.Avro,
209209
},
210-
err: NewXk6KafkaError(failedToEncode, "Failed to encode data", errors.New("cannot decode textual record \"io.confluent.kafka.avro.Schema\": cannot decode textual map: cannot determine codec: \"unknown\"")),
210+
err: NewXk6KafkaError(failedToEncodeToBinary, "Failed to encode data into binary", errors.New("avro: missing required field key")),
211211
},
212212
{
213213
container: &Container{

0 commit comments

Comments
 (0)