func (fm *FileMgr) setupNatsOptions() { if !fm.certs.skipTLS { err := fm.certs.certLoad() if err != nil { panic(err) } } o := []nats.Option{} o = append(o, nats.MaxReconnects(-1)) // -1 => keep trying forever o = append(o, nats.ReconnectWait(2*time.Second)) o = append(o, nats.Name("archiver")) o = append(o, nats.ErrorHandler(func(c *nats.Conn, s *nats.Subscription, e error) { fm.NatsAsyncErrCh <- asyncErr{conn: c, sub: s, err: e} })) o = append(o, nats.DisconnectHandler(func(conn *nats.Conn) { fm.NatsConnDisconCh <- conn })) o = append(o, nats.ReconnectHandler(func(conn *nats.Conn) { fm.NatsConnReconCh <- conn })) o = append(o, nats.ClosedHandler(func(conn *nats.Conn) { fm.NatsConnClosedCh <- conn })) if !fm.certs.skipTLS { o = append(o, nats.Secure(&fm.certs.tlsConfig)) o = append(o, fm.certs.rootCA) } fm.opts = o }
func TestBasicClusterReconnect(t *testing.T) { s1 := RunServerOnPort(1222) defer s1.Shutdown() s2 := RunServerOnPort(1224) defer s2.Shutdown() dch := make(chan bool) rch := make(chan bool) opts := []nats.Option{nats.DontRandomize(), nats.DisconnectHandler(func(nc *nats.Conn) { // Suppress any additional callbacks nc.SetDisconnectHandler(nil) dch <- true }), nats.ReconnectHandler(func(_ *nats.Conn) { rch <- true }), } nc, err := nats.Connect(servers, opts...) if err != nil { t.Fatalf("Expected to connect, got err: %v\n", err) } defer nc.Close() s1.Shutdown() // wait for disconnect if e := WaitTime(dch, 2*time.Second); e != nil { t.Fatal("Did not receive a disconnect callback message") } reconnectTimeStart := time.Now() // wait for reconnect if e := WaitTime(rch, 2*time.Second); e != nil { t.Fatal("Did not receive a reconnect callback message") } if nc.ConnectedUrl() != testServers[2] { t.Fatalf("Does not report correct connection: %s\n", nc.ConnectedUrl()) } // Make sure we did not wait on reconnect for default time. // Reconnect should be fast since it will be a switch to the // second server and not be dependent on server restart time. reconnectTime := time.Since(reconnectTimeStart) if reconnectTime > (100 * time.Millisecond) { t.Fatalf("Took longer than expected to reconnect: %v\n", reconnectTime) } }
func TestProperReconnectDelay(t *testing.T) { s1 := RunServerOnPort(1222) defer s1.Shutdown() opts := nats.DefaultOptions opts.Servers = testServers opts.NoRandomize = true dcbCalled := false closedCbCalled := false dch := make(chan bool) dcb := func(nc *nats.Conn) { // Suppress any additional calls nc.SetDisconnectHandler(nil) dcbCalled = true dch <- true } ccb := func(_ *nats.Conn) { closedCbCalled = true } nc, err := nats.Connect(servers, nats.DontRandomize(), nats.DisconnectHandler(dcb), nats.ClosedHandler(ccb)) if err != nil { t.Fatalf("Expected to connect, got err: %v\n", err) } defer nc.Close() s1.Shutdown() // wait for disconnect if e := WaitTime(dch, 2*time.Second); e != nil { t.Fatal("Did not receive a disconnect callback message") } // Wait, want to make sure we don't spin on reconnect to non-existant servers. time.Sleep(1 * time.Second) // Make sure we are still reconnecting.. if closedCbCalled { t.Fatal("Closed CB was triggered, should not have been.") } if status := nc.Status(); status != nats.RECONNECTING { t.Fatalf("Wrong status: %d\n", status) } }
func TestCallbacksOrder(t *testing.T) { authS, authSOpts := RunServerWithConfig("./configs/tls.conf") defer authS.Shutdown() s := RunDefaultServer() defer s.Shutdown() firstDisconnect := true dtime1 := time.Time{} dtime2 := time.Time{} rtime := time.Time{} atime1 := time.Time{} atime2 := time.Time{} ctime := time.Time{} cbErrors := make(chan error, 20) reconnected := make(chan bool) closed := make(chan bool) asyncErr := make(chan bool, 2) recvCh := make(chan bool, 2) recvCh1 := make(chan bool) recvCh2 := make(chan bool) dch := func(nc *nats.Conn) { if err := isRunningInAsyncCBDispatcher(); err != nil { cbErrors <- err return } time.Sleep(100 * time.Millisecond) if firstDisconnect { firstDisconnect = false dtime1 = time.Now() } else { dtime2 = time.Now() } } rch := func(nc *nats.Conn) { if err := isRunningInAsyncCBDispatcher(); err != nil { cbErrors <- err reconnected <- true return } time.Sleep(50 * time.Millisecond) rtime = time.Now() reconnected <- true } ech := func(nc *nats.Conn, sub *nats.Subscription, err error) { if err := isRunningInAsyncCBDispatcher(); err != nil { cbErrors <- err asyncErr <- true return } if sub.Subject == "foo" { time.Sleep(20 * time.Millisecond) atime1 = time.Now() } else { atime2 = time.Now() } asyncErr <- true } cch := func(nc *nats.Conn) { if err := isRunningInAsyncCBDispatcher(); err != nil { cbErrors <- err closed <- true return } ctime = time.Now() closed <- true } url := net.JoinHostPort(authSOpts.Host, strconv.Itoa(authSOpts.Port)) url = "nats://" + url + "," + nats.DefaultURL nc, err := nats.Connect(url, nats.DisconnectHandler(dch), nats.ReconnectHandler(rch), nats.ClosedHandler(cch), nats.ErrorHandler(ech), nats.ReconnectWait(50*time.Millisecond), nats.DontRandomize()) if err != nil { t.Fatalf("Unable to connect: %v\n", err) } defer nc.Close() ncp, err := nats.Connect(nats.DefaultURL, nats.ReconnectWait(50*time.Millisecond)) if err != nil { t.Fatalf("Unable to connect: %v\n", err) } defer ncp.Close() // Wait to make sure that if we have closed (incorrectly) the // asyncCBDispatcher during the connect process, this is caught here. time.Sleep(time.Second) s.Shutdown() s = RunDefaultServer() defer s.Shutdown() if err := Wait(reconnected); err != nil { t.Fatal("Did not get the reconnected callback") } var sub1 *nats.Subscription var sub2 *nats.Subscription recv := func(m *nats.Msg) { // Signal that one message is received recvCh <- true // We will now block if m.Subject == "foo" { <-recvCh1 } else { <-recvCh2 } m.Sub.Unsubscribe() } sub1, err = nc.Subscribe("foo", recv) if err != nil { t.Fatalf("Unable to create subscription: %v\n", err) } sub1.SetPendingLimits(1, 100000) sub2, err = nc.Subscribe("bar", recv) if err != nil { t.Fatalf("Unable to create subscription: %v\n", err) } sub2.SetPendingLimits(1, 100000) nc.Flush() ncp.Publish("foo", []byte("test")) ncp.Publish("bar", []byte("test")) ncp.Flush() // Wait notification that message were received err = Wait(recvCh) if err == nil { err = Wait(recvCh) } if err != nil { t.Fatal("Did not receive message") } for i := 0; i < 2; i++ { ncp.Publish("foo", []byte("test")) ncp.Publish("bar", []byte("test")) } ncp.Flush() if err := Wait(asyncErr); err != nil { t.Fatal("Did not get the async callback") } if err := Wait(asyncErr); err != nil { t.Fatal("Did not get the async callback") } close(recvCh1) close(recvCh2) nc.Close() if err := Wait(closed); err != nil { t.Fatal("Did not get the close callback") } if len(cbErrors) > 0 { t.Fatalf("%v", <-cbErrors) } if (dtime1 == time.Time{}) || (dtime2 == time.Time{}) || (rtime == time.Time{}) || (atime1 == time.Time{}) || (atime2 == time.Time{}) || (ctime == time.Time{}) { t.Fatalf("Some callbacks did not fire:\n%v\n%v\n%v\n%v\n%v\n%v", dtime1, rtime, atime1, atime2, dtime2, ctime) } if rtime.Before(dtime1) || dtime2.Before(rtime) || atime2.Before(atime1) || ctime.Before(atime2) { t.Fatalf("Wrong callback order:\n%v\n%v\n%v\n%v\n%v\n%v", dtime1, rtime, atime1, atime2, dtime2, ctime) } }