github.com/asynkron/protoactor-go@v0.0.0-20240308120642-ef91a6abee75/cluster/pubsub_batch.go (about)

     1  package cluster
     2  
     3  import (
     4  	"github.com/asynkron/protoactor-go/actor"
     5  	"github.com/asynkron/protoactor-go/remote"
     6  	"google.golang.org/protobuf/proto"
     7  )
     8  
     9  var (
    10  	_ remote.RootSerializable = (*PubSubBatch)(nil)
    11  	_ remote.RootSerializable = (*DeliverBatchRequest)(nil)
    12  	_ remote.RootSerializable = (*PubSubAutoRespondBatch)(nil)
    13  
    14  	_ remote.RootSerialized = (*PubSubBatchTransport)(nil)
    15  	_ remote.RootSerialized = (*DeliverBatchRequestTransport)(nil)
    16  	_ remote.RootSerialized = (*PubSubAutoRespondBatchTransport)(nil)
    17  )
    18  
    19  type PubSubBatch struct {
    20  	Envelopes []proto.Message
    21  }
    22  
    23  // Serialize converts a PubSubBatch to a PubSubBatchTransport.
    24  func (b *PubSubBatch) Serialize() (remote.RootSerialized, error) {
    25  	batch := &PubSubBatchTransport{
    26  		TypeNames: make([]string, 0),
    27  		Envelopes: make([]*PubSubEnvelope, 0),
    28  	}
    29  
    30  	for _, envelope := range b.Envelopes {
    31  		var serializerId int32
    32  		messageData, typeName, err := remote.Serialize(envelope, serializerId)
    33  		if err != nil {
    34  			return nil, err
    35  		}
    36  		// batch.TypeNames.IndexOf(typeName)
    37  		typeIndex := -1
    38  		for i, t := range batch.TypeNames {
    39  			if t == typeName {
    40  				typeIndex = i
    41  				break
    42  			}
    43  		}
    44  		if typeIndex == -1 {
    45  			batch.TypeNames = append(batch.TypeNames, typeName)
    46  			typeIndex = len(batch.TypeNames) - 1
    47  		}
    48  		batch.Envelopes = append(batch.Envelopes, &PubSubEnvelope{
    49  			MessageData:  messageData,
    50  			TypeId:       int32(typeIndex),
    51  			SerializerId: serializerId,
    52  		})
    53  	}
    54  	return batch, nil
    55  }
    56  
    57  // Deserialize converts a PubSubBatchTransport to a PubSubBatch.
    58  func (t *PubSubBatchTransport) Deserialize() (remote.RootSerializable, error) {
    59  	b := &PubSubBatch{
    60  		Envelopes: make([]proto.Message, 0),
    61  	}
    62  
    63  	for _, envelope := range t.Envelopes {
    64  		message, err := remote.Deserialize(envelope.MessageData, t.TypeNames[envelope.TypeId], envelope.SerializerId)
    65  		if err != nil {
    66  			return nil, err
    67  		}
    68  		protoMessage, ok := message.(proto.Message)
    69  		if !ok {
    70  			panic("message is not proto.Message")
    71  		}
    72  
    73  		b.Envelopes = append(b.Envelopes, protoMessage)
    74  	}
    75  	return b, nil
    76  }
    77  
    78  type DeliverBatchRequest struct {
    79  	Subscribers *Subscribers
    80  	PubSubBatch *PubSubBatch
    81  	Topic       string
    82  }
    83  
    84  func (d *DeliverBatchRequest) Serialize() (remote.RootSerialized, error) {
    85  	rs, err := d.PubSubBatch.Serialize()
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	return &DeliverBatchRequestTransport{
    91  		Subscribers: d.Subscribers,
    92  		Batch:       rs.(*PubSubBatchTransport),
    93  		Topic:       d.Topic,
    94  	}, nil
    95  }
    96  
    97  func (t *DeliverBatchRequestTransport) Deserialize() (remote.RootSerializable, error) {
    98  	rs, err := t.Batch.Deserialize()
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  
   103  	return &DeliverBatchRequest{
   104  		Subscribers: t.Subscribers,
   105  		PubSubBatch: rs.(*PubSubBatch),
   106  		Topic:       t.Topic,
   107  	}, nil
   108  }
   109  
   110  var _ actor.MessageBatch = (*PubSubAutoRespondBatch)(nil)
   111  
   112  type PubSubAutoRespondBatch struct {
   113  	Envelopes []proto.Message
   114  }
   115  
   116  // Serialize converts a PubSubAutoRespondBatch to a PubSubAutoRespondBatchTransport.
   117  func (b *PubSubAutoRespondBatch) Serialize() (remote.RootSerialized, error) {
   118  	batch := &PubSubBatch{Envelopes: b.Envelopes}
   119  
   120  	rs, err := batch.Serialize()
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  
   125  	return &PubSubAutoRespondBatchTransport{
   126  		TypeNames: rs.(*PubSubBatchTransport).TypeNames,
   127  		Envelopes: rs.(*PubSubBatchTransport).Envelopes,
   128  	}, nil
   129  }
   130  
   131  // GetAutoResponse returns a PublishResponse.
   132  func (b *PubSubAutoRespondBatch) GetAutoResponse(_ actor.Context) interface{} {
   133  	return &PublishResponse{
   134  		Status: PublishStatus_Ok,
   135  	}
   136  }
   137  
   138  // GetMessages returns the message.
   139  func (b *PubSubAutoRespondBatch) GetMessages() []interface{} {
   140  	var messages []interface{}
   141  	for _, envelope := range b.Envelopes {
   142  		messages = append(messages, envelope)
   143  	}
   144  	return messages
   145  }
   146  
   147  // Deserialize converts a PubSubAutoRespondBatchTransport to a PubSubAutoRespondBatch.
   148  func (t *PubSubAutoRespondBatchTransport) Deserialize() (remote.RootSerializable, error) {
   149  	batch := &PubSubBatchTransport{
   150  		TypeNames: t.TypeNames,
   151  		Envelopes: t.Envelopes,
   152  	}
   153  	rs, err := batch.Deserialize()
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  
   158  	return &PubSubAutoRespondBatch{
   159  		Envelopes: rs.(*PubSubBatch).Envelopes,
   160  	}, nil
   161  }