func TestAuth(t *testing.T) { opts := gnatsd.DefaultTestOptions opts.Port = 8232 s := RunServerWithOptions(opts) // Auth is pluggable, so need to set here.. auth := &auth.Plain{ Username: "******", Password: "******", } s.SetAuthMethod(auth) defer s.Shutdown() _, err := nats.Connect("nats://*****:*****@localhost:8232") if err != nil { t.Fatal("Should have connected successfully") } nc.Close() }
func TestAuth(t *testing.T) { s := RunServerOnPort(8232) // Auth is pluggable, so need to set here.. auth := &auth.Plain{ Username: "******", Password: "******", } s.SetClientAuthMethod(auth) defer s.Shutdown() _, err := nats.Connect("nats://*****:*****@localhost:8232") if err != nil { t.Fatal("Should have connected successfully with a token") } nc.Close() }
func BenchmarkProxyPool(b *testing.B) { fmt.Println("Executing TestProxyPoolNoForm") proxyConn, _ := nats.Connect(nats_url) proxyHandler, _ := NewNatsProxy(proxyConn) clientConn, _ := nats.Connect(nats_url) natsClient, _ := NewNatsClient(clientConn) natsClient.Subscribe("POST", "/test/:event/:session", func(c *Context) { }) time.Sleep(time.Millisecond) reader := strings.NewReader("post=post") req, _ := http.NewRequest("POST", "http://127.0.0.1:3000/test/12324/2222", reader) req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value") rw := httptest.NewRecorder() b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { proxyHandler.ServeHTTP(rw, req) } b.StopTimer() }
func TestTLSConnection(t *testing.T) { srv, opts := RunServerWithConfig("./configs/tls.conf") defer srv.Shutdown() endpoint := fmt.Sprintf("%s:%d", opts.Host, opts.Port) nurl := fmt.Sprintf("tls://%s:%s@%s/", opts.Username, opts.Password, endpoint) nc, err := nats.Connect(nurl) if err == nil { t.Fatalf("Expected error trying to connect to secure server") } // Do simple SecureConnect nc, err = nats.Connect(fmt.Sprintf("tls://%s/", endpoint)) if err == nil { t.Fatalf("Expected error trying to connect to secure server with no auth") } // Now do more advanced checking, verifying servername and using rootCA. nc, err = nats.Connect(nurl, nats.RootCAs("./configs/certs/ca.pem")) if err != nil { t.Fatalf("Got an error on Connect with Secure Options: %+v\n", err) } defer nc.Close() subj := "foo-tls" sub, _ := nc.SubscribeSync(subj) nc.Publish(subj, []byte("We are Secure!")) nc.Flush() nmsgs, _ := sub.QueuedMsgs() if nmsgs != 1 { t.Fatalf("Expected to receive a message over the TLS connection") } }
func TestTokenAuth(t *testing.T) { s := RunServerOnPort(8232) secret := "S3Cr3T0k3n!" // Auth is pluggable, so need to set here.. auth := &auth.Token{Token: secret} s.SetClientAuthMethod(auth) defer s.Shutdown() _, err := nats.Connect("nats://*****:*****@localhost:8232", secret) nc, err := nats.Connect(tokenURL) if err != nil { t.Fatal("Should have connected successfully") } nc.Close() // Use Options nc, err = nats.Connect("nats://localhost:8232", nats.Token(secret)) if err != nil { t.Fatalf("Should have connected successfully: %v", err) } nc.Close() // Verify that token in the URL takes precedence. nc, err = nats.Connect(tokenURL, nats.Token("badtoken")) if err != nil { t.Fatalf("Should have connected successfully: %v", err) } nc.Close() }
func TestTLSClientCertificate(t *testing.T) { srv, opts := RunServerWithConfig("./configs/tlsverify.conf") defer srv.Shutdown() nurl := fmt.Sprintf("tls://%s:%d", opts.Host, opts.Port) _, err := nats.Connect(nurl) if err == nil { t.Fatalf("Expected error trying to connect to secure server without a certificate") } _, err = nats.Connect(nurl) if err == nil { t.Fatalf("Expected error trying to secure connect to secure server without a certificate") } // Load client certificate to sucessfully connect. certFile := "./configs/certs/client-cert.pem" keyFile := "./configs/certs/client-key.pem" cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { t.Fatalf("error parsing X509 certificate/key pair: %v", err) } // Load in root CA for server verification rootPEM, err := ioutil.ReadFile("./configs/certs/ca.pem") if err != nil || rootPEM == nil { t.Fatalf("failed to read root certificate") } pool := x509.NewCertPool() ok := pool.AppendCertsFromPEM([]byte(rootPEM)) if !ok { t.Fatalf("failed to parse root certificate") } config := &tls.Config{ Certificates: []tls.Certificate{cert}, ServerName: opts.Host, RootCAs: pool, MinVersion: tls.VersionTLS12, } copts := nats.DefaultOptions copts.Url = nurl copts.Secure = true copts.TLSConfig = config nc, err := copts.Connect() if err != nil { t.Fatalf("Got an error on Connect with Secure Options: %+v\n", err) } nc.Flush() defer nc.Close() }
func TestOptions(t *testing.T) { s := RunDefaultServer() defer s.Shutdown() nc, err := nats.Connect(nats.DefaultURL, nats.Name("myName"), nats.MaxReconnects(2), nats.ReconnectWait(50*time.Millisecond)) if err != nil { t.Fatalf("Failed to connect: %v", err) } defer nc.Close() rch := make(chan bool) cch := make(chan bool) nc.SetReconnectHandler(func(_ *nats.Conn) { rch <- true }) nc.SetClosedHandler(func(_ *nats.Conn) { cch <- true }) s.Shutdown() s = RunDefaultServer() defer s.Shutdown() if err := Wait(rch); err != nil { t.Fatal("Failed getting reconnected cb") } nc.Close() if err := Wait(cch); err != nil { t.Fatal("Failed getting closed cb") } nc, err = nats.Connect(nats.DefaultURL, nats.NoReconnect()) if err != nil { t.Fatalf("Failed to connect: %v", err) } defer nc.Close() nc.SetReconnectHandler(func(_ *nats.Conn) { rch <- true }) nc.SetClosedHandler(func(_ *nats.Conn) { cch <- true }) s.Shutdown() // We should not get a reconnect cb this time if err := WaitTime(rch, time.Second); err == nil { t.Fatal("Unexpected reconnect cb") } nc.Close() if err := Wait(cch); err != nil { t.Fatal("Failed getting closed cb") } }
func TestTLSChainedSolicitWorks(t *testing.T) { optsSeed, _ := ProcessConfigFile("./configs/seed_tls.conf") optsSeed.NoSigs, optsSeed.NoLog = true, true srvSeed := RunServer(optsSeed) defer srvSeed.Shutdown() optsA := nextServerOpts(optsSeed) optsA.Routes = RoutesFromStr(fmt.Sprintf("nats://%s:%d", optsSeed.ClusterHost, optsSeed.ClusterPort)) srvA := RunServer(optsA) defer srvA.Shutdown() urlSeed := fmt.Sprintf("nats://%s:%d/", optsSeed.Host, optsSeed.Port) nc1, err := nats.Connect(urlSeed) if err != nil { t.Fatalf("Error creating client: %v\n", err) } defer nc1.Close() // Test that we are connected. ch := make(chan bool) nc1.Subscribe("foo", func(m *nats.Msg) { ch <- true }) nc1.Flush() optsB := nextServerOpts(optsA) // Server B connects to A optsB.Routes = RoutesFromStr(fmt.Sprintf("nats://%s:%d", optsA.ClusterHost, optsA.ClusterPort)) srvB := RunServer(optsB) defer srvB.Shutdown() urlB := fmt.Sprintf("nats://%s:%d/", optsB.Host, optsB.Port) nc2, err := nats.Connect(urlB) if err != nil { t.Fatalf("Error creating client: %v\n", err) } defer nc2.Close() checkClusterFormed(t, srvSeed, srvA, srvB) nc2.Publish("foo", []byte("Hello")) // Wait for message select { case <-ch: case <-time.After(2 * time.Second): t.Fatal("Timeout waiting for message across route") } }
// This will test request semantics across a route to queues func TestRequestsAcrossRoutesToQueues(t *testing.T) { srvA, srvB, optsA, optsB := runServers(t) defer srvA.Shutdown() defer srvB.Shutdown() urlA := fmt.Sprintf("nats://%s:%d/", optsA.Host, optsA.Port) urlB := fmt.Sprintf("nats://%s:%d/", optsB.Host, optsB.Port) nc1, err := nats.Connect(urlA) if err != nil { t.Fatalf("Failed to create connection for nc1: %v\n", err) } defer nc1.Close() nc2, err := nats.Connect(urlB) if err != nil { t.Fatalf("Failed to create connection for nc2: %v\n", err) } defer nc2.Close() ec1, _ := nats.NewEncodedConn(nc1, nats.JSON_ENCODER) ec2, _ := nats.NewEncodedConn(nc2, nats.JSON_ENCODER) response := []byte("I will help you") // Connect one responder to srvA nc1.QueueSubscribe("foo-req", "booboo", func(m *nats.Msg) { nc1.Publish(m.Reply, response) }) // Make sure the route and the subscription are propagated. nc1.Flush() // Connect the other responder to srvB nc2.QueueSubscribe("foo-req", "booboo", func(m *nats.Msg) { nc2.Publish(m.Reply, response) }) var resp string for i := 0; i < 100; i++ { if err := ec2.Request("foo-req", i, &resp, 100*time.Millisecond); err != nil { t.Fatalf("Received an error on Request test [%d]: %s", i, err) } } for i := 0; i < 100; i++ { if err := ec1.Request("foo-req", i, &resp, 100*time.Millisecond); err != nil { t.Fatalf("Received an error on Request test [%d]: %s", i, err) } } }
// Shows different ways to create a Conn func ExampleConnect() { nats.Connect(nats.DefaultURL) nats.Connect("nats://*****:*****@nats.apcera.com:421") opts := nats.Options{ AllowReconnect: true, MaxReconnect: 10, ReconnectWait: 5 * time.Second, Timeout: 1 * time.Second, } nc, _ := opts.Connect() nc.Close() }
// Connect just connects you to nats, no fuss. func Connect() (*Uplink, error) { nc, err := nats.Connect(*natsServer) if err != nil { return nil, err } c, err := nats.NewEncodedConn(nc, nats.JSON_ENCODER) if err != nil { return nil, err } id := uuid.New() u := &Uplink{ EncodedConn: c, Logger: log.New(os.Stdout, id+" ", log.LstdFlags), ID: id, Nats: nc, } _, err = c.Subscribe(u.ID+":ping", func(subj, reply string, msg string) { c.Publish(reply, "pong") }) if err != nil { return nil, err } return u, nil }
func main() { var urls = flag.String("s", nats.DefaultURL, "The nats server URLs (separated by comma)") var showTime = flag.Bool("t", false, "Display timestamps") log.SetFlags(0) flag.Usage = usage flag.Parse() args := flag.Args() if len(args) < 2 { usage() } nc, err := nats.Connect(*urls) if err != nil { log.Fatalf("Can't connect: %v\n", err) } subj, reply, i := args[0], args[1], 0 nc.Subscribe(subj, func(msg *nats.Msg) { i++ printMsg(msg, i) nc.Publish(msg.Reply, []byte(reply)) }) log.Printf("Listening on [%s]\n", subj) if *showTime { log.SetFlags(log.LstdFlags) } runtime.Goexit() }
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 main() { c = nconfig.Load() qAddr := c.GetString(nconfig.KEY_QUEUE_ADDR) n, e := nats.Connect(qAddr) if e != nil { panic(e) } conn, err := nats.NewEncodedConn(n, nats.JSON_ENCODER) if err != nil { panic(err) } conn.Subscribe("realtime-jobs", jobsHandler) log.Info("Connected to NATS on " + qAddr) http.HandleFunc("/register", func(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { panic(err) return } connections = append(connections, conn) }) port := c.GetString(nconfig.KEY_BROKER_PORT) log.Info("Starting WS service on port " + port) http.ListenAndServe(port, nil) }
func main() { c, err := nats.Connect(*url) if err != nil { panic(err) } client := derek.NewNATSClient(*subject, c) ticker := time.NewTicker(time.Second) for _ = range ticker.C { req, err := http.NewRequest("GET", "http://ya.ru", nil) if err != nil { panic(err) } r, err := derek.NewRequest(req) if err != nil { panic(err) } start := time.Now() res, err := client.Do(r) duration := time.Now().Sub(start) if err != nil { fmt.Println("ERR", duration, err) } else { fmt.Println("DONE", duration, res.StatusCode, bytes.NewBuffer(res.Body)) } } }
func main() { flag.Parse() fmt.Println("topic is " + topic) fmt.Println("message is " + message) ticker := time.NewTicker(4 * time.Second) _ = <-ticker.C nc, _ := nats.Connect(nats.DefaultURL) c, _ := nats.NewEncodedConn(nc, nats.JSON_ENCODER) defer c.Close() if c == nil { fmt.Printf("nats error: fail to connect.\n") os.Exit(0) } for { err := c.LastError() if err != nil { fmt.Printf("nats error: %s", err.Error()) break } _ = <-ticker.C err = c.Publish(topic, message) if err != nil { fmt.Printf("publish err: %s", err.Error()) os.Exit(0) } fmt.Printf("public topic %s with content %s\n", topic, message) } }
func runResponder() { log.Printf("Starting responder") nc, err := nats.Connect("nats://localhost:4222") if err != nil { log.Printf("Failed to connect to message queue: %s", err) return } c, err := nats.NewEncodedConn(nc, nats.JSON_ENCODER) if err != nil { log.Printf("Failed to create encoded connection for message queue: %s", err) return } log.Printf("Connected") subject := "call" subscription, err := c.Subscribe(subject, func(subject string, replyTo string, s string) { log.Printf("Received a message: %v", s) c.Publish(replyTo, "pong") }) if err != nil { log.Printf("Failed to subscribe to subject %s: %v", subject, err) return } log.Printf("Responding to messages on %s", subscription.Subject) }
func ExampleConn_PublishMsg() { nc, _ := nats.Connect(nats.DefaultURL) defer nc.Close() msg := &nats.Msg{Subject: "foo", Reply: "bar", Data: []byte("Hello World!")} nc.PublishMsg(msg) }
func main() { var urls = flag.String("s", nats.DefaultURL, "The nats server URLs (separated by comma)") log.SetFlags(0) flag.Usage = usage flag.Parse() args := flag.Args() if len(args) < 2 { usage() } nc, err := nats.Connect(*urls) if err != nil { log.Fatalf("Can't connect: %v\n", err) } defer nc.Close() subj, payload := args[0], []byte(args[1]) msg, err := nc.Request(subj, []byte(payload), 100*time.Millisecond) if err != nil { if nc.LastError() != nil { log.Fatalf("Error in Request: %v\n", nc.LastError()) } log.Fatalf("Error in Request: %v\n", err) } log.Printf("Published [%s] : '%s'\n", subj, payload) log.Printf("Received [%v] : '%s'\n", msg.Subject, string(msg.Data)) }
func main() { var urls = flag.String("s", nats.DefaultURL, "The nats server URLs (separated by comma)") log.SetFlags(0) flag.Usage = usage flag.Parse() args := flag.Args() if len(args) < 2 { usage() } nc, err := nats.Connect(*urls) if err != nil { log.Fatal(err) } defer nc.Close() subj, msg := args[0], []byte(args[1]) nc.Publish(subj, msg) nc.Flush() if err := nc.LastError(); err != nil { log.Fatal(err) } else { log.Printf("Published [%s] : '%s'\n", subj, msg) } }
func TestNatsConnNotClosedOnClose(t *testing.T) { // Run a NATS Streaming server s := RunServer(clusterName) defer s.Shutdown() // Create a NATS connection nc, err := nats.Connect(nats.DefaultURL) if err != nil { t.Fatalf("Unexpected error on Connect: %v", err) } defer nc.Close() // Pass this NATS connection to NATS Streaming sc, err := Connect(clusterName, clientName, NatsConn(nc)) if err != nil { t.Fatalf("Unexpected error on connect: %v", err) } // Now close the NATS Streaming connection sc.Close() // Verify that NATS connection is not closed if nc.IsClosed() { t.Fatal("NATS connection should NOT have been closed in Connect") } }
func (s *gnatsdSuite) aTestSerivce() { service := &gnatsdService{} port, err := service.Start() s.NoError(err, "start service error") defer service.Stop() nc, err := nats.Connect(fmt.Sprintf("nats://localhost:%d", port)) s.NoError(err, "create conn error") c, err := nats.NewEncodedConn(nc, nats.JSON_ENCODER) s.NoError(err, "create encoded conn error") defer c.Close() testText := "Hello World" testTopic := "foo" received := false // Simple Async Subscriber c.Subscribe(testTopic, func(reply string) { s.Equal(testText, reply, "reply inconsistent") received = true }) // Simple Publisher err = c.Publish(testTopic, testText) s.NoError(err, "publish msg error") time.Sleep(3 * time.Second) s.True(received, "not recevied any msgs") }
func NewGnatsd(numberOfMessages int, testLatency bool) *Gnatsd { conn, _ := nats.Connect(nats.DefaultURL) // We want to be alerted if we get disconnected, this will // be due to Slow Consumer. conn.Opts.AllowReconnect = false // Report async errors. conn.Opts.AsyncErrorCB = func(nc *nats.Conn, sub *nats.Subscription, err error) { panic(fmt.Sprintf("NATS: Received an async error! %v\n", err)) } // Report a disconnect scenario. conn.Opts.DisconnectedCB = func(nc *nats.Conn) { fmt.Printf("Getting behind! %d\n", nc.OutMsgs-nc.InMsgs) panic("NATS: Got disconnected!") } var handler benchmark.MessageHandler if testLatency { handler = &benchmark.LatencyMessageHandler{ NumberOfMessages: numberOfMessages, Latencies: []float32{}, } } else { handler = &benchmark.ThroughputMessageHandler{NumberOfMessages: numberOfMessages} } return &Gnatsd{ handler: handler, subject: "test", conn: conn, testLatency: testLatency, } }
func stressConnect(t *testing.T, wg *sync.WaitGroup, errCh chan error, url string, index int) { defer wg.Done() subName := fmt.Sprintf("foo.%d", index) for i := 0; i < 100; i++ { nc, err := nats.Connect(url, nats.RootCAs("./configs/certs/ca.pem")) if err != nil { errCh <- fmt.Errorf("Unable to create TLS connection: %v\n", err) return } defer nc.Close() sub, err := nc.SubscribeSync(subName) if err != nil { errCh <- fmt.Errorf("Unable to subscribe on '%s': %v\n", subName, err) return } if err := nc.Publish(subName, []byte("secure data")); err != nil { errCh <- fmt.Errorf("Unable to send on '%s': %v\n", subName, err) } if _, err := sub.NextMsg(2 * time.Second); err != nil { errCh <- fmt.Errorf("Unable to get next message: %v\n", err) } nc.Close() } errCh <- nil }
func createNATSConnection(endpoint string) (publisher.PublishingConnection, error) { nc, err := nats.Connect(endpoint) if err != nil { return nil, err } return nc, nil }
func TestHotSpotReconnect(t *testing.T) { s1 := RunServerOnPort(1222) defer s1.Shutdown() numClients := 32 clients := []*nats.Conn{} wg := &sync.WaitGroup{} wg.Add(numClients) opts := []nats.Option{ nats.ReconnectWait(50 * time.Millisecond), nats.ReconnectHandler(func(_ *nats.Conn) { wg.Done() }), } for i := 0; i < numClients; i++ { // nc, err := opts.Connect() nc, err := nats.Connect(servers, opts...) if err != nil { t.Fatalf("Expected to connect, got err: %v\n", err) } defer nc.Close() if nc.ConnectedUrl() != testServers[0] { t.Fatalf("Connected to incorrect server: %v\n", nc.ConnectedUrl()) } clients = append(clients, nc) } s2 := RunServerOnPort(1224) defer s2.Shutdown() s3 := RunServerOnPort(1226) defer s3.Shutdown() s1.Shutdown() numServers := 2 // Wait on all reconnects wg.Wait() // Walk the clients and calculate how many of each.. cs := make(map[string]int) for _, nc := range clients { cs[nc.ConnectedUrl()]++ nc.Close() } if len(cs) != numServers { t.Fatalf("Wrong number of reported servers: %d vs %d\n", len(cs), numServers) } expected := numClients / numServers v := uint(float32(expected) * 0.40) // Check that each item is within acceptable range for s, total := range cs { delta := uint(math.Abs(float64(expected - total))) if delta > v { t.Fatalf("Connected clients to server: %s out of range: %d\n", s, total) } } }
// Subscribe to all events func (s *Subscriber) Subscribe() { log.Println("Listening...") nc, _ := nats.Connect(nats.DefaultURL) nc.Subscribe("issues.list", func(m *nats.Msg) { issues := s.issuesList(m.Data) nc.Publish(m.Reply, *issues.toJSON()) }) nc.Subscribe("issues.details", func(m *nats.Msg) { issue := s.issuesDetails(m.Data) if issue != nil { nc.Publish(m.Reply, *issue.toJSON()) } else { nc.Publish(m.Reply, []byte(`{"error":"non existing issue"}`)) return } }) nc.Subscribe("issues.update", func(m *nats.Msg) { res := s.issuesUpdate(m.Data) nc.Publish(m.Reply, *ToJSON(res)) }) nc.Subscribe("issues.create", func(m *nats.Msg) { res := s.issuesCreate(m.Data) nc.Publish(m.Reply, *ToJSON(res)) }) nc.Subscribe("issue-tracker.setup", func(m *nats.Msg) { s.setup(nc, m) }) runtime.Goexit() }
func (runner *NATSRunner) Start() { if runner.natsSession != nil { panic("starting an already started NATS runner!!!") } _, err := exec.LookPath("gnatsd") if err != nil { fmt.Println("You need gnatsd installed!") os.Exit(1) } cmd := exec.Command("gnatsd", "-p", strconv.Itoa(runner.port)) sess, err := gexec.Start( cmd, gexec.NewPrefixedWriter("\x1b[32m[o]\x1b[34m[gnatsd]\x1b[0m ", ginkgo.GinkgoWriter), gexec.NewPrefixedWriter("\x1b[91m[e]\x1b[34m[gnatsd]\x1b[0m ", ginkgo.GinkgoWriter), ) Expect(err).NotTo(HaveOccurred(), "Make sure to have gnatsd on your path") runner.natsSession = sess Expect(err).NotTo(HaveOccurred()) var messageBus *nats.Conn Eventually(func() error { messageBus, err = nats.Connect(fmt.Sprintf("nats://127.0.0.1:%d", runner.port)) return err }, 5, 0.1).ShouldNot(HaveOccurred()) runner.MessageBus = messageBus }
func runLogger() { log.Printf("Starting worker") nc, err := nats.Connect("nats://localhost:4222") if err != nil { log.Printf("Failed to connect to message queue: %s", err) return } c, err := nats.NewEncodedConn(nc, nats.JSON_ENCODER) if err != nil { log.Printf("Failed to create encoded connection for message queue: %s", err) return } log.Printf("Connected") subject := "cast" subscription, err := c.Subscribe(subject, func(s string) { log.Printf("Received a message: %v", s) }) if err != nil { log.Printf("Failed to subscribe to subject %s: %v", subject, err) return } log.Printf("Listening for messages on %s", subscription.Subject) }
func NewElectronConn(opt *nats.Options) (ec *ElectronConn, err error) { var nc *nats.Conn if opt == nil { nc, err = nats.Connect(nats.DefaultURL) } else { nc, err = opt.Connect() } if err != nil { return nil, err } ec = &ElectronConn{conn: nc} f := func(m *nats.Msg) { ID := atomic.AddUint32(&ec.genID, 1) if err := nc.Publish(m.Reply, []byte(fmt.Sprintf("%d", ID))); err != nil { logrus.Error(err) return } ec.Lock() ec.clients = append(ec.clients, ID) ec.Unlock() } if _, err = nc.Subscribe("register", f); err != nil { nc.Close() return nil, fmt.Errorf("nats: %v", err) } if ec.jsonConn, err = nats.NewEncodedConn(nc, "json"); err != nil { nc.Close() return nil, fmt.Errorf("nats: %v", err) } return }