private IEnumerable <FetchResponse> DecodeFetchResponse(byte[] data) { var stream = new ReadByteStream(data); var correlationId = stream.ReadInt(); var topicCount = stream.ReadInt(); for (int i = 0; i < topicCount; i++) { var topic = stream.ReadInt16String(); var partitionCount = stream.ReadInt(); for (int j = 0; j < partitionCount; j++) { var partitionId = stream.ReadInt(); var response = new FetchResponse { Topic = topic, PartitionId = partitionId, Error = stream.ReadInt16(), HighWaterMark = stream.ReadLong() }; //note: dont use initializer here as it breaks stream position. response.Messages = Message.DecodeMessageSet(stream.ReadIntPrefixedBytes()) .Select(x => { x.Meta.PartitionId = partitionId; return(x); }); yield return(response); } } }
/// <summary> /// Decode messages from a payload and assign it a given kafka offset. /// </summary> /// <param name="offset">The offset represting the log entry from kafka of this message.</param> /// <param name="payload">The byte[] encode as a message from kafka.</param> /// <returns>Enumerable representing stream of messages decoded from byte[].</returns> /// <remarks>The return type is an Enumerable as the message could be a compressed message set.</remarks> public static IEnumerable <Message> DecodeMessage(long offset, byte[] payload) { var crc = payload.Take(4).ToArray(); var stream = new ReadByteStream(payload.Skip(4)); var hash = Crc32Provider.ComputeHash(stream.Payload); if (crc.SequenceEqual(hash) == false) { throw new FailCrcCheckException("Payload did not match CRC validation."); } var message = new Message { Meta = new MessageMetadata { Offset = offset }, MagicNumber = stream.ReadByte(), Attribute = stream.ReadByte(), Key = stream.ReadIntPrefixedBytes() }; var codec = (MessageCodec)(ProtocolConstants.AttributeCodeMask & message.Attribute); switch (codec) { case MessageCodec.CodecNone: message.Value = stream.ReadIntPrefixedBytes(); yield return(message); break; case MessageCodec.CodecGzip: var gZipData = stream.ReadIntPrefixedBytes(); foreach (var m in DecodeMessageSet(Compression.Unzip(gZipData))) { yield return(m); } break; default: throw new NotSupportedException(string.Format("Codec type of {0} is not supported.", codec)); } }
/// <summary> /// Decode a byte[] that represents a collection of messages. /// </summary> /// <param name="messageSet">The byte[] encode as a message set from kafka.</param> /// <returns>Enumerable representing stream of messages decoded from byte[]</returns> public static IEnumerable <Message> DecodeMessageSet(byte[] messageSet) { var stream = new ReadByteStream(messageSet); while (stream.HasData) { var offset = stream.ReadLong(); foreach (var message in DecodeMessage(offset, stream.ReadIntPrefixedBytes())) { yield return(message); } } }