go-micro.dev/v5@v5.12.0/config/source/nats/nats.go (about) 1 package nats 2 3 import ( 4 "fmt" 5 "net" 6 "strings" 7 "time" 8 9 natsgo "github.com/nats-io/nats.go" 10 "go-micro.dev/v5/config/source" 11 log "go-micro.dev/v5/logger" 12 ) 13 14 type nats struct { 15 url string 16 bucket string 17 key string 18 kv natsgo.KeyValue 19 opts source.Options 20 } 21 22 // DefaultBucket is the bucket that nats keys will be assumed to have if you 23 // haven't specified one. 24 var ( 25 DefaultBucket = "default" 26 DefaultKey = "micro_config" 27 ) 28 29 func (n *nats) Read() (*source.ChangeSet, error) { 30 e, err := n.kv.Get(n.key) 31 if err != nil { 32 if err == natsgo.ErrKeyNotFound { 33 return nil, nil 34 } 35 return nil, err 36 } 37 38 if e.Value() == nil || len(e.Value()) == 0 { 39 return nil, fmt.Errorf("source not found: %s", n.key) 40 } 41 42 cs := &source.ChangeSet{ 43 Data: e.Value(), 44 Format: n.opts.Encoder.String(), 45 Source: n.String(), 46 Timestamp: time.Now(), 47 } 48 cs.Checksum = cs.Sum() 49 50 return cs, nil 51 } 52 53 func (n *nats) Write(cs *source.ChangeSet) error { 54 _, err := n.kv.Put(n.key, cs.Data) 55 if err != nil { 56 return err 57 } 58 59 return nil 60 } 61 62 func (n *nats) String() string { 63 return "nats" 64 } 65 66 func (n *nats) Watch() (source.Watcher, error) { 67 return newWatcher(n.kv, n.bucket, n.key, n.String(), n.opts.Encoder) 68 } 69 70 func NewSource(opts ...source.Option) source.Source { 71 options := source.NewOptions(opts...) 72 73 config := natsgo.GetDefaultOptions() 74 75 urls, ok := options.Context.Value(urlKey{}).([]string) 76 endpoints := []string{} 77 if ok { 78 for _, u := range urls { 79 addr, port, err := net.SplitHostPort(u) 80 if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" { 81 port = "4222" 82 addr = u 83 endpoints = append(endpoints, fmt.Sprintf("%s:%s", addr, port)) 84 } else if err == nil { 85 endpoints = append(endpoints, fmt.Sprintf("%s:%s", addr, port)) 86 } 87 } 88 } 89 if len(endpoints) == 0 { 90 endpoints = append(endpoints, "127.0.0.1:4222") 91 } 92 93 bucket, ok := options.Context.Value(bucketKey{}).(string) 94 if !ok { 95 bucket = DefaultBucket 96 } 97 98 key, ok := options.Context.Value(keyKey{}).(string) 99 if !ok { 100 key = DefaultKey 101 } 102 103 config.Url = strings.Join(endpoints, ",") 104 105 nc, err := natsgo.Connect(config.Url) 106 if err != nil { 107 log.Error(err) 108 } 109 110 js, err := nc.JetStream(natsgo.MaxWait(10 * time.Second)) 111 if err != nil { 112 log.Error(err) 113 } 114 115 kv, err := js.KeyValue(bucket) 116 if err == natsgo.ErrBucketNotFound || err == natsgo.ErrKeyNotFound { 117 kv, err = js.CreateKeyValue(&natsgo.KeyValueConfig{Bucket: bucket}) 118 if err != nil { 119 log.Error(err) 120 } 121 } 122 123 if err != nil { 124 log.Error(err) 125 } 126 127 return &nats{ 128 url: config.Url, 129 bucket: bucket, 130 key: key, 131 kv: kv, 132 opts: options, 133 } 134 }