// Produce is settings messages Crc and Offset attributes and pushing all // passed arguments to broker. Produce call is blocking until pushed message // will be read with broker's ReadProduces. func (p *Producer) Produce(topic string, partition int32, messages ...*proto.Message) (int64, error) { if p.ResponseError != nil { return 0, p.ResponseError } off := p.ResponseOffset for i, msg := range messages { msg.Offset = off + int64(i) msg.Crc = proto.ComputeCrc(msg) } p.Broker.produced <- &ProducedMessages{ Topic: topic, Partition: partition, Messages: messages, } p.ResponseOffset += int64(len(messages)) return off, nil }
func TestProducer(t *testing.T) { srv := NewServer() srv.Start() defer srv.Close() srv.Handle(MetadataRequest, NewMetadataHandler(srv, false).Handler()) broker, err := Dial([]string{srv.Address()}, newTestBrokerConf("tester")) if err != nil { t.Fatalf("cannot create broker: %s", err) } prodConf := NewProducerConf() prodConf.RetryWait = time.Millisecond producer := broker.Producer(prodConf) messages := []*proto.Message{ {Value: []byte("first")}, {Value: []byte("second")}, } _, err = producer.Produce("does-not-exist", 42142, messages...) if err != proto.ErrUnknownTopicOrPartition { t.Fatalf("expected '%s', got %s", proto.ErrUnknownTopicOrPartition, err) } var handleErr error var createdMsgs int srv.Handle(ProduceRequest, func(request Serializable) Serializable { req := request.(*proto.ProduceReq) if req.Topics[0].Name != "test" { handleErr = fmt.Errorf("expected 'test' topic, got %s", req.Topics[0].Name) return nil } if req.Topics[0].Partitions[0].ID != 0 { handleErr = fmt.Errorf("expected 0 partition, got %d", req.Topics[0].Partitions[0].ID) return nil } messages := req.Topics[0].Partitions[0].Messages for _, msg := range messages { createdMsgs++ crc := proto.ComputeCrc(msg, proto.CompressionNone) if msg.Crc != crc { handleErr = fmt.Errorf("expected '%d' crc, got %d", crc, msg.Crc) return nil } } return &proto.ProduceResp{ CorrelationID: req.CorrelationID, Topics: []proto.ProduceRespTopic{ { Name: "test", Partitions: []proto.ProduceRespPartition{ { ID: 0, Offset: 5, }, }, }, }, } }) offset, err := producer.Produce("test", 0, messages...) if handleErr != nil { t.Fatalf("handling error: %s", handleErr) } if err != nil { t.Fatalf("expected no error, got %s", err) } if offset != 5 { t.Fatalf("expected offset different than %d", offset) } if messages[0].Offset != 5 || messages[1].Offset != 6 { t.Fatalf("message offset is incorrect: %#v", messages) } if createdMsgs != 2 { t.Fatalf("expected 2 messages to be created, got %d", createdMsgs) } broker.Close() }
func TestConnectionFetch(t *testing.T) { messages := []*proto.Message{ {Offset: 4, Key: []byte("f"), Value: []byte("first")}, {Offset: 5, Key: []byte("s"), Value: []byte("second")}, {Offset: 6, Key: []byte("t"), Value: []byte("third")}, } for _, m := range messages { m.Crc = proto.ComputeCrc(m, proto.CompressionNone) } resp1 := &proto.FetchResp{ CorrelationID: 1, Topics: []proto.FetchRespTopic{ { Name: "foo", Partitions: []proto.FetchRespPartition{ { ID: 1, Err: nil, TipOffset: 20, Messages: messages, }, }, }, { Name: "bar", Partitions: []proto.FetchRespPartition{ { ID: 6, Err: proto.ErrUnknownTopicOrPartition, TipOffset: -1, Messages: []*proto.Message{}, }, }, }, }, } ln, err := testServer(resp1) if err != nil { t.Fatalf("test server error: %s", err) } conn, err := newTCPConnection(ln.Addr().String(), time.Second) if err != nil { t.Fatalf("could not conect to test server: %s", err) } resp, err := conn.Fetch(&proto.FetchReq{ CorrelationID: 1, ClientID: "tester", Topics: []proto.FetchReqTopic{ { Name: "foo", Partitions: []proto.FetchReqPartition{ { ID: 1, FetchOffset: 5, }, }, }, { Name: "bar", Partitions: []proto.FetchReqPartition{ { ID: 6, }, }, }, }, }) if err != nil { t.Fatalf("could not fetch response: %s", err) } // before comparison, set attributes as we expect deserializer to do for _, m := range messages { m.Topic = "foo" m.Partition = 1 } // offset 5 was requested; first message should be trimmed resp1.Topics[0].Partitions[0].Messages = messages[1:] if !reflect.DeepEqual(resp, resp1) { t.Fatalf("expected different response %#v", resp) } }