github.com/nsqio/nsq@v1.3.0/nsqd/message.go (about)

     1  package nsqd
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"io"
     7  	"time"
     8  )
     9  
    10  const (
    11  	MsgIDLength       = 16
    12  	minValidMsgLength = MsgIDLength + 8 + 2 // Timestamp + Attempts
    13  )
    14  
    15  type MessageID [MsgIDLength]byte
    16  
    17  type Message struct {
    18  	ID        MessageID
    19  	Body      []byte
    20  	Timestamp int64
    21  	Attempts  uint16
    22  
    23  	// for in-flight handling
    24  	deliveryTS time.Time
    25  	clientID   int64
    26  	pri        int64
    27  	index      int
    28  	deferred   time.Duration
    29  }
    30  
    31  func NewMessage(id MessageID, body []byte) *Message {
    32  	return &Message{
    33  		ID:        id,
    34  		Body:      body,
    35  		Timestamp: time.Now().UnixNano(),
    36  	}
    37  }
    38  
    39  func (m *Message) WriteTo(w io.Writer) (int64, error) {
    40  	var buf [10]byte
    41  	var total int64
    42  
    43  	binary.BigEndian.PutUint64(buf[:8], uint64(m.Timestamp))
    44  	binary.BigEndian.PutUint16(buf[8:10], uint16(m.Attempts))
    45  
    46  	n, err := w.Write(buf[:])
    47  	total += int64(n)
    48  	if err != nil {
    49  		return total, err
    50  	}
    51  
    52  	n, err = w.Write(m.ID[:])
    53  	total += int64(n)
    54  	if err != nil {
    55  		return total, err
    56  	}
    57  
    58  	n, err = w.Write(m.Body)
    59  	total += int64(n)
    60  	if err != nil {
    61  		return total, err
    62  	}
    63  
    64  	return total, nil
    65  }
    66  
    67  // decodeMessage deserializes data (as []byte) and creates a new Message
    68  //
    69  //	[x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x]...
    70  //	|       (int64)        ||    ||      (hex string encoded in ASCII)           || (binary)
    71  //	|       8-byte         ||    ||                 16-byte                      || N-byte
    72  //	------------------------------------------------------------------------------------------...
    73  //	  nanosecond timestamp    ^^                   message ID                       message body
    74  //	                       (uint16)
    75  //	                        2-byte
    76  //	                       attempts
    77  func decodeMessage(b []byte) (*Message, error) {
    78  	var msg Message
    79  
    80  	if len(b) < minValidMsgLength {
    81  		return nil, fmt.Errorf("invalid message buffer size (%d)", len(b))
    82  	}
    83  
    84  	msg.Timestamp = int64(binary.BigEndian.Uint64(b[:8]))
    85  	msg.Attempts = binary.BigEndian.Uint16(b[8:10])
    86  	copy(msg.ID[:], b[10:10+MsgIDLength])
    87  	msg.Body = b[10+MsgIDLength:]
    88  
    89  	return &msg, nil
    90  }
    91  
    92  func writeMessageToBackend(msg *Message, bq BackendQueue) error {
    93  	buf := bufferPoolGet()
    94  	defer bufferPoolPut(buf)
    95  	_, err := msg.WriteTo(buf)
    96  	if err != nil {
    97  		return err
    98  	}
    99  	return bq.Put(buf.Bytes())
   100  }