"github.com/apache/rocketmq-client-go/v2"
"github.com/apache/rocketmq-client-go/v2/consumer"
"github.com/apache/rocketmq-client-go/v2/primitive"
"github.com/twpayne/go-geom/encoding/wkb"
"github.com/twpayne/go-geom/encoding/wkt"
"github.com/volcengine/volc-sdk-golang/example/dts/data-subscription-demo/avro/avro"
"your path of code generated by avro compilation/avro"
nameserver := "your nameserver address"
accessKey := "your access key"
secretKey := "your secret key"
cli, _ := rocketmq.NewPushConsumer(
consumer.WithGroupName(group),
consumer.WithNsResolver(primitive.NewPassthroughResolver(strings.Split(nameserver, ","))),
consumer.WithConsumerModel(consumer.Clustering),
consumer.WithConsumerOrder(true),
consumer.WithCredentials(primitive.Credentials{
err := cli.Subscribe(topic, consumer.MessageSelector{}, func(ctx context.Context, msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
for _, msg := range msgs {
record, err := avro.DeserializeRecord(bytes.NewReader(msg.Body))
return consumer.ConsumeSuccess, nil
func printRecord(record *avro.Record) {
fmt.Printf("Operation[%s] ObjectName[%s] SourceTimestamp[%v] Id[%v]\n",
record.Operation.String(), record.ObjectName.String, record.SourceTimestamp, record.Id)
switch record.Operation {
fmt.Printf("DDL[%s] \n", record.AfterImages.String)
case avro.OperationINSERT:
for i := 0; i < len(record.AfterImages.ArrayUnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObject); i++ {
after, err := getValue(record.AfterImages.ArrayUnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObject[i])
fmt.Printf("Field[%s] After[%s]\n", record.Fields.ArrayField[i].Name, after)
case avro.OperationUPDATE:
for i := 0; i < len(record.AfterImages.ArrayUnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObject); i++ {
before, err := getValue(record.BeforeImages.ArrayUnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObject[i])
after, err := getValue(record.AfterImages.ArrayUnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObject[i])
fmt.Printf("Field[%s] Before[%s] After[%s]\n", record.Fields.ArrayField[i].Name, before, after)
case avro.OperationDELETE:
for i := 0; i < len(record.BeforeImages.ArrayUnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObject); i++ {
before, err := getValue(record.BeforeImages.ArrayUnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObject[i])
fmt.Printf("Field[%s] Before[%s]\n", record.Fields.ArrayField[i].Name, before)
func getValue(in *avro.UnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObject) (string, error) {
case avro.UnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObjectTypeEnumInteger:
return in.Integer.Value, nil
case avro.UnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObjectTypeEnumCharacter:
return string(in.Character.Value), nil
case avro.UnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObjectTypeEnumDecimal:
return fmt.Sprintf("%s", in.Decimal.Value), nil
case avro.UnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObjectTypeEnumFloat:
return fmt.Sprintf("%v", in.Float.Value), nil
case avro.UnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObjectTypeEnumTimestamp:
return fmt.Sprintf("%v.%v", in.Timestamp.Timestamp, in.Timestamp.Millis), nil
case avro.UnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObjectTypeEnumDateTime:
var year, month, day, hour, minute, second int32
if in.DateTime.Year != nil {
year = in.DateTime.Year.Int
if in.DateTime.Month != nil {
month = in.DateTime.Month.Int
if in.DateTime.Day != nil {
day = in.DateTime.Day.Int
if in.DateTime.Hour != nil {
hour = in.DateTime.Hour.Int
if in.DateTime.Minute != nil {
minute = in.DateTime.Minute.Int
if in.DateTime.Second != nil {
second = in.DateTime.Second.Int
return fmt.Sprintf("%v-%v-%v %v:%v:%v", year, month, day, hour, minute, second), nil
return fmt.Sprintf("%v:%v:%v", hour, minute, second), nil
case avro.UnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObjectTypeEnumTimestampWithTimeZone:
var year, month, day, hour, minute, second int32
if in.TimestampWithTimeZone.Value.Year != nil {
year = in.TimestampWithTimeZone.Value.Year.Int
if in.TimestampWithTimeZone.Value.Month != nil {
month = in.TimestampWithTimeZone.Value.Month.Int
if in.TimestampWithTimeZone.Value.Day != nil {
day = in.TimestampWithTimeZone.Value.Day.Int
if in.TimestampWithTimeZone.Value.Hour != nil {
hour = in.TimestampWithTimeZone.Value.Hour.Int
if in.TimestampWithTimeZone.Value.Minute != nil {
minute = in.TimestampWithTimeZone.Value.Minute.Int
if in.TimestampWithTimeZone.Value.Second != nil {
second = in.TimestampWithTimeZone.Value.Second.Int
return fmt.Sprintf("%v-%v-%v %v:%v:%v+%v", year, month, day, hour, minute, second, in.TimestampWithTimeZone.Timezone), nil
return fmt.Sprintf("%v:%v:%v", hour, minute, second), nil
case avro.UnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObjectTypeEnumBinaryGeometry:
return getReadableGeometry(in.BinaryGeometry.Value)
case avro.UnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObjectTypeEnumTextGeometry:
return getReadableGeometry([]byte(in.TextGeometry.Value))
case avro.UnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObjectTypeEnumBinaryObject:
return fmt.Sprintf("%s", string(in.BinaryObject.Value)), nil
case avro.UnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObjectTypeEnumTextObject:
return fmt.Sprintf("%s", in.TextObject.Value), nil
case avro.UnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObjectTypeEnumEmptyObject:
return fmt.Sprintf("%s", in.EmptyObject.String()), nil
return "", fmt.Errorf("invalid value for *UnionNullIntegerCharacterDecimalFloatTimestampDateTimeTimestampWithTimeZoneBinaryGeometryTextGeometryBinaryObjectTextObjectEmptyObject")
func getReadableGeometry(raw []byte) (string, error) {
return "", fmt.Errorf("not a valid geometry %v", raw)
geomObj, err := wkb.Unmarshal(raw[4:])
wktObj, err := wkt.Marshal(geomObj)