go.temporal.io/server@v1.23.0/common/persistence/serialization/serializer.go (about)

     1  // The MIT License
     2  //
     3  // Copyright (c) 2020 Temporal Technologies Inc.  All rights reserved.
     4  //
     5  // Copyright (c) 2020 Uber Technologies, Inc.
     6  //
     7  // Permission is hereby granted, free of charge, to any person obtaining a copy
     8  // of this software and associated documentation files (the "Software"), to deal
     9  // in the Software without restriction, including without limitation the rights
    10  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    11  // copies of the Software, and to permit persons to whom the Software is
    12  // furnished to do so, subject to the following conditions:
    13  //
    14  // The above copyright notice and this permission notice shall be included in
    15  // all copies or substantial portions of the Software.
    16  //
    17  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    18  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    19  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    20  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    21  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    22  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    23  // THE SOFTWARE.
    24  
    25  package serialization
    26  
    27  import (
    28  	"errors"
    29  	"fmt"
    30  	"reflect"
    31  	"strings"
    32  
    33  	commonpb "go.temporal.io/api/common/v1"
    34  	enumspb "go.temporal.io/api/enums/v1"
    35  	historypb "go.temporal.io/api/history/v1"
    36  	"google.golang.org/protobuf/proto"
    37  
    38  	enumsspb "go.temporal.io/server/api/enums/v1"
    39  	persistencespb "go.temporal.io/server/api/persistence/v1"
    40  	replicationspb "go.temporal.io/server/api/replication/v1"
    41  	"go.temporal.io/server/common/codec"
    42  	"go.temporal.io/server/service/history/tasks"
    43  )
    44  
    45  type (
    46  	// Serializer is used by persistence to serialize/deserialize objects
    47  	// It will only be used inside persistence, so that serialize/deserialize is transparent for application
    48  	Serializer interface {
    49  		SerializeEvents(batch []*historypb.HistoryEvent, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    50  		DeserializeEvents(data *commonpb.DataBlob) ([]*historypb.HistoryEvent, error)
    51  
    52  		SerializeEvent(event *historypb.HistoryEvent, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    53  		DeserializeEvent(data *commonpb.DataBlob) (*historypb.HistoryEvent, error)
    54  
    55  		SerializeClusterMetadata(icm *persistencespb.ClusterMetadata, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    56  		DeserializeClusterMetadata(data *commonpb.DataBlob) (*persistencespb.ClusterMetadata, error)
    57  
    58  		ShardInfoToBlob(info *persistencespb.ShardInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    59  		ShardInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.ShardInfo, error)
    60  
    61  		NamespaceDetailToBlob(info *persistencespb.NamespaceDetail, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    62  		NamespaceDetailFromBlob(data *commonpb.DataBlob) (*persistencespb.NamespaceDetail, error)
    63  
    64  		HistoryTreeInfoToBlob(info *persistencespb.HistoryTreeInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    65  		HistoryTreeInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.HistoryTreeInfo, error)
    66  
    67  		HistoryBranchToBlob(info *persistencespb.HistoryBranch, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    68  		HistoryBranchFromBlob(data *commonpb.DataBlob) (*persistencespb.HistoryBranch, error)
    69  
    70  		WorkflowExecutionInfoToBlob(info *persistencespb.WorkflowExecutionInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    71  		WorkflowExecutionInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.WorkflowExecutionInfo, error)
    72  
    73  		WorkflowExecutionStateToBlob(info *persistencespb.WorkflowExecutionState, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    74  		WorkflowExecutionStateFromBlob(data *commonpb.DataBlob) (*persistencespb.WorkflowExecutionState, error)
    75  
    76  		ActivityInfoToBlob(info *persistencespb.ActivityInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    77  		ActivityInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.ActivityInfo, error)
    78  
    79  		ChildExecutionInfoToBlob(info *persistencespb.ChildExecutionInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    80  		ChildExecutionInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.ChildExecutionInfo, error)
    81  
    82  		SignalInfoToBlob(info *persistencespb.SignalInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    83  		SignalInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.SignalInfo, error)
    84  
    85  		RequestCancelInfoToBlob(info *persistencespb.RequestCancelInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    86  		RequestCancelInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.RequestCancelInfo, error)
    87  
    88  		TimerInfoToBlob(info *persistencespb.TimerInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    89  		TimerInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.TimerInfo, error)
    90  
    91  		TaskInfoToBlob(info *persistencespb.AllocatedTaskInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    92  		TaskInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.AllocatedTaskInfo, error)
    93  
    94  		TaskQueueInfoToBlob(info *persistencespb.TaskQueueInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    95  		TaskQueueInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.TaskQueueInfo, error)
    96  
    97  		TaskQueueUserDataToBlob(info *persistencespb.TaskQueueUserData, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
    98  		TaskQueueUserDataFromBlob(data *commonpb.DataBlob) (*persistencespb.TaskQueueUserData, error)
    99  
   100  		ChecksumToBlob(checksum *persistencespb.Checksum, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
   101  		ChecksumFromBlob(data *commonpb.DataBlob) (*persistencespb.Checksum, error)
   102  
   103  		QueueMetadataToBlob(metadata *persistencespb.QueueMetadata, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
   104  		QueueMetadataFromBlob(data *commonpb.DataBlob) (*persistencespb.QueueMetadata, error)
   105  
   106  		ReplicationTaskToBlob(replicationTask *replicationspb.ReplicationTask, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error)
   107  		ReplicationTaskFromBlob(data *commonpb.DataBlob) (*replicationspb.ReplicationTask, error)
   108  		// ParseReplicationTask is unique among these methods in that it does not serialize or deserialize a type to or
   109  		// from a byte array. Instead, it takes a proto and "parses" it into a more structured type.
   110  		ParseReplicationTask(replicationTask *persistencespb.ReplicationTaskInfo) (tasks.Task, error)
   111  
   112  		SerializeTask(task tasks.Task) (*commonpb.DataBlob, error)
   113  		DeserializeTask(category tasks.Category, blob *commonpb.DataBlob) (tasks.Task, error)
   114  	}
   115  
   116  	// SerializationError is an error type for serialization
   117  	SerializationError struct {
   118  		encodingType enumspb.EncodingType
   119  		wrappedErr   error
   120  	}
   121  
   122  	// DeserializationError is an error type for deserialization
   123  	DeserializationError struct {
   124  		encodingType enumspb.EncodingType
   125  		wrappedErr   error
   126  	}
   127  
   128  	// UnknownEncodingTypeError is an error type for unknown or unsupported encoding type
   129  	UnknownEncodingTypeError struct {
   130  		providedType        string
   131  		expectedEncodingStr []string
   132  	}
   133  
   134  	serializerImpl struct {
   135  		TaskSerializer
   136  	}
   137  
   138  	marshaler interface {
   139  		Marshal() ([]byte, error)
   140  	}
   141  )
   142  
   143  // NewSerializer returns a PayloadSerializer
   144  func NewSerializer() Serializer {
   145  	return &serializerImpl{}
   146  }
   147  
   148  func (t *serializerImpl) SerializeEvents(events []*historypb.HistoryEvent, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   149  	return t.serialize(&historypb.History{Events: events}, encodingType)
   150  }
   151  
   152  func (t *serializerImpl) DeserializeEvents(data *commonpb.DataBlob) ([]*historypb.HistoryEvent, error) {
   153  	if data == nil {
   154  		return nil, nil
   155  	}
   156  	if len(data.Data) == 0 {
   157  		return nil, nil
   158  	}
   159  
   160  	events := &historypb.History{}
   161  	var err error
   162  	switch data.EncodingType {
   163  	case enumspb.ENCODING_TYPE_PROTO3:
   164  		// Client API currently specifies encodingType on requests which span multiple of these objects
   165  		err = events.Unmarshal(data.Data)
   166  	default:
   167  		return nil, NewUnknownEncodingTypeError(data.EncodingType.String(), enumspb.ENCODING_TYPE_PROTO3)
   168  	}
   169  	if err != nil {
   170  		return nil, err
   171  	}
   172  	return events.Events, nil
   173  }
   174  
   175  func (t *serializerImpl) SerializeEvent(event *historypb.HistoryEvent, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   176  	if event == nil {
   177  		return nil, nil
   178  	}
   179  	return t.serialize(event, encodingType)
   180  }
   181  
   182  func (t *serializerImpl) DeserializeEvent(data *commonpb.DataBlob) (*historypb.HistoryEvent, error) {
   183  	if data == nil {
   184  		return nil, nil
   185  	}
   186  	if len(data.Data) == 0 {
   187  		return nil, nil
   188  	}
   189  
   190  	event := &historypb.HistoryEvent{}
   191  	var err error
   192  	switch data.EncodingType {
   193  	case enumspb.ENCODING_TYPE_PROTO3:
   194  		// Client API currently specifies encodingType on requests which span multiple of these objects
   195  		err = event.Unmarshal(data.Data)
   196  	default:
   197  		return nil, NewUnknownEncodingTypeError(data.EncodingType.String(), enumspb.ENCODING_TYPE_PROTO3)
   198  	}
   199  
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  
   204  	return event, err
   205  }
   206  
   207  func (t *serializerImpl) SerializeClusterMetadata(cm *persistencespb.ClusterMetadata, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   208  	if cm == nil {
   209  		cm = &persistencespb.ClusterMetadata{}
   210  	}
   211  	return t.serialize(cm, encodingType)
   212  }
   213  
   214  func (t *serializerImpl) DeserializeClusterMetadata(data *commonpb.DataBlob) (*persistencespb.ClusterMetadata, error) {
   215  	if data == nil {
   216  		return nil, nil
   217  	}
   218  	if len(data.Data) == 0 {
   219  		return nil, nil
   220  	}
   221  
   222  	cm := &persistencespb.ClusterMetadata{}
   223  	var err error
   224  	switch data.EncodingType {
   225  	case enumspb.ENCODING_TYPE_PROTO3:
   226  		// Thrift == Proto for this object so that we can maintain test behavior until thrift is gone
   227  		// Client API currently specifies encodingType on requests which span multiple of these objects
   228  		err = cm.Unmarshal(data.Data)
   229  	default:
   230  		return nil, NewUnknownEncodingTypeError(data.EncodingType.String(), enumspb.ENCODING_TYPE_PROTO3)
   231  	}
   232  
   233  	if err != nil {
   234  		return nil, err
   235  	}
   236  
   237  	return cm, err
   238  }
   239  
   240  func (t *serializerImpl) serialize(p marshaler, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   241  	if p == nil {
   242  		return nil, nil
   243  	}
   244  
   245  	var data []byte
   246  	var err error
   247  
   248  	switch encodingType {
   249  	case enumspb.ENCODING_TYPE_PROTO3:
   250  		// Client API currently specifies encodingType on requests which span multiple of these objects
   251  		data, err = p.Marshal()
   252  	default:
   253  		return nil, NewUnknownEncodingTypeError(encodingType.String(), enumspb.ENCODING_TYPE_PROTO3)
   254  	}
   255  
   256  	if err != nil {
   257  		return nil, NewSerializationError(enumspb.ENCODING_TYPE_PROTO3, err)
   258  	}
   259  
   260  	// Shouldn't happen, but keeping
   261  	if data == nil {
   262  		return nil, nil
   263  	}
   264  
   265  	return &commonpb.DataBlob{
   266  		Data:         data,
   267  		EncodingType: encodingType,
   268  	}, nil
   269  }
   270  
   271  // NewUnknownEncodingTypeError returns a new instance of encoding type error
   272  func NewUnknownEncodingTypeError(
   273  	providedType string,
   274  	expectedEncoding ...enumspb.EncodingType,
   275  ) error {
   276  	if len(expectedEncoding) == 0 {
   277  		for encodingType := range enumspb.EncodingType_name {
   278  			expectedEncoding = append(expectedEncoding, enumspb.EncodingType(encodingType))
   279  		}
   280  	}
   281  	expectedEncodingStr := make([]string, 0, len(expectedEncoding))
   282  	for _, encodingType := range expectedEncoding {
   283  		expectedEncodingStr = append(expectedEncodingStr, encodingType.String())
   284  	}
   285  	return &UnknownEncodingTypeError{
   286  		providedType:        providedType,
   287  		expectedEncodingStr: expectedEncodingStr,
   288  	}
   289  }
   290  
   291  func (e *UnknownEncodingTypeError) Error() string {
   292  	return fmt.Sprintf("unknown or unsupported encoding type %v, supported types: %v",
   293  		e.providedType,
   294  		strings.Join(e.expectedEncodingStr, ","),
   295  	)
   296  }
   297  
   298  // IsTerminalTaskError informs our task processing subsystem that it is impossible
   299  // to retry this error
   300  func (e *UnknownEncodingTypeError) IsTerminalTaskError() {}
   301  
   302  // NewSerializationError returns a SerializationError
   303  func NewSerializationError(
   304  	encodingType enumspb.EncodingType,
   305  	serializationErr error,
   306  ) error {
   307  	return &SerializationError{
   308  		encodingType: encodingType,
   309  		wrappedErr:   serializationErr,
   310  	}
   311  }
   312  
   313  func (e *SerializationError) Error() string {
   314  	return fmt.Sprintf("error serializing using %v encoding: %v", e.encodingType, e.wrappedErr)
   315  }
   316  
   317  func (e *SerializationError) Unwrap() error {
   318  	return e.wrappedErr
   319  }
   320  
   321  // NewDeserializationError returns a DeserializationError
   322  func NewDeserializationError(
   323  	encodingType enumspb.EncodingType,
   324  	deserializationErr error,
   325  ) error {
   326  	return &DeserializationError{
   327  		encodingType: encodingType,
   328  		wrappedErr:   deserializationErr,
   329  	}
   330  }
   331  
   332  func (e *DeserializationError) Error() string {
   333  	return fmt.Sprintf("error deserializing using %v encoding: %v", e.encodingType, e.wrappedErr)
   334  }
   335  
   336  func (e *DeserializationError) Unwrap() error {
   337  	return e.wrappedErr
   338  }
   339  
   340  // IsTerminalTaskError informs our task processing subsystem that it is impossible to
   341  // retry this error and that the task should be sent to a DLQ
   342  func (e *DeserializationError) IsTerminalTaskError() {}
   343  
   344  func (t *serializerImpl) ShardInfoToBlob(info *persistencespb.ShardInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   345  	return ProtoEncodeBlob(info, encodingType)
   346  }
   347  
   348  func (t *serializerImpl) ShardInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.ShardInfo, error) {
   349  	shardInfo := &persistencespb.ShardInfo{}
   350  	err := ProtoDecodeBlob(data, shardInfo)
   351  
   352  	if err != nil {
   353  		return nil, err
   354  	}
   355  
   356  	if shardInfo.GetReplicationDlqAckLevel() == nil {
   357  		shardInfo.ReplicationDlqAckLevel = make(map[string]int64)
   358  	}
   359  
   360  	if shardInfo.GetQueueStates() == nil {
   361  		shardInfo.QueueStates = make(map[int32]*persistencespb.QueueState)
   362  	}
   363  	for _, queueState := range shardInfo.QueueStates {
   364  		if queueState.ReaderStates == nil {
   365  			queueState.ReaderStates = make(map[int64]*persistencespb.QueueReaderState)
   366  		}
   367  		for _, readerState := range queueState.ReaderStates {
   368  			if readerState.Scopes == nil {
   369  				readerState.Scopes = make([]*persistencespb.QueueSliceScope, 0)
   370  			}
   371  		}
   372  	}
   373  
   374  	return shardInfo, nil
   375  }
   376  
   377  func (t *serializerImpl) NamespaceDetailToBlob(info *persistencespb.NamespaceDetail, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   378  	return ProtoEncodeBlob(info, encodingType)
   379  }
   380  
   381  func (t *serializerImpl) NamespaceDetailFromBlob(data *commonpb.DataBlob) (*persistencespb.NamespaceDetail, error) {
   382  	result := &persistencespb.NamespaceDetail{}
   383  	return result, ProtoDecodeBlob(data, result)
   384  }
   385  
   386  func (t *serializerImpl) HistoryTreeInfoToBlob(info *persistencespb.HistoryTreeInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   387  	return ProtoEncodeBlob(info, encodingType)
   388  }
   389  
   390  func (t *serializerImpl) HistoryTreeInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.HistoryTreeInfo, error) {
   391  	result := &persistencespb.HistoryTreeInfo{}
   392  	return result, ProtoDecodeBlob(data, result)
   393  }
   394  
   395  func (t *serializerImpl) HistoryBranchToBlob(info *persistencespb.HistoryBranch, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   396  	return ProtoEncodeBlob(info, encodingType)
   397  }
   398  
   399  func (t *serializerImpl) HistoryBranchFromBlob(data *commonpb.DataBlob) (*persistencespb.HistoryBranch, error) {
   400  	result := &persistencespb.HistoryBranch{}
   401  	return result, ProtoDecodeBlob(data, result)
   402  }
   403  
   404  func (t *serializerImpl) WorkflowExecutionInfoToBlob(info *persistencespb.WorkflowExecutionInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   405  	return ProtoEncodeBlob(info, encodingType)
   406  }
   407  
   408  func (t *serializerImpl) WorkflowExecutionInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.WorkflowExecutionInfo, error) {
   409  	result := &persistencespb.WorkflowExecutionInfo{}
   410  	return result, ProtoDecodeBlob(data, result)
   411  }
   412  
   413  func (t *serializerImpl) WorkflowExecutionStateToBlob(info *persistencespb.WorkflowExecutionState, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   414  	return ProtoEncodeBlob(info, encodingType)
   415  }
   416  
   417  func (t *serializerImpl) WorkflowExecutionStateFromBlob(data *commonpb.DataBlob) (*persistencespb.WorkflowExecutionState, error) {
   418  	result := &persistencespb.WorkflowExecutionState{}
   419  	return result, ProtoDecodeBlob(data, result)
   420  }
   421  
   422  func (t *serializerImpl) ActivityInfoToBlob(info *persistencespb.ActivityInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   423  	return ProtoEncodeBlob(info, encodingType)
   424  }
   425  
   426  func (t *serializerImpl) ActivityInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.ActivityInfo, error) {
   427  	result := &persistencespb.ActivityInfo{}
   428  	return result, ProtoDecodeBlob(data, result)
   429  }
   430  
   431  func (t *serializerImpl) ChildExecutionInfoToBlob(info *persistencespb.ChildExecutionInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   432  	return ProtoEncodeBlob(info, encodingType)
   433  }
   434  
   435  func (t *serializerImpl) ChildExecutionInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.ChildExecutionInfo, error) {
   436  	result := &persistencespb.ChildExecutionInfo{}
   437  	return result, ProtoDecodeBlob(data, result)
   438  }
   439  
   440  func (t *serializerImpl) SignalInfoToBlob(info *persistencespb.SignalInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   441  	return ProtoEncodeBlob(info, encodingType)
   442  }
   443  
   444  func (t *serializerImpl) SignalInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.SignalInfo, error) {
   445  	result := &persistencespb.SignalInfo{}
   446  	return result, ProtoDecodeBlob(data, result)
   447  }
   448  
   449  func (t *serializerImpl) RequestCancelInfoToBlob(info *persistencespb.RequestCancelInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   450  	return ProtoEncodeBlob(info, encodingType)
   451  }
   452  
   453  func (t *serializerImpl) RequestCancelInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.RequestCancelInfo, error) {
   454  	result := &persistencespb.RequestCancelInfo{}
   455  	return result, ProtoDecodeBlob(data, result)
   456  }
   457  
   458  func (t *serializerImpl) TimerInfoToBlob(info *persistencespb.TimerInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   459  	return ProtoEncodeBlob(info, encodingType)
   460  }
   461  
   462  func (t *serializerImpl) TimerInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.TimerInfo, error) {
   463  	result := &persistencespb.TimerInfo{}
   464  	return result, ProtoDecodeBlob(data, result)
   465  }
   466  
   467  func (t *serializerImpl) TaskInfoToBlob(info *persistencespb.AllocatedTaskInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   468  	return ProtoEncodeBlob(info, encodingType)
   469  }
   470  
   471  func (t *serializerImpl) TaskInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.AllocatedTaskInfo, error) {
   472  	result := &persistencespb.AllocatedTaskInfo{}
   473  	return result, ProtoDecodeBlob(data, result)
   474  }
   475  
   476  func (t *serializerImpl) TaskQueueInfoToBlob(info *persistencespb.TaskQueueInfo, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   477  	return ProtoEncodeBlob(info, encodingType)
   478  }
   479  
   480  func (t *serializerImpl) TaskQueueInfoFromBlob(data *commonpb.DataBlob) (*persistencespb.TaskQueueInfo, error) {
   481  	result := &persistencespb.TaskQueueInfo{}
   482  	return result, ProtoDecodeBlob(data, result)
   483  }
   484  
   485  func (t *serializerImpl) TaskQueueUserDataToBlob(data *persistencespb.TaskQueueUserData, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   486  	return ProtoEncodeBlob(data, encodingType)
   487  }
   488  
   489  func (t *serializerImpl) TaskQueueUserDataFromBlob(data *commonpb.DataBlob) (*persistencespb.TaskQueueUserData, error) {
   490  	result := &persistencespb.TaskQueueUserData{}
   491  	return result, ProtoDecodeBlob(data, result)
   492  }
   493  
   494  func (t *serializerImpl) ChecksumToBlob(checksum *persistencespb.Checksum, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   495  	// nil is replaced with empty object because it is not supported for "checksum" field in DB.
   496  	if checksum == nil {
   497  		checksum = &persistencespb.Checksum{}
   498  	}
   499  	return ProtoEncodeBlob(checksum, encodingType)
   500  }
   501  
   502  func (t *serializerImpl) ChecksumFromBlob(data *commonpb.DataBlob) (*persistencespb.Checksum, error) {
   503  	result := &persistencespb.Checksum{}
   504  	err := ProtoDecodeBlob(data, result)
   505  	if err != nil || result.GetFlavor() == enumsspb.CHECKSUM_FLAVOR_UNSPECIFIED {
   506  		// If result is an empty struct (Flavor is unspecified), replace it with nil, because everywhere in the code checksum is pointer type.
   507  		return nil, err
   508  	}
   509  	return result, nil
   510  }
   511  
   512  func (t *serializerImpl) QueueMetadataToBlob(metadata *persistencespb.QueueMetadata, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   513  	return encodeBlob(metadata, encodingType)
   514  }
   515  
   516  func (t *serializerImpl) QueueMetadataFromBlob(data *commonpb.DataBlob) (*persistencespb.QueueMetadata, error) {
   517  	result := &persistencespb.QueueMetadata{}
   518  	return result, decodeBlob(data, result)
   519  }
   520  
   521  func (t *serializerImpl) ReplicationTaskToBlob(replicationTask *replicationspb.ReplicationTask, encodingType enumspb.EncodingType) (*commonpb.DataBlob, error) {
   522  	return ProtoEncodeBlob(replicationTask, encodingType)
   523  }
   524  
   525  func (t *serializerImpl) ReplicationTaskFromBlob(data *commonpb.DataBlob) (*replicationspb.ReplicationTask, error) {
   526  	result := &replicationspb.ReplicationTask{}
   527  	return result, ProtoDecodeBlob(data, result)
   528  }
   529  
   530  func ProtoDecodeBlob(data *commonpb.DataBlob, result proto.Message) error {
   531  	if data == nil {
   532  		// TODO: should we return nil or error?
   533  		return NewDeserializationError(enumspb.ENCODING_TYPE_UNSPECIFIED, errors.New("cannot decode nil"))
   534  	}
   535  
   536  	if data.EncodingType != enumspb.ENCODING_TYPE_PROTO3 {
   537  		return NewUnknownEncodingTypeError(data.EncodingType.String(), enumspb.ENCODING_TYPE_PROTO3)
   538  	}
   539  
   540  	if err := proto.Unmarshal(data.Data, result); err != nil {
   541  		return NewDeserializationError(enumspb.ENCODING_TYPE_PROTO3, err)
   542  	}
   543  	return nil
   544  }
   545  
   546  func decodeBlob(data *commonpb.DataBlob, result proto.Message) error {
   547  	if data == nil {
   548  		// TODO: should we return nil or error?
   549  		return NewDeserializationError(enumspb.ENCODING_TYPE_UNSPECIFIED, errors.New("cannot decode nil"))
   550  	}
   551  
   552  	if data.Data == nil {
   553  		return nil
   554  	}
   555  
   556  	switch data.EncodingType {
   557  	case enumspb.ENCODING_TYPE_JSON:
   558  		return codec.NewJSONPBEncoder().Decode(data.Data, result)
   559  	case enumspb.ENCODING_TYPE_PROTO3:
   560  		return ProtoDecodeBlob(data, result)
   561  	default:
   562  		return NewUnknownEncodingTypeError(data.EncodingType.String(), enumspb.ENCODING_TYPE_JSON, enumspb.ENCODING_TYPE_PROTO3)
   563  	}
   564  }
   565  
   566  func encodeBlob(o proto.Message, encoding enumspb.EncodingType) (*commonpb.DataBlob, error) {
   567  	if o == nil || (reflect.ValueOf(o).Kind() == reflect.Ptr && reflect.ValueOf(o).IsNil()) {
   568  		return &commonpb.DataBlob{
   569  			Data:         nil,
   570  			EncodingType: encoding,
   571  		}, nil
   572  	}
   573  
   574  	switch encoding {
   575  	case enumspb.ENCODING_TYPE_JSON:
   576  		blob, err := codec.NewJSONPBEncoder().Encode(o)
   577  		if err != nil {
   578  			return nil, err
   579  		}
   580  		return &commonpb.DataBlob{
   581  			Data:         blob,
   582  			EncodingType: enumspb.ENCODING_TYPE_JSON,
   583  		}, nil
   584  	case enumspb.ENCODING_TYPE_PROTO3:
   585  		return ProtoEncodeBlob(o, enumspb.ENCODING_TYPE_PROTO3)
   586  	default:
   587  		return nil, NewUnknownEncodingTypeError(encoding.String(), enumspb.ENCODING_TYPE_JSON, enumspb.ENCODING_TYPE_PROTO3)
   588  	}
   589  }
   590  
   591  func ProtoEncodeBlob(m proto.Message, encoding enumspb.EncodingType) (*commonpb.DataBlob, error) {
   592  	if encoding != enumspb.ENCODING_TYPE_PROTO3 {
   593  		return nil, NewUnknownEncodingTypeError(encoding.String(), enumspb.ENCODING_TYPE_PROTO3)
   594  	}
   595  
   596  	if m == nil || (reflect.ValueOf(m).Kind() == reflect.Ptr && reflect.ValueOf(m).IsNil()) {
   597  		// TODO: is this expected?
   598  		return &commonpb.DataBlob{
   599  			Data:         nil,
   600  			EncodingType: encoding,
   601  		}, nil
   602  	}
   603  
   604  	blob := &commonpb.DataBlob{EncodingType: enumspb.ENCODING_TYPE_PROTO3}
   605  	data, err := proto.Marshal(m)
   606  	if err != nil {
   607  		return nil, NewSerializationError(enumspb.ENCODING_TYPE_PROTO3, err)
   608  	}
   609  	blob.Data = data
   610  	return blob, nil
   611  }