github.com/micro/go-micro/examples@v0.0.0-20210105173217-bf4ab679e18b/config/grpc/srv/main.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"crypto/md5"
     6  	"fmt"
     7  	"net"
     8  	"strings"
     9  	"sync"
    10  	"time"
    11  
    12  	"github.com/micro/go-micro/v2/config"
    13  	"github.com/micro/go-micro/v2/config/source/file"
    14  	"github.com/micro/go-micro/v2/util/log"
    15  	proto "github.com/micro/go-plugins/config/source/grpc/v2/proto"
    16  	grpc "google.golang.org/grpc"
    17  )
    18  
    19  var (
    20  	mux        sync.RWMutex
    21  	configMaps = make(map[string]*proto.ChangeSet)
    22  	apps       = []string{"micro", "extra"}
    23  )
    24  
    25  type Service struct{}
    26  
    27  func main() {
    28  	// load config files
    29  	err := loadConfigFile()
    30  	if err != nil {
    31  		log.Fatal(err)
    32  	}
    33  
    34  	// new service
    35  	service := grpc.NewServer()
    36  	proto.RegisterSourceServer(service, new(Service))
    37  	ts, err := net.Listen("tcp", ":8600")
    38  	if err != nil {
    39  		log.Fatal(err)
    40  	}
    41  
    42  	log.Logf("configServer started")
    43  	err = service.Serve(ts)
    44  	if err != nil {
    45  		log.Fatal(err)
    46  	}
    47  }
    48  
    49  func (s Service) Read(ctx context.Context, req *proto.ReadRequest) (rsp *proto.ReadResponse, err error) {
    50  	appName := parsePath(req.Path)
    51  	switch appName {
    52  	case "micro", "extra":
    53  		rsp = &proto.ReadResponse{
    54  			ChangeSet: getConfig(appName),
    55  		}
    56  		return
    57  	default:
    58  		err = fmt.Errorf("[Read] the first path is invalid")
    59  		return
    60  	}
    61  
    62  	return
    63  }
    64  
    65  func (s Service) Watch(req *proto.WatchRequest, server proto.Source_WatchServer) (err error) {
    66  	appName := parsePath(req.Path)
    67  	rsp := &proto.WatchResponse{
    68  		ChangeSet: getConfig(appName),
    69  	}
    70  	if err = server.Send(rsp); err != nil {
    71  		log.Logf("[Watch] watch files error,%s", err)
    72  		return err
    73  	}
    74  
    75  	return
    76  }
    77  
    78  func loadConfigFile() (err error) {
    79  	for _, app := range apps {
    80  		if err := config.Load(file.NewSource(
    81  			file.WithPath("./conf/" + app + ".yml"),
    82  		)); err != nil {
    83  			log.Fatalf("[loadConfigFile] load files error,%s", err)
    84  			return err
    85  		}
    86  	}
    87  
    88  	// watch changes
    89  	watcher, err := config.Watch()
    90  	if err != nil {
    91  		log.Fatalf("[loadConfigFile] start watching files error,%s", err)
    92  		return err
    93  	}
    94  
    95  	go func() {
    96  		for {
    97  			v, err := watcher.Next()
    98  			if err != nil {
    99  				log.Fatalf("[loadConfigFile] watch files error,%s", err)
   100  				return
   101  			}
   102  
   103  			log.Logf("[loadConfigFile] file change, %s", string(v.Bytes()))
   104  		}
   105  	}()
   106  
   107  	return
   108  }
   109  
   110  func getConfig(appName string) *proto.ChangeSet {
   111  	bytes := config.Get(appName).Bytes()
   112  
   113  	log.Logf("[getConfig] appName,%s", string(bytes))
   114  	return &proto.ChangeSet{
   115  		Data:      bytes,
   116  		Checksum:  fmt.Sprintf("%x", md5.Sum(bytes)),
   117  		Format:    "yml",
   118  		Source:    "file",
   119  		Timestamp: time.Now().Unix()}
   120  }
   121  
   122  func parsePath(path string) (appName string) {
   123  	paths := strings.Split(path, "/")
   124  
   125  	if paths[0] == "" && len(paths) > 1 {
   126  		return paths[1]
   127  	}
   128  
   129  	return paths[0]
   130  }