func BenchmarkPublishSpeedViaChan(b *testing.B) { b.StopTimer() s := RunDefaultServer() defer s.Shutdown() nc, err := nats.Connect(nats.DefaultURL) if err != nil { b.Fatalf("Could not connect: %v\n", err) } ec, err := nats.NewEncodedConn(nc, nats.DEFAULT_ENCODER) defer ec.Close() ch := make(chan int32, 1024) if err := ec.BindSendChan("foo", ch); err != nil { b.Fatalf("Failed to bind to a send channel: %v\n", err) } b.StartTimer() num := int32(22) for i := 0; i < b.N; i++ { ch <- num } // Make sure they are all processed. nc.Flush() b.StopTimer() }
func NewEConn(t tLogger) *nats.EncodedConn { ec, err := nats.NewEncodedConn(NewDefaultConnection(t), nats.DEFAULT_ENCODER) if err != nil { t.Fatalf("Failed to create an encoded connection: %v\n", err) } return ec }
func TestBasicReconnectFunctionality(t *testing.T) { ts := startReconnectServer(t) ch := make(chan bool) opts := reconnectOpts nc, _ := opts.Connect() ec, err := nats.NewEncodedConn(nc, nats.DEFAULT_ENCODER) if err != nil { t.Fatalf("Failed to create an encoded connection: %v\n", err) } testString := "bar" ec.Subscribe("foo", func(s string) { if s != testString { t.Fatal("String doesn't match") } ch <- true }) ec.Flush() ts.Shutdown() // server is stopped here... dch := make(chan bool) opts.DisconnectedCB = func(_ *nats.Conn) { dch <- true } Wait(dch) if err := ec.Publish("foo", testString); err != nil { t.Fatalf("Failed to publish message: %v\n", err) } ts = startReconnectServer(t) defer ts.Shutdown() if err := ec.FlushTimeout(5 * time.Second); err != nil { t.Fatalf("Error on Flush: %v", err) } if e := Wait(ch); e != nil { t.Fatal("Did not receive our message") } expectedReconnectCount := uint64(1) if ec.Conn.Reconnects != expectedReconnectCount { t.Fatalf("Reconnect count incorrect: %d vs %d\n", ec.Conn.Reconnects, expectedReconnectCount) } nc.Close() }
func TestQueueSubsOnReconnect(t *testing.T) { ts := startReconnectServer(t) opts := reconnectOpts // Allow us to block on reconnect complete. reconnectsDone := make(chan bool) opts.ReconnectedCB = func(nc *nats.Conn) { reconnectsDone <- true } // Helper to wait on a reconnect. waitOnReconnect := func() { select { case <-reconnectsDone: break case <-time.After(2 * time.Second): t.Fatalf("Expected a reconnect, timedout!\n") } } // Create connection nc, _ := opts.Connect() ec, err := nats.NewEncodedConn(nc, nats.JSON_ENCODER) if err != nil { t.Fatalf("Failed to create an encoded connection: %v\n", err) } // To hold results. results := make(map[int]int) var mu sync.Mutex // Make sure we got what we needed, 1 msg only and all seqnos accounted for.. checkResults := func(numSent int) { mu.Lock() defer mu.Unlock() for i := 0; i < numSent; i++ { if results[i] != 1 { t.Fatalf("Received incorrect number of messages, [%d] for seq: %d\n", results[i], i) } } // Auto reset results map results = make(map[int]int) } subj := "foo.bar" qgroup := "workers" cb := func(seqno int) { mu.Lock() defer mu.Unlock() results[seqno] = results[seqno] + 1 } // Create Queue Subscribers ec.QueueSubscribe(subj, qgroup, cb) ec.QueueSubscribe(subj, qgroup, cb) ec.Flush() // Helper function to send messages and check results. sendAndCheckMsgs := func(numToSend int) { for i := 0; i < numToSend; i++ { ec.Publish(subj, i) } // Wait for processing. ec.Flush() time.Sleep(50 * time.Millisecond) // Check Results checkResults(numToSend) } // Base Test sendAndCheckMsgs(10) // Stop and restart server ts.Shutdown() ts = startReconnectServer(t) defer ts.Shutdown() waitOnReconnect() // Reconnect Base Test sendAndCheckMsgs(10) }
func TestExtendedReconnectFunctionality(t *testing.T) { ts := startReconnectServer(t) opts := reconnectOpts dch := make(chan bool) opts.DisconnectedCB = func(_ *nats.Conn) { dch <- true } rch := make(chan bool) opts.ReconnectedCB = func(_ *nats.Conn) { rch <- true } nc, err := opts.Connect() if err != nil { t.Fatalf("Should have connected ok: %v", err) } ec, err := nats.NewEncodedConn(nc, nats.DEFAULT_ENCODER) if err != nil { t.Fatalf("Failed to create an encoded connection: %v\n", err) } testString := "bar" received := int32(0) ec.Subscribe("foo", func(s string) { atomic.AddInt32(&received, 1) }) sub, _ := ec.Subscribe("foobar", func(s string) { atomic.AddInt32(&received, 1) }) ec.Publish("foo", testString) ec.Flush() ts.Shutdown() // server is stopped here.. // wait for disconnect if e := WaitTime(dch, 2*time.Second); e != nil { t.Fatal("Did not receive a disconnect callback message") } // Sub while disconnected ec.Subscribe("bar", func(s string) { atomic.AddInt32(&received, 1) }) // Unsub foobar while disconnected sub.Unsubscribe() if err = ec.Publish("foo", testString); err != nil { t.Fatalf("Received an error after disconnect: %v\n", err) } if err = ec.Publish("bar", testString); err != nil { t.Fatalf("Received an error after disconnect: %v\n", err) } ts = startReconnectServer(t) defer ts.Shutdown() // server is restarted here.. // wait for reconnect if e := WaitTime(rch, 2*time.Second); e != nil { t.Fatal("Did not receive a reconnect callback message") } if err = ec.Publish("foobar", testString); err != nil { t.Fatalf("Received an error after server restarted: %v\n", err) } if err = ec.Publish("foo", testString); err != nil { t.Fatalf("Received an error after server restarted: %v\n", err) } ch := make(chan bool) ec.Subscribe("done", func(b bool) { ch <- true }) ec.Publish("done", true) if e := Wait(ch); e != nil { t.Fatal("Did not receive our message") } // Sleep a bit to guarantee scheduler runs and process all subs. time.Sleep(50 * time.Millisecond) if atomic.LoadInt32(&received) != 4 { t.Fatalf("Received != %d, equals %d\n", 4, received) } }