123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854 |
- package sarama
- import (
- "log"
- "os"
- "os/signal"
- "sync"
- "testing"
- "time"
- )
- var testMsg = StringEncoder("Foo")
- func TestConsumerOffsetManual(t *testing.T) {
-
- broker0 := NewMockBroker(t, 0)
- mockFetchResponse := NewMockFetchResponse(t, 1)
- for i := 0; i < 10; i++ {
- mockFetchResponse.SetMessage("my_topic", 0, int64(i+1234), testMsg)
- }
- broker0.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetBroker(broker0.Addr(), broker0.BrokerID()).
- SetLeader("my_topic", 0, broker0.BrokerID()),
- "OffsetRequest": NewMockOffsetResponse(t).
- SetOffset("my_topic", 0, OffsetOldest, 0).
- SetOffset("my_topic", 0, OffsetNewest, 2345),
- "FetchRequest": mockFetchResponse,
- })
-
- master, err := NewConsumer([]string{broker0.Addr()}, nil)
- if err != nil {
- t.Fatal(err)
- }
- consumer, err := master.ConsumePartition("my_topic", 0, 1234)
- if err != nil {
- t.Fatal(err)
- }
-
- for i := 0; i < 10; i++ {
- select {
- case message := <-consumer.Messages():
- assertMessageOffset(t, message, int64(i+1234))
- case err := <-consumer.Errors():
- t.Error(err)
- }
- }
- safeClose(t, consumer)
- safeClose(t, master)
- broker0.Close()
- }
- func TestConsumerOffsetNewest(t *testing.T) {
-
- broker0 := NewMockBroker(t, 0)
- broker0.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetBroker(broker0.Addr(), broker0.BrokerID()).
- SetLeader("my_topic", 0, broker0.BrokerID()),
- "OffsetRequest": NewMockOffsetResponse(t).
- SetOffset("my_topic", 0, OffsetNewest, 10).
- SetOffset("my_topic", 0, OffsetOldest, 7),
- "FetchRequest": NewMockFetchResponse(t, 1).
- SetMessage("my_topic", 0, 9, testMsg).
- SetMessage("my_topic", 0, 10, testMsg).
- SetMessage("my_topic", 0, 11, testMsg).
- SetHighWaterMark("my_topic", 0, 14),
- })
- master, err := NewConsumer([]string{broker0.Addr()}, nil)
- if err != nil {
- t.Fatal(err)
- }
-
- consumer, err := master.ConsumePartition("my_topic", 0, OffsetNewest)
- if err != nil {
- t.Fatal(err)
- }
-
- assertMessageOffset(t, <-consumer.Messages(), 10)
- if hwmo := consumer.HighWaterMarkOffset(); hwmo != 14 {
- t.Errorf("Expected high water mark offset 14, found %d", hwmo)
- }
- safeClose(t, consumer)
- safeClose(t, master)
- broker0.Close()
- }
- func TestConsumerRecreate(t *testing.T) {
-
- broker0 := NewMockBroker(t, 0)
- broker0.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetBroker(broker0.Addr(), broker0.BrokerID()).
- SetLeader("my_topic", 0, broker0.BrokerID()),
- "OffsetRequest": NewMockOffsetResponse(t).
- SetOffset("my_topic", 0, OffsetOldest, 0).
- SetOffset("my_topic", 0, OffsetNewest, 1000),
- "FetchRequest": NewMockFetchResponse(t, 1).
- SetMessage("my_topic", 0, 10, testMsg),
- })
- c, err := NewConsumer([]string{broker0.Addr()}, nil)
- if err != nil {
- t.Fatal(err)
- }
- pc, err := c.ConsumePartition("my_topic", 0, 10)
- if err != nil {
- t.Fatal(err)
- }
- assertMessageOffset(t, <-pc.Messages(), 10)
-
- safeClose(t, pc)
- pc, err = c.ConsumePartition("my_topic", 0, 10)
- if err != nil {
- t.Fatal(err)
- }
-
- assertMessageOffset(t, <-pc.Messages(), 10)
- safeClose(t, pc)
- safeClose(t, c)
- broker0.Close()
- }
- func TestConsumerDuplicate(t *testing.T) {
-
- broker0 := NewMockBroker(t, 0)
- broker0.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetBroker(broker0.Addr(), broker0.BrokerID()).
- SetLeader("my_topic", 0, broker0.BrokerID()),
- "OffsetRequest": NewMockOffsetResponse(t).
- SetOffset("my_topic", 0, OffsetOldest, 0).
- SetOffset("my_topic", 0, OffsetNewest, 1000),
- "FetchRequest": NewMockFetchResponse(t, 1),
- })
- config := NewConfig()
- config.ChannelBufferSize = 0
- c, err := NewConsumer([]string{broker0.Addr()}, config)
- if err != nil {
- t.Fatal(err)
- }
- pc1, err := c.ConsumePartition("my_topic", 0, 0)
- if err != nil {
- t.Fatal(err)
- }
-
- pc2, err := c.ConsumePartition("my_topic", 0, 0)
-
- if pc2 != nil || err != ConfigurationError("That topic/partition is already being consumed") {
- t.Fatal("A partition cannot be consumed twice at the same time")
- }
- safeClose(t, pc1)
- safeClose(t, c)
- broker0.Close()
- }
- func TestConsumerLeaderRefreshError(t *testing.T) {
-
- broker0 := NewMockBroker(t, 100)
-
- Logger.Printf(" STAGE 1")
- broker0.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetBroker(broker0.Addr(), broker0.BrokerID()).
- SetLeader("my_topic", 0, broker0.BrokerID()),
- "OffsetRequest": NewMockOffsetResponse(t).
- SetOffset("my_topic", 0, OffsetOldest, 123).
- SetOffset("my_topic", 0, OffsetNewest, 1000),
- "FetchRequest": NewMockFetchResponse(t, 1).
- SetMessage("my_topic", 0, 123, testMsg),
- })
- config := NewConfig()
- config.Net.ReadTimeout = 100 * time.Millisecond
- config.Consumer.Retry.Backoff = 200 * time.Millisecond
- config.Consumer.Return.Errors = true
- config.Metadata.Retry.Max = 0
- c, err := NewConsumer([]string{broker0.Addr()}, config)
- if err != nil {
- t.Fatal(err)
- }
- pc, err := c.ConsumePartition("my_topic", 0, OffsetOldest)
- if err != nil {
- t.Fatal(err)
- }
- assertMessageOffset(t, <-pc.Messages(), 123)
-
-
- Logger.Printf(" STAGE 2")
- fetchResponse2 := &FetchResponse{}
- fetchResponse2.AddError("my_topic", 0, ErrNotLeaderForPartition)
- broker0.SetHandlerByMap(map[string]MockResponse{
- "FetchRequest": NewMockWrapper(fetchResponse2),
- })
- if consErr := <-pc.Errors(); consErr.Err != ErrOutOfBrokers {
- t.Errorf("Unexpected error: %v", consErr.Err)
- }
-
-
- Logger.Printf(" STAGE 3")
- broker1 := NewMockBroker(t, 101)
- broker1.SetHandlerByMap(map[string]MockResponse{
- "FetchRequest": NewMockFetchResponse(t, 1).
- SetMessage("my_topic", 0, 124, testMsg),
- })
- broker0.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetBroker(broker0.Addr(), broker0.BrokerID()).
- SetBroker(broker1.Addr(), broker1.BrokerID()).
- SetLeader("my_topic", 0, broker1.BrokerID()),
- })
- assertMessageOffset(t, <-pc.Messages(), 124)
- safeClose(t, pc)
- safeClose(t, c)
- broker1.Close()
- broker0.Close()
- }
- func TestConsumerInvalidTopic(t *testing.T) {
-
- broker0 := NewMockBroker(t, 100)
- broker0.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetBroker(broker0.Addr(), broker0.BrokerID()),
- })
- c, err := NewConsumer([]string{broker0.Addr()}, nil)
- if err != nil {
- t.Fatal(err)
- }
-
- pc, err := c.ConsumePartition("my_topic", 0, OffsetOldest)
-
- if pc != nil || err != ErrUnknownTopicOrPartition {
- t.Errorf("Should fail with, err=%v", err)
- }
- safeClose(t, c)
- broker0.Close()
- }
- func TestConsumerClosePartitionWithoutLeader(t *testing.T) {
-
- broker0 := NewMockBroker(t, 100)
- broker0.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetBroker(broker0.Addr(), broker0.BrokerID()).
- SetLeader("my_topic", 0, broker0.BrokerID()),
- "OffsetRequest": NewMockOffsetResponse(t).
- SetOffset("my_topic", 0, OffsetOldest, 123).
- SetOffset("my_topic", 0, OffsetNewest, 1000),
- "FetchRequest": NewMockFetchResponse(t, 1).
- SetMessage("my_topic", 0, 123, testMsg),
- })
- config := NewConfig()
- config.Net.ReadTimeout = 100 * time.Millisecond
- config.Consumer.Retry.Backoff = 100 * time.Millisecond
- config.Consumer.Return.Errors = true
- config.Metadata.Retry.Max = 0
- c, err := NewConsumer([]string{broker0.Addr()}, config)
- if err != nil {
- t.Fatal(err)
- }
- pc, err := c.ConsumePartition("my_topic", 0, OffsetOldest)
- if err != nil {
- t.Fatal(err)
- }
- assertMessageOffset(t, <-pc.Messages(), 123)
-
-
- fetchResponse2 := &FetchResponse{}
- fetchResponse2.AddError("my_topic", 0, ErrNotLeaderForPartition)
- broker0.SetHandlerByMap(map[string]MockResponse{
- "FetchRequest": NewMockWrapper(fetchResponse2),
- })
-
- if consErr := <-pc.Errors(); consErr.Err != ErrOutOfBrokers {
- t.Errorf("Unexpected error: %v", consErr.Err)
- }
-
- safeClose(t, pc)
- safeClose(t, c)
- broker0.Close()
- }
- func TestConsumerShutsDownOutOfRange(t *testing.T) {
-
- broker0 := NewMockBroker(t, 0)
- fetchResponse := new(FetchResponse)
- fetchResponse.AddError("my_topic", 0, ErrOffsetOutOfRange)
- broker0.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetBroker(broker0.Addr(), broker0.BrokerID()).
- SetLeader("my_topic", 0, broker0.BrokerID()),
- "OffsetRequest": NewMockOffsetResponse(t).
- SetOffset("my_topic", 0, OffsetNewest, 1234).
- SetOffset("my_topic", 0, OffsetOldest, 7),
- "FetchRequest": NewMockWrapper(fetchResponse),
- })
- master, err := NewConsumer([]string{broker0.Addr()}, nil)
- if err != nil {
- t.Fatal(err)
- }
-
- consumer, err := master.ConsumePartition("my_topic", 0, 101)
- if err != nil {
- t.Fatal(err)
- }
-
- if _, ok := <-consumer.Messages(); ok {
- t.Error("Expected the consumer to shut down")
- }
- safeClose(t, consumer)
- safeClose(t, master)
- broker0.Close()
- }
- func TestConsumerExtraOffsets(t *testing.T) {
-
- broker0 := NewMockBroker(t, 0)
- fetchResponse1 := &FetchResponse{}
- fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 1)
- fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 2)
- fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 3)
- fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 4)
- fetchResponse2 := &FetchResponse{}
- fetchResponse2.AddError("my_topic", 0, ErrNoError)
- broker0.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetBroker(broker0.Addr(), broker0.BrokerID()).
- SetLeader("my_topic", 0, broker0.BrokerID()),
- "OffsetRequest": NewMockOffsetResponse(t).
- SetOffset("my_topic", 0, OffsetNewest, 1234).
- SetOffset("my_topic", 0, OffsetOldest, 0),
- "FetchRequest": NewMockSequence(fetchResponse1, fetchResponse2),
- })
- master, err := NewConsumer([]string{broker0.Addr()}, nil)
- if err != nil {
- t.Fatal(err)
- }
-
- consumer, err := master.ConsumePartition("my_topic", 0, 3)
- if err != nil {
- t.Fatal(err)
- }
-
-
- assertMessageOffset(t, <-consumer.Messages(), 3)
- assertMessageOffset(t, <-consumer.Messages(), 4)
- safeClose(t, consumer)
- safeClose(t, master)
- broker0.Close()
- }
- func TestConsumerNonSequentialOffsets(t *testing.T) {
-
- broker0 := NewMockBroker(t, 0)
- fetchResponse1 := &FetchResponse{}
- fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 5)
- fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 7)
- fetchResponse1.AddMessage("my_topic", 0, nil, testMsg, 11)
- fetchResponse2 := &FetchResponse{}
- fetchResponse2.AddError("my_topic", 0, ErrNoError)
- broker0.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetBroker(broker0.Addr(), broker0.BrokerID()).
- SetLeader("my_topic", 0, broker0.BrokerID()),
- "OffsetRequest": NewMockOffsetResponse(t).
- SetOffset("my_topic", 0, OffsetNewest, 1234).
- SetOffset("my_topic", 0, OffsetOldest, 0),
- "FetchRequest": NewMockSequence(fetchResponse1, fetchResponse2),
- })
- master, err := NewConsumer([]string{broker0.Addr()}, nil)
- if err != nil {
- t.Fatal(err)
- }
-
- consumer, err := master.ConsumePartition("my_topic", 0, 3)
- if err != nil {
- t.Fatal(err)
- }
-
-
- assertMessageOffset(t, <-consumer.Messages(), 5)
- assertMessageOffset(t, <-consumer.Messages(), 7)
- assertMessageOffset(t, <-consumer.Messages(), 11)
- safeClose(t, consumer)
- safeClose(t, master)
- broker0.Close()
- }
- func TestConsumerRebalancingMultiplePartitions(t *testing.T) {
-
- seedBroker := NewMockBroker(t, 10)
- leader0 := NewMockBroker(t, 0)
- leader1 := NewMockBroker(t, 1)
- seedBroker.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetBroker(leader0.Addr(), leader0.BrokerID()).
- SetBroker(leader1.Addr(), leader1.BrokerID()).
- SetLeader("my_topic", 0, leader0.BrokerID()).
- SetLeader("my_topic", 1, leader1.BrokerID()),
- })
- mockOffsetResponse1 := NewMockOffsetResponse(t).
- SetOffset("my_topic", 0, OffsetOldest, 0).
- SetOffset("my_topic", 0, OffsetNewest, 1000).
- SetOffset("my_topic", 1, OffsetOldest, 0).
- SetOffset("my_topic", 1, OffsetNewest, 1000)
- leader0.SetHandlerByMap(map[string]MockResponse{
- "OffsetRequest": mockOffsetResponse1,
- "FetchRequest": NewMockFetchResponse(t, 1),
- })
- leader1.SetHandlerByMap(map[string]MockResponse{
- "OffsetRequest": mockOffsetResponse1,
- "FetchRequest": NewMockFetchResponse(t, 1),
- })
-
- config := NewConfig()
- config.Consumer.Retry.Backoff = 50
- master, err := NewConsumer([]string{seedBroker.Addr()}, config)
- if err != nil {
- t.Fatal(err)
- }
-
- var wg sync.WaitGroup
- for i := int32(0); i < 2; i++ {
- consumer, err := master.ConsumePartition("my_topic", i, 0)
- if err != nil {
- t.Error(err)
- }
- go func(c PartitionConsumer) {
- for err := range c.Errors() {
- t.Error(err)
- }
- }(consumer)
- wg.Add(1)
- go func(partition int32, c PartitionConsumer) {
- for i := 0; i < 10; i++ {
- message := <-consumer.Messages()
- if message.Offset != int64(i) {
- t.Error("Incorrect message offset!", i, partition, message.Offset)
- }
- if message.Partition != partition {
- t.Error("Incorrect message partition!")
- }
- }
- safeClose(t, consumer)
- wg.Done()
- }(i, consumer)
- }
- time.Sleep(50 * time.Millisecond)
- Logger.Printf(" STAGE 1")
-
-
-
- mockFetchResponse := NewMockFetchResponse(t, 1)
- for i := 0; i < 4; i++ {
- mockFetchResponse.SetMessage("my_topic", 0, int64(i), testMsg)
- }
- leader0.SetHandlerByMap(map[string]MockResponse{
- "FetchRequest": mockFetchResponse,
- })
- time.Sleep(50 * time.Millisecond)
- Logger.Printf(" STAGE 2")
-
-
-
-
- seedBroker.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetLeader("my_topic", 0, leader1.BrokerID()).
- SetLeader("my_topic", 1, leader1.BrokerID()),
- })
-
- fetchResponse := new(FetchResponse)
- fetchResponse.AddError("my_topic", 0, ErrNotLeaderForPartition)
- leader0.SetHandlerByMap(map[string]MockResponse{
- "FetchRequest": NewMockWrapper(fetchResponse),
- })
- time.Sleep(50 * time.Millisecond)
- Logger.Printf(" STAGE 3")
-
-
-
-
- mockFetchResponse2 := NewMockFetchResponse(t, 2)
- for i := 4; i < 7; i++ {
- mockFetchResponse2.SetMessage("my_topic", 0, int64(i), testMsg)
- }
- for i := 0; i < 8; i++ {
- mockFetchResponse2.SetMessage("my_topic", 1, int64(i), testMsg)
- }
- leader1.SetHandlerByMap(map[string]MockResponse{
- "FetchRequest": mockFetchResponse2,
- })
- time.Sleep(50 * time.Millisecond)
- Logger.Printf(" STAGE 4")
-
-
-
-
-
- seedBroker.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetLeader("my_topic", 0, leader1.BrokerID()).
- SetLeader("my_topic", 1, leader0.BrokerID()),
- })
-
- mockFetchResponse3 := NewMockFetchResponse(t, 3).
- SetMessage("my_topic", 0, int64(7), testMsg).
- SetMessage("my_topic", 0, int64(8), testMsg).
- SetMessage("my_topic", 0, int64(9), testMsg)
- fetchResponse4 := new(FetchResponse)
- fetchResponse4.AddError("my_topic", 1, ErrNotLeaderForPartition)
- leader1.SetHandlerByMap(map[string]MockResponse{
- "FetchRequest": NewMockSequence(mockFetchResponse3, fetchResponse4),
- })
-
- mockFetchResponse4 := NewMockFetchResponse(t, 2)
- for i := 8; i < 10; i++ {
- mockFetchResponse4.SetMessage("my_topic", 1, int64(i), testMsg)
- }
- leader0.SetHandlerByMap(map[string]MockResponse{
- "FetchRequest": mockFetchResponse4,
- })
- wg.Wait()
- safeClose(t, master)
- leader1.Close()
- leader0.Close()
- seedBroker.Close()
- }
- func TestConsumerInterleavedClose(t *testing.T) {
-
- broker0 := NewMockBroker(t, 0)
- broker0.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetBroker(broker0.Addr(), broker0.BrokerID()).
- SetLeader("my_topic", 0, broker0.BrokerID()).
- SetLeader("my_topic", 1, broker0.BrokerID()),
- "OffsetRequest": NewMockOffsetResponse(t).
- SetOffset("my_topic", 0, OffsetOldest, 1000).
- SetOffset("my_topic", 0, OffsetNewest, 1100).
- SetOffset("my_topic", 1, OffsetOldest, 2000).
- SetOffset("my_topic", 1, OffsetNewest, 2100),
- "FetchRequest": NewMockFetchResponse(t, 1).
- SetMessage("my_topic", 0, 1000, testMsg).
- SetMessage("my_topic", 0, 1001, testMsg).
- SetMessage("my_topic", 0, 1002, testMsg).
- SetMessage("my_topic", 1, 2000, testMsg),
- })
- config := NewConfig()
- config.ChannelBufferSize = 0
- master, err := NewConsumer([]string{broker0.Addr()}, config)
- if err != nil {
- t.Fatal(err)
- }
- c0, err := master.ConsumePartition("my_topic", 0, 1000)
- if err != nil {
- t.Fatal(err)
- }
- c1, err := master.ConsumePartition("my_topic", 1, 2000)
- if err != nil {
- t.Fatal(err)
- }
-
- assertMessageOffset(t, <-c0.Messages(), 1000)
- assertMessageOffset(t, <-c0.Messages(), 1001)
- assertMessageOffset(t, <-c0.Messages(), 1002)
- safeClose(t, c1)
- safeClose(t, c0)
- safeClose(t, master)
- broker0.Close()
- }
- func TestConsumerBounceWithReferenceOpen(t *testing.T) {
- broker0 := NewMockBroker(t, 0)
- broker0Addr := broker0.Addr()
- broker1 := NewMockBroker(t, 1)
- mockMetadataResponse := NewMockMetadataResponse(t).
- SetBroker(broker0.Addr(), broker0.BrokerID()).
- SetBroker(broker1.Addr(), broker1.BrokerID()).
- SetLeader("my_topic", 0, broker0.BrokerID()).
- SetLeader("my_topic", 1, broker1.BrokerID())
- mockOffsetResponse := NewMockOffsetResponse(t).
- SetOffset("my_topic", 0, OffsetOldest, 1000).
- SetOffset("my_topic", 0, OffsetNewest, 1100).
- SetOffset("my_topic", 1, OffsetOldest, 2000).
- SetOffset("my_topic", 1, OffsetNewest, 2100)
- mockFetchResponse := NewMockFetchResponse(t, 1)
- for i := 0; i < 10; i++ {
- mockFetchResponse.SetMessage("my_topic", 0, int64(1000+i), testMsg)
- mockFetchResponse.SetMessage("my_topic", 1, int64(2000+i), testMsg)
- }
- broker0.SetHandlerByMap(map[string]MockResponse{
- "OffsetRequest": mockOffsetResponse,
- "FetchRequest": mockFetchResponse,
- })
- broker1.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": mockMetadataResponse,
- "OffsetRequest": mockOffsetResponse,
- "FetchRequest": mockFetchResponse,
- })
- config := NewConfig()
- config.Consumer.Return.Errors = true
- config.Consumer.Retry.Backoff = 100 * time.Millisecond
- config.ChannelBufferSize = 1
- master, err := NewConsumer([]string{broker1.Addr()}, config)
- if err != nil {
- t.Fatal(err)
- }
- c0, err := master.ConsumePartition("my_topic", 0, 1000)
- if err != nil {
- t.Fatal(err)
- }
- c1, err := master.ConsumePartition("my_topic", 1, 2000)
- if err != nil {
- t.Fatal(err)
- }
-
-
- assertMessageOffset(t, <-c0.Messages(), 1000)
- assertMessageOffset(t, <-c1.Messages(), 2000)
-
-
-
- broker0.Close()
-
-
- for i := 1; i < 7; i++ {
- offset := (<-c1.Messages()).Offset
- if offset != int64(2000+i) {
- t.Errorf("Expected offset %d from consumer/partition/1", int64(2000+i))
- }
- }
-
- broker0 = NewMockBrokerAddr(t, 0, broker0Addr)
- broker0.SetHandlerByMap(map[string]MockResponse{
- "FetchRequest": mockFetchResponse,
- })
-
- for i := 7; i < 10; i++ {
- assertMessageOffset(t, <-c1.Messages(), int64(2000+i))
- }
- for i := 1; i < 10; i++ {
- assertMessageOffset(t, <-c0.Messages(), int64(1000+i))
- }
- select {
- case <-c0.Errors():
- default:
- t.Errorf("Partition consumer should have detected broker restart")
- }
- safeClose(t, c1)
- safeClose(t, c0)
- safeClose(t, master)
- broker0.Close()
- broker1.Close()
- }
- func TestConsumerOffsetOutOfRange(t *testing.T) {
-
- broker0 := NewMockBroker(t, 2)
- broker0.SetHandlerByMap(map[string]MockResponse{
- "MetadataRequest": NewMockMetadataResponse(t).
- SetBroker(broker0.Addr(), broker0.BrokerID()).
- SetLeader("my_topic", 0, broker0.BrokerID()),
- "OffsetRequest": NewMockOffsetResponse(t).
- SetOffset("my_topic", 0, OffsetNewest, 1234).
- SetOffset("my_topic", 0, OffsetOldest, 2345),
- })
- master, err := NewConsumer([]string{broker0.Addr()}, nil)
- if err != nil {
- t.Fatal(err)
- }
-
- if _, err := master.ConsumePartition("my_topic", 0, 0); err != ErrOffsetOutOfRange {
- t.Fatal("Should return ErrOffsetOutOfRange, got:", err)
- }
- if _, err := master.ConsumePartition("my_topic", 0, 3456); err != ErrOffsetOutOfRange {
- t.Fatal("Should return ErrOffsetOutOfRange, got:", err)
- }
- if _, err := master.ConsumePartition("my_topic", 0, -3); err != ErrOffsetOutOfRange {
- t.Fatal("Should return ErrOffsetOutOfRange, got:", err)
- }
- safeClose(t, master)
- broker0.Close()
- }
- func assertMessageOffset(t *testing.T, msg *ConsumerMessage, expectedOffset int64) {
- if msg.Offset != expectedOffset {
- t.Errorf("Incorrect message offset: expected=%d, actual=%d", expectedOffset, msg.Offset)
- }
- }
- func ExampleConsumer() {
- consumer, err := NewConsumer([]string{"localhost:9092"}, nil)
- if err != nil {
- panic(err)
- }
- defer func() {
- if err := consumer.Close(); err != nil {
- log.Fatalln(err)
- }
- }()
- partitionConsumer, err := consumer.ConsumePartition("my_topic", 0, OffsetNewest)
- if err != nil {
- panic(err)
- }
- defer func() {
- if err := partitionConsumer.Close(); err != nil {
- log.Fatalln(err)
- }
- }()
-
- signals := make(chan os.Signal, 1)
- signal.Notify(signals, os.Interrupt)
- consumed := 0
- ConsumerLoop:
- for {
- select {
- case msg := <-partitionConsumer.Messages():
- log.Printf("Consumed message offset %d\n", msg.Offset)
- consumed++
- case <-signals:
- break ConsumerLoop
- }
- }
- log.Printf("Consumed: %d\n", consumed)
- }
|