github.com/nsqio/nsq@v1.3.0/nsqd/channel_test.go (about) 1 package nsqd 2 3 import ( 4 "fmt" 5 "io" 6 "net/http" 7 "os" 8 "strconv" 9 "testing" 10 "time" 11 12 "github.com/nsqio/nsq/internal/test" 13 ) 14 15 // ensure that we can push a message through a topic and get it out of a channel 16 func TestPutMessage(t *testing.T) { 17 opts := NewOptions() 18 opts.Logger = test.NewTestLogger(t) 19 _, _, nsqd := mustStartNSQD(opts) 20 defer os.RemoveAll(opts.DataPath) 21 defer nsqd.Exit() 22 23 topicName := "test_put_message" + strconv.Itoa(int(time.Now().Unix())) 24 topic := nsqd.GetTopic(topicName) 25 channel1 := topic.GetChannel("ch") 26 27 var id MessageID 28 msg := NewMessage(id, []byte("test")) 29 topic.PutMessage(msg) 30 31 outputMsg := <-channel1.memoryMsgChan 32 test.Equal(t, msg.ID, outputMsg.ID) 33 test.Equal(t, msg.Body, outputMsg.Body) 34 } 35 36 // ensure that both channels get the same message 37 func TestPutMessage2Chan(t *testing.T) { 38 opts := NewOptions() 39 opts.Logger = test.NewTestLogger(t) 40 _, _, nsqd := mustStartNSQD(opts) 41 defer os.RemoveAll(opts.DataPath) 42 defer nsqd.Exit() 43 44 topicName := "test_put_message_2chan" + strconv.Itoa(int(time.Now().Unix())) 45 topic := nsqd.GetTopic(topicName) 46 channel1 := topic.GetChannel("ch1") 47 channel2 := topic.GetChannel("ch2") 48 49 var id MessageID 50 msg := NewMessage(id, []byte("test")) 51 topic.PutMessage(msg) 52 53 outputMsg1 := <-channel1.memoryMsgChan 54 test.Equal(t, msg.ID, outputMsg1.ID) 55 test.Equal(t, msg.Body, outputMsg1.Body) 56 57 outputMsg2 := <-channel2.memoryMsgChan 58 test.Equal(t, msg.ID, outputMsg2.ID) 59 test.Equal(t, msg.Body, outputMsg2.Body) 60 } 61 62 func TestInFlightWorker(t *testing.T) { 63 count := 250 64 65 opts := NewOptions() 66 opts.Logger = test.NewTestLogger(t) 67 opts.MsgTimeout = 100 * time.Millisecond 68 opts.QueueScanRefreshInterval = 100 * time.Millisecond 69 _, _, nsqd := mustStartNSQD(opts) 70 defer os.RemoveAll(opts.DataPath) 71 defer nsqd.Exit() 72 73 topicName := "test_in_flight_worker" + strconv.Itoa(int(time.Now().Unix())) 74 topic := nsqd.GetTopic(topicName) 75 channel := topic.GetChannel("channel") 76 77 for i := 0; i < count; i++ { 78 msg := NewMessage(topic.GenerateID(), []byte("test")) 79 channel.StartInFlightTimeout(msg, 0, opts.MsgTimeout) 80 } 81 82 channel.Lock() 83 inFlightMsgs := len(channel.inFlightMessages) 84 channel.Unlock() 85 test.Equal(t, count, inFlightMsgs) 86 87 channel.inFlightMutex.Lock() 88 inFlightPQMsgs := len(channel.inFlightPQ) 89 channel.inFlightMutex.Unlock() 90 test.Equal(t, count, inFlightPQMsgs) 91 92 // the in flight worker has a resolution of 100ms so we need to wait 93 // at least that much longer than our msgTimeout (in worst case) 94 time.Sleep(4 * opts.MsgTimeout) 95 96 channel.Lock() 97 inFlightMsgs = len(channel.inFlightMessages) 98 channel.Unlock() 99 test.Equal(t, 0, inFlightMsgs) 100 101 channel.inFlightMutex.Lock() 102 inFlightPQMsgs = len(channel.inFlightPQ) 103 channel.inFlightMutex.Unlock() 104 test.Equal(t, 0, inFlightPQMsgs) 105 } 106 107 func TestChannelEmpty(t *testing.T) { 108 opts := NewOptions() 109 opts.Logger = test.NewTestLogger(t) 110 _, _, nsqd := mustStartNSQD(opts) 111 defer os.RemoveAll(opts.DataPath) 112 defer nsqd.Exit() 113 114 topicName := "test_channel_empty" + strconv.Itoa(int(time.Now().Unix())) 115 topic := nsqd.GetTopic(topicName) 116 channel := topic.GetChannel("channel") 117 118 msgs := make([]*Message, 0, 25) 119 for i := 0; i < 25; i++ { 120 msg := NewMessage(topic.GenerateID(), []byte("test")) 121 channel.StartInFlightTimeout(msg, 0, opts.MsgTimeout) 122 msgs = append(msgs, msg) 123 } 124 125 channel.RequeueMessage(0, msgs[len(msgs)-1].ID, 100*time.Millisecond) 126 test.Equal(t, 24, len(channel.inFlightMessages)) 127 test.Equal(t, 24, len(channel.inFlightPQ)) 128 test.Equal(t, 1, len(channel.deferredMessages)) 129 test.Equal(t, 1, len(channel.deferredPQ)) 130 131 channel.Empty() 132 133 test.Equal(t, 0, len(channel.inFlightMessages)) 134 test.Equal(t, 0, len(channel.inFlightPQ)) 135 test.Equal(t, 0, len(channel.deferredMessages)) 136 test.Equal(t, 0, len(channel.deferredPQ)) 137 test.Equal(t, int64(0), channel.Depth()) 138 } 139 140 func TestChannelEmptyConsumer(t *testing.T) { 141 opts := NewOptions() 142 opts.Logger = test.NewTestLogger(t) 143 tcpAddr, _, nsqd := mustStartNSQD(opts) 144 defer os.RemoveAll(opts.DataPath) 145 defer nsqd.Exit() 146 147 conn, _ := mustConnectNSQD(tcpAddr) 148 defer conn.Close() 149 150 topicName := "test_channel_empty" + strconv.Itoa(int(time.Now().Unix())) 151 topic := nsqd.GetTopic(topicName) 152 channel := topic.GetChannel("channel") 153 client := newClientV2(0, conn, nsqd) 154 client.SetReadyCount(25) 155 err := channel.AddClient(client.ID, client) 156 test.Equal(t, err, nil) 157 158 for i := 0; i < 25; i++ { 159 msg := NewMessage(topic.GenerateID(), []byte("test")) 160 channel.StartInFlightTimeout(msg, 0, opts.MsgTimeout) 161 client.SendingMessage() 162 } 163 164 for _, cl := range channel.clients { 165 stats := cl.Stats("").(ClientV2Stats) 166 test.Equal(t, int64(25), stats.InFlightCount) 167 } 168 169 channel.Empty() 170 171 for _, cl := range channel.clients { 172 stats := cl.Stats("").(ClientV2Stats) 173 test.Equal(t, int64(0), stats.InFlightCount) 174 } 175 } 176 177 func TestMaxChannelConsumers(t *testing.T) { 178 opts := NewOptions() 179 opts.Logger = test.NewTestLogger(t) 180 opts.MaxChannelConsumers = 1 181 tcpAddr, _, nsqd := mustStartNSQD(opts) 182 defer os.RemoveAll(opts.DataPath) 183 defer nsqd.Exit() 184 185 conn, _ := mustConnectNSQD(tcpAddr) 186 defer conn.Close() 187 188 topicName := "test_max_channel_consumers" + strconv.Itoa(int(time.Now().Unix())) 189 topic := nsqd.GetTopic(topicName) 190 channel := topic.GetChannel("channel") 191 192 client1 := newClientV2(1, conn, nsqd) 193 client1.SetReadyCount(25) 194 err := channel.AddClient(client1.ID, client1) 195 test.Equal(t, err, nil) 196 197 client2 := newClientV2(2, conn, nsqd) 198 client2.SetReadyCount(25) 199 err = channel.AddClient(client2.ID, client2) 200 test.NotEqual(t, err, nil) 201 } 202 203 func TestChannelHealth(t *testing.T) { 204 opts := NewOptions() 205 opts.Logger = test.NewTestLogger(t) 206 opts.MemQueueSize = 2 207 208 _, httpAddr, nsqd := mustStartNSQD(opts) 209 defer os.RemoveAll(opts.DataPath) 210 defer nsqd.Exit() 211 212 topic := nsqd.GetTopic("test") 213 214 channel := topic.GetChannel("channel") 215 216 channel.backend = &errorBackendQueue{} 217 218 msg := NewMessage(topic.GenerateID(), make([]byte, 100)) 219 err := channel.PutMessage(msg) 220 test.Nil(t, err) 221 222 msg = NewMessage(topic.GenerateID(), make([]byte, 100)) 223 err = channel.PutMessage(msg) 224 test.Nil(t, err) 225 226 msg = NewMessage(topic.GenerateID(), make([]byte, 100)) 227 err = channel.PutMessage(msg) 228 test.NotNil(t, err) 229 230 url := fmt.Sprintf("http://%s/ping", httpAddr) 231 resp, err := http.Get(url) 232 test.Nil(t, err) 233 test.Equal(t, 500, resp.StatusCode) 234 body, _ := io.ReadAll(resp.Body) 235 resp.Body.Close() 236 test.Equal(t, "NOK - never gonna happen", string(body)) 237 238 channel.backend = &errorRecoveredBackendQueue{} 239 240 msg = NewMessage(topic.GenerateID(), make([]byte, 100)) 241 err = channel.PutMessage(msg) 242 test.Nil(t, err) 243 244 resp, err = http.Get(url) 245 test.Nil(t, err) 246 test.Equal(t, 200, resp.StatusCode) 247 body, _ = io.ReadAll(resp.Body) 248 resp.Body.Close() 249 test.Equal(t, "OK", string(body)) 250 }