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 }