github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/rpc/nats/connect.go (about) 1 package nats 2 3 import ( 4 "time" 5 6 "github.com/angenalZZZ/gofunc/log" 7 "github.com/nats-io/nats.go" 8 ) 9 10 // Conn represents a bare connection to global nats-server. 11 // The connection is safe to use in multiple Go routines concurrently. 12 var Conn *nats.Conn 13 14 // Subject global subscription. This can be different 15 // than the received subject inside a Msg if this is a wildcard. 16 var Subject string 17 18 // Log logger for global Conn. 19 var Log *log.Logger 20 21 // Connection addr and token, credentials, cert and key 22 // to be used when connecting to a nats-server. 23 type Connection struct { 24 Addr string 25 Token string 26 Cred string 27 Cert string 28 Key string 29 } 30 31 // New creates a client connect. 32 func New(name, flagAddr, flagCred string, flagToken string, flagCert, flagKey string) (nc *nats.Conn, err error) { 33 var ( 34 addr = nats.DefaultURL 35 ops = []nats.Option{nats.Name(name)} 36 ) 37 38 if Log == nil { 39 Log = log.InitConsole("15:04:05.000", false) 40 } 41 42 if flagAddr != "" { 43 addr = flagAddr 44 } 45 if flagCred != "" { 46 ops = append(ops, nats.UserCredentials(flagCred)) 47 } 48 if flagToken != "" { 49 ops = append(ops, nats.Token(flagToken)) 50 } 51 52 // If the server requires client certificate 53 // E.g. /certs/client-cert.pem /certs/client-Index.pem 54 if flagCert != "" && flagKey != "" { 55 cert := nats.ClientCert(flagCert, flagKey) 56 ops = append(ops, cert) 57 } 58 // If you are using a self-signed certificate, you need to have a tls.Config with RootCAs setup 59 // E.g. /certs/ca.pem 60 if flagCert != "" { 61 cert := nats.RootCAs(flagCert) 62 ops = append(ops, cert) 63 } 64 65 ops = append(ops, 66 nats.MaxReconnects(1200), 67 nats.PingInterval(time.Minute), 68 nats.ReconnectWait(2*time.Second), 69 nats.PingInterval(time.Minute), 70 nats.Timeout(2*time.Second), 71 nats.SyncQueueLen(100000000), // sets number of messages will buffer internally. 72 nats.ReconnectBufSize(104857600), // 100Mb size of messages kept while busy reconnecting. 73 nats.DisconnectErrHandler(func(nc *nats.Conn, err error) { 74 Log.Error().Msgf("[nats] disconnected due to: %s, will attempt reconnects for 10 minutes", err) 75 }), 76 nats.ReconnectHandler(func(nc *nats.Conn) { 77 Log.Error().Msgf("[nats] reconnected %q", nc.ConnectedUrl()) 78 }), 79 nats.ClosedHandler(func(nc *nats.Conn) { 80 Log.Error().Msgf("[nats] exiting") 81 }), 82 ) 83 84 nc, err = nats.Connect(addr, ops...) 85 return 86 } 87 88 // FlushAndCheckLastError Flush connection to server, returns when all messages have been processed. 89 func FlushAndCheckLastError(nc *nats.Conn) { 90 if err := nc.Flush(); err != nil { 91 Log.Error().Msgf("[nats] flush messages > %s", err) 92 } else if err = nc.LastError(); err != nil { 93 Log.Error().Msgf("[nats] after flush and get last error > %s", err) 94 } 95 } 96 97 // SubscribeLimitHandle Set pending limits error handle. 98 func SubscribeLimitHandle(sub *nats.Subscription, msgLimit, bytesLimitOfMsg int) { 99 if err := sub.SetPendingLimits(msgLimit, msgLimit*bytesLimitOfMsg); err != nil { 100 Log.Error().Msgf("[nats] set pending limits > %s", err) 101 } 102 103 // Delivered returns the number of delivered messages for this subscription. 104 if deliveredNum, err := sub.Delivered(); err != nil { 105 Log.Error().Msgf("[nats] number of messages deliver > %s", err) 106 } else if deliveredNum > 0 { 107 Log.Info().Msgf("[nats] number of messages deliver: %d", deliveredNum) 108 } 109 110 // Dropped returns the number of known dropped messages for this subscription. 111 if droppedNum, err := sub.Dropped(); err != nil { 112 Log.Error().Msgf("[nats] number of messages dropped > %s", err) 113 } else if droppedNum > 0 { 114 Log.Info().Msgf("[nats] number of messages dropped: %d", droppedNum) 115 } 116 } 117 118 // SubscribeErrorHandle Set listening error handle. 119 func SubscribeErrorHandle(sub *nats.Subscription, async bool, err error) { 120 if err != nil { 121 Log.Error().Msgf("[nats] failed listening on %q > %s", sub.Subject, err) 122 } else { 123 a, v := "async", "available" 124 if async == false { 125 a = "sync" 126 } 127 if sub.IsValid() == false { 128 v = "invalid" 129 } 130 Log.Info().Msgf("[nats] successful listening on %s subject: %q", v, sub.Subject) 131 Log.Info().Msgf("[nats] start %s waiting to receive messages on %q", a, sub.Subject) 132 } 133 }