159
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								README.md
									
									
									
									
									
								
							| @@ -27,7 +27,7 @@ By default go-micro only provides a single implementation of each interface. Plu | |||||||
|  |  | ||||||
| ## Prerequisites | ## Prerequisites | ||||||
|  |  | ||||||
| Consul is the default discovery mechanism provided in go-micro. Discovery is however pluggable. | Consul is the default discovery mechanism provided in go-micro. Discovery is however pluggable so you can used etcd, kubernetes, zookeeper, etc. | ||||||
|  |  | ||||||
| ### Install Consul | ### Install Consul | ||||||
| [https://www.consul.io/intro/getting-started/install.html](https://www.consul.io/intro/getting-started/install.html) | [https://www.consul.io/intro/getting-started/install.html](https://www.consul.io/intro/getting-started/install.html) | ||||||
| @@ -41,104 +41,141 @@ $ consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul | |||||||
|  |  | ||||||
| ### Run Service | ### Run Service | ||||||
| ``` | ``` | ||||||
| $ go run examples/server/main.go --logtostderr | $ go run examples/service/main.go --logtostderr | ||||||
| I1108 11:08:19.926071   11358 server.go:96] Starting server go.micro.srv.example id go.micro.srv.example-04de4cf0-8609-11e5-bf3a-68a86d0d36b6 | I0102 00:22:26.413467   12018 rpc_server.go:297] Listening on [::]:62492 | ||||||
| I1108 11:08:19.926407   11358 rpc_server.go:233] Listening on [::]:54080 | I0102 00:22:26.413803   12018 http_broker.go:115] Broker Listening on [::]:62493 | ||||||
| I1108 11:08:19.926500   11358 http_broker.go:80] Broker Listening on [::]:54081 | I0102 00:22:26.414009   12018 rpc_server.go:212] Registering node: greeter-e6b2fc6f-b0e6-11e5-a42f-68a86d0d36b6 | ||||||
| I1108 11:08:19.926632   11358 rpc_server.go:158] Registering node: go.micro.srv.example-04de4cf0-8609-11e5-bf3a-68a86d0d36b6 |  | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ### Test Service | ### Test Service | ||||||
| ``` | ``` | ||||||
| $ go run examples/client/main.go  | $ go run examples/service/main.go --client | ||||||
| go.micro.srv.example-59b6e0ab-0300-11e5-b696-68a86d0d36b6: Hello John | Hello John | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ## Writing a service | ## Writing a service | ||||||
|  |  | ||||||
| ### Create request/response proto | ### Create request/response proto | ||||||
| `go-micro/examples/server/proto/example/example.proto`: | `go-micro/examples/service/proto/greeter.proto`: | ||||||
|  |  | ||||||
| ``` | ``` | ||||||
| syntax = "proto3"; | syntax = "proto3"; | ||||||
|  |  | ||||||
| message Request { | service Greeter { | ||||||
|  | 	rpc Hello(HelloRequest) returns (HelloResponse) {} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | message HelloRequest { | ||||||
| 	string name = 1; | 	string name = 1; | ||||||
| } | } | ||||||
|  |  | ||||||
| message Response { | message HelloResponse { | ||||||
|         string msg = 1; | 	string greeting = 2; | ||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| Compile proto `protoc -I$GOPATH/src --go_out=$GOPATH/src $GOPATH/src/github.com/micro/go-micro/examples/server/proto/example/example.proto` | ### Install protobuf for code generation | ||||||
|  |  | ||||||
| ### Create request handler | We use a protobuf plugin for code generation. This is completely optional. Look at [examples/server](https://github.com/micro/go-micro/blob/master/examples/server/main.go)  | ||||||
| `go-micro/examples/server/handler/example.go`: | and [examples/client](https://github.com/micro/go-micro/blob/master/examples/client/main.go) for examples without code generation. | ||||||
|  |  | ||||||
| ```go | ```shell | ||||||
| package handler | go get github.com/micro/protobuf | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	log "github.com/golang/glog" |  | ||||||
| 	c "github.com/micro/go-micro/context" |  | ||||||
| 	example "github.com/micro/go-micro/examples/server/proto/example" |  | ||||||
| 	"github.com/micro/go-micro/server" |  | ||||||
|  |  | ||||||
| 	"golang.org/x/net/context" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type Example struct{} |  | ||||||
|  |  | ||||||
| func (e *Example) Call(ctx context.Context, req *example.Request, rsp *example.Response) error { |  | ||||||
| 	md, _ := c.GetMetadata(ctx) |  | ||||||
| 	log.Infof("Received Example.Call request with metadata: %v", md) |  | ||||||
| 	rsp.Msg = server.Options().Id + ": Hello " + req.Name |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ### Init server | Compile proto `protoc -I$GOPATH/src --go_out=plugins=micro:$GOPATH/src $GOPATH/src/github.com/micro/go-micro/examples/service/proto/greeter.proto` | ||||||
| `go-micro/examples/server/main.go`: |  | ||||||
|  | ### Define the service | ||||||
|  | `go-micro/examples/service/main.go`: | ||||||
|  |  | ||||||
| ```go | ```go | ||||||
| package main | package main | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	log "github.com/golang/glog" | 	"fmt" | ||||||
| 	"github.com/micro/go-micro/cmd" |  | ||||||
| 	"github.com/micro/go-micro/examples/server/handler" | 	micro "github.com/micro/go-micro" | ||||||
| 	"github.com/micro/go-micro/server" | 	proto "github.com/micro/go-micro/examples/service/proto" | ||||||
|  | 	"golang.org/x/net/context" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | type Greeter struct{} | ||||||
|  |  | ||||||
|  | func (g *Greeter) Hello(ctx context.Context, req *proto.HelloRequest, rsp *proto.HelloResponse) error { | ||||||
|  | 	rsp.Greeting = "Hello " + req.Name | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func main() { | func main() { | ||||||
| 	// optionally setup command line usage | 	// Create a new service. Optionally include some options here. | ||||||
| 	cmd.Init() | 	service := micro.NewService( | ||||||
|  | 		micro.Name("greeter"), | ||||||
| 	// Initialise Server | 		micro.Version("latest"), | ||||||
| 	server.Init( | 		micro.Metadata(map[string]string{ | ||||||
| 		server.Name("go.micro.srv.example"), | 			"type": "helloworld", | ||||||
|  | 		}), | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
| 	// Register Handlers | 	// Init will parse the command line flags. Any flags set will | ||||||
| 	server.Handle( | 	// override the above settings. Options defined here will | ||||||
| 		server.NewHandler( | 	// override anything set on the command line. | ||||||
| 			new(handler.Example), | 	service.Init() | ||||||
| 		), |  | ||||||
| 	) |  | ||||||
|  |  | ||||||
| 	// Run server | 	// Register handler | ||||||
| 	if err := server.Run(); err != nil { | 	proto.RegisterGreeterHandler(service.Server(), new(Greeter)) | ||||||
| 		log.Fatal(err) |  | ||||||
|  | 	// Run the server | ||||||
|  | 	if err := service.Run(); err != nil { | ||||||
|  | 		fmt.Println(err) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ### Run service | ### Run service | ||||||
| ``` | ``` | ||||||
| $ go run examples/server/main.go --logtostderr | go run examples/service/main.go --logtostderr | ||||||
| I1108 11:08:19.926071   11358 server.go:96] Starting server go.micro.srv.example id go.micro.srv.example-04de4cf0-8609-11e5-bf3a-68a86d0d36b6 | I0102 00:22:26.413467   12018 rpc_server.go:297] Listening on [::]:62492 | ||||||
| I1108 11:08:19.926407   11358 rpc_server.go:233] Listening on [::]:54080 | I0102 00:22:26.413803   12018 http_broker.go:115] Broker Listening on [::]:62493 | ||||||
| I1108 11:08:19.926500   11358 http_broker.go:80] Broker Listening on [::]:54081 | I0102 00:22:26.414009   12018 rpc_server.go:212] Registering node: greeter-e6b2fc6f-b0e6-11e5-a42f-68a86d0d36b6 | ||||||
| I1108 11:08:19.926632   11358 rpc_server.go:158] Registering node: go.micro.srv.example-04de4cf0-8609-11e5-bf3a-68a86d0d36b6 | ``` | ||||||
|  |  | ||||||
|  | ### Define a client | ||||||
|  |  | ||||||
|  | `client.go` | ||||||
|  |  | ||||||
|  | ```go | ||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  |  | ||||||
|  | 	micro "github.com/micro/go-micro" | ||||||
|  | 	proto "github.com/micro/go-micro/examples/service/proto" | ||||||
|  | 	"golang.org/x/net/context" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	// Create a new service. Optionally include some options here. | ||||||
|  | 	service := micro.NewService(micro.Name("greeter.client")) | ||||||
|  |  | ||||||
|  | 	// Create new greeter client | ||||||
|  | 	greeter := proto.NewGreeterClient("greeter", service.Client()) | ||||||
|  |  | ||||||
|  | 	// Call the greeter | ||||||
|  | 	rsp, err := greeter.Hello(context.TODO(), &proto.HelloRequest{Name: "John"}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Println(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Print response | ||||||
|  | 	fmt.Println(rsp.Greeting) | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### Run the client | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | go run client.go | ||||||
|  | Hello John | ||||||
| ``` | ``` | ||||||
|   | |||||||
| @@ -26,6 +26,8 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| type Client interface { | type Client interface { | ||||||
|  | 	Init(...Option) error | ||||||
|  | 	Options() Options | ||||||
| 	NewPublication(topic string, msg interface{}) Publication | 	NewPublication(topic string, msg interface{}) Publication | ||||||
| 	NewRequest(service, method string, req interface{}, reqOpts ...RequestOption) Request | 	NewRequest(service, method string, req interface{}, reqOpts ...RequestOption) Request | ||||||
| 	NewProtoRequest(service, method string, req interface{}, reqOpts ...RequestOption) Request | 	NewProtoRequest(service, method string, req interface{}, reqOpts ...RequestOption) Request | ||||||
|   | |||||||
| @@ -149,6 +149,17 @@ func (r *rpcClient) stream(ctx context.Context, address string, req Request) (St | |||||||
| 	return stream, err | 	return stream, err | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (r *rpcClient) Init(opts ...Option) error { | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		o(&r.opts) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (r *rpcClient) Options() Options { | ||||||
|  | 	return r.opts | ||||||
|  | } | ||||||
|  |  | ||||||
| func (r *rpcClient) CallRemote(ctx context.Context, address string, request Request, response interface{}, opts ...CallOption) error { | func (r *rpcClient) CallRemote(ctx context.Context, address string, request Request, response interface{}, opts ...CallOption) error { | ||||||
| 	return r.call(ctx, address, request, response) | 	return r.call(ctx, address, request, response) | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										257
									
								
								cmd/cmd.go
									
									
									
									
									
								
							
							
						
						
									
										257
									
								
								cmd/cmd.go
									
									
									
									
									
								
							| @@ -7,11 +7,9 @@ import ( | |||||||
| 	"math/rand" | 	"math/rand" | ||||||
| 	"os" | 	"os" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"text/tabwriter" |  | ||||||
| 	"text/template" |  | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/codegangsta/cli" | 	"github.com/micro/cli" | ||||||
| 	"github.com/micro/go-micro/broker" | 	"github.com/micro/go-micro/broker" | ||||||
| 	"github.com/micro/go-micro/client" | 	"github.com/micro/go-micro/client" | ||||||
| 	"github.com/micro/go-micro/registry" | 	"github.com/micro/go-micro/registry" | ||||||
| @@ -20,10 +18,27 @@ import ( | |||||||
| 	"github.com/micro/go-micro/transport" | 	"github.com/micro/go-micro/transport" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var ( | type Cmd interface { | ||||||
| 	Actions = []func(*cli.Context){} | 	// The cli app within this cmd | ||||||
|  | 	App() *cli.App | ||||||
|  | 	// Adds options, parses flags and initialise | ||||||
|  | 	// exits on error | ||||||
|  | 	Init(opts ...Option) error | ||||||
|  | 	// Options set within this command | ||||||
|  | 	Options() Options | ||||||
|  | } | ||||||
|  |  | ||||||
| 	Flags = []cli.Flag{ | type cmd struct { | ||||||
|  | 	opts Options | ||||||
|  | 	app  *cli.App | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type Option func(o *Options) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	DefaultCmd = newCmd() | ||||||
|  |  | ||||||
|  | 	DefaultFlags = []cli.Flag{ | ||||||
| 		cli.StringFlag{ | 		cli.StringFlag{ | ||||||
| 			Name:   "server_name", | 			Name:   "server_name", | ||||||
| 			EnvVar: "MICRO_SERVER_NAME", | 			EnvVar: "MICRO_SERVER_NAME", | ||||||
| @@ -42,7 +57,6 @@ var ( | |||||||
| 		cli.StringFlag{ | 		cli.StringFlag{ | ||||||
| 			Name:   "server_address", | 			Name:   "server_address", | ||||||
| 			EnvVar: "MICRO_SERVER_ADDRESS", | 			EnvVar: "MICRO_SERVER_ADDRESS", | ||||||
| 			Value:  ":0", |  | ||||||
| 			Usage:  "Bind address for the server. 127.0.0.1:8080", | 			Usage:  "Bind address for the server. 127.0.0.1:8080", | ||||||
| 		}, | 		}, | ||||||
| 		cli.StringFlag{ | 		cli.StringFlag{ | ||||||
| @@ -59,7 +73,6 @@ var ( | |||||||
| 		cli.StringFlag{ | 		cli.StringFlag{ | ||||||
| 			Name:   "broker", | 			Name:   "broker", | ||||||
| 			EnvVar: "MICRO_BROKER", | 			EnvVar: "MICRO_BROKER", | ||||||
| 			Value:  "http", |  | ||||||
| 			Usage:  "Broker for pub/sub. http, nats, rabbitmq", | 			Usage:  "Broker for pub/sub. http, nats, rabbitmq", | ||||||
| 		}, | 		}, | ||||||
| 		cli.StringFlag{ | 		cli.StringFlag{ | ||||||
| @@ -70,7 +83,6 @@ var ( | |||||||
| 		cli.StringFlag{ | 		cli.StringFlag{ | ||||||
| 			Name:   "registry", | 			Name:   "registry", | ||||||
| 			EnvVar: "MICRO_REGISTRY", | 			EnvVar: "MICRO_REGISTRY", | ||||||
| 			Value:  "consul", |  | ||||||
| 			Usage:  "Registry for discovery. memory, consul, etcd, kubernetes", | 			Usage:  "Registry for discovery. memory, consul, etcd, kubernetes", | ||||||
| 		}, | 		}, | ||||||
| 		cli.StringFlag{ | 		cli.StringFlag{ | ||||||
| @@ -81,13 +93,11 @@ var ( | |||||||
| 		cli.StringFlag{ | 		cli.StringFlag{ | ||||||
| 			Name:   "selector", | 			Name:   "selector", | ||||||
| 			EnvVar: "MICRO_SELECTOR", | 			EnvVar: "MICRO_SELECTOR", | ||||||
| 			Value:  "selector", |  | ||||||
| 			Usage:  "Selector used to pick nodes for querying. random, roundrobin, blacklist", | 			Usage:  "Selector used to pick nodes for querying. random, roundrobin, blacklist", | ||||||
| 		}, | 		}, | ||||||
| 		cli.StringFlag{ | 		cli.StringFlag{ | ||||||
| 			Name:   "transport", | 			Name:   "transport", | ||||||
| 			EnvVar: "MICRO_TRANSPORT", | 			EnvVar: "MICRO_TRANSPORT", | ||||||
| 			Value:  "http", |  | ||||||
| 			Usage:  "Transport mechanism used; http, rabbitmq, nats", | 			Usage:  "Transport mechanism used; http, rabbitmq, nats", | ||||||
| 		}, | 		}, | ||||||
| 		cli.StringFlag{ | 		cli.StringFlag{ | ||||||
| @@ -127,58 +137,151 @@ var ( | |||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Brokers = map[string]func([]string, ...broker.Option) broker.Broker{ | 	DefaultBrokers = map[string]func([]string, ...broker.Option) broker.Broker{ | ||||||
| 		"http": broker.NewBroker, | 		"http": broker.NewBroker, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Registries = map[string]func([]string, ...registry.Option) registry.Registry{ | 	DefaultRegistries = map[string]func([]string, ...registry.Option) registry.Registry{ | ||||||
| 		"consul": registry.NewRegistry, | 		"consul": registry.NewRegistry, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Selectors = map[string]func(...selector.Option) selector.Selector{ | 	DefaultSelectors = map[string]func(...selector.Option) selector.Selector{ | ||||||
| 		"random": selector.NewSelector, | 		"random": selector.NewSelector, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Transports = map[string]func([]string, ...transport.Option) transport.Transport{ | 	DefaultTransports = map[string]func([]string, ...transport.Option) transport.Transport{ | ||||||
| 		"http": transport.NewTransport, | 		"http": transport.NewTransport, | ||||||
| 	} | 	} | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| 	rand.Seed(time.Now().Unix()) | 	rand.Seed(time.Now().Unix()) | ||||||
|  | 	help := cli.HelpPrinter | ||||||
|  | 	cli.HelpPrinter = func(writer io.Writer, templ string, data interface{}) { | ||||||
|  | 		help(writer, templ, data) | ||||||
|  | 		os.Exit(0) | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func Setup(c *cli.Context) error { | func newCmd(opts ...Option) Cmd { | ||||||
|  | 	options := Options{ | ||||||
|  | 		Broker:    &broker.DefaultBroker, | ||||||
|  | 		Client:    &client.DefaultClient, | ||||||
|  | 		Registry:  ®istry.DefaultRegistry, | ||||||
|  | 		Server:    &server.DefaultServer, | ||||||
|  | 		Selector:  &selector.DefaultSelector, | ||||||
|  | 		Transport: &transport.DefaultTransport, | ||||||
|  |  | ||||||
|  | 		Brokers:    DefaultBrokers, | ||||||
|  | 		Registries: DefaultRegistries, | ||||||
|  | 		Selectors:  DefaultSelectors, | ||||||
|  | 		Transports: DefaultTransports, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		o(&options) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(options.Description) == 0 { | ||||||
|  | 		options.Description = "a go-micro service" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	cmd := new(cmd) | ||||||
|  | 	cmd.opts = options | ||||||
|  | 	cmd.app = cli.NewApp() | ||||||
|  | 	cmd.app.Name = cmd.opts.Name | ||||||
|  | 	cmd.app.Version = cmd.opts.Version | ||||||
|  | 	cmd.app.Usage = cmd.opts.Description | ||||||
|  | 	cmd.app.Before = cmd.Before | ||||||
|  | 	cmd.app.Flags = DefaultFlags | ||||||
|  | 	cmd.app.Action = func(c *cli.Context) {} | ||||||
|  |  | ||||||
|  | 	if len(options.Version) == 0 { | ||||||
|  | 		cmd.app.HideVersion = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return cmd | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *cmd) App() *cli.App { | ||||||
|  | 	return c.app | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *cmd) Options() Options { | ||||||
|  | 	return c.opts | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *cmd) Before(ctx *cli.Context) error { | ||||||
|  | 	// Due to logger issues with glog, we need to do this | ||||||
| 	os.Args = os.Args[:1] | 	os.Args = os.Args[:1] | ||||||
|  | 	flag.Set("logtostderr", fmt.Sprintf("%v", ctx.Bool("logtostderr"))) | ||||||
| 	flag.Set("logtostderr", fmt.Sprintf("%v", c.Bool("logtostderr"))) | 	flag.Set("alsologtostderr", fmt.Sprintf("%v", ctx.Bool("alsologtostderr"))) | ||||||
| 	flag.Set("alsologtostderr", fmt.Sprintf("%v", c.Bool("alsologtostderr"))) | 	flag.Set("stderrthreshold", ctx.String("stderrthreshold")) | ||||||
| 	flag.Set("stderrthreshold", c.String("stderrthreshold")) | 	flag.Set("log_backtrace_at", ctx.String("log_backtrace_at")) | ||||||
| 	flag.Set("log_backtrace_at", c.String("log_backtrace_at")) | 	flag.Set("log_dir", ctx.String("log_dir")) | ||||||
| 	flag.Set("log_dir", c.String("log_dir")) | 	flag.Set("vmodule", ctx.String("vmodule")) | ||||||
| 	flag.Set("vmodule", c.String("vmodule")) | 	flag.Set("v", ctx.String("v")) | ||||||
| 	flag.Set("v", c.String("v")) |  | ||||||
|  |  | ||||||
| 	flag.Parse() | 	flag.Parse() | ||||||
|  |  | ||||||
| 	if b, ok := Brokers[c.String("broker")]; ok { | 	// If flags are set then use them otherwise do nothing | ||||||
| 		broker.DefaultBroker = b(strings.Split(c.String("broker_address"), ",")) | 	var serverOpts []server.Option | ||||||
|  | 	var clientOpts []client.Option | ||||||
|  |  | ||||||
|  | 	// Set the broker | ||||||
|  | 	if len(ctx.String("broker")) > 0 { | ||||||
|  | 		if b, ok := c.opts.Brokers[ctx.String("broker")]; ok { | ||||||
|  | 			n := b(strings.Split(ctx.String("broker_address"), ",")) | ||||||
|  | 			c.opts.Broker = &n | ||||||
|  | 		} else { | ||||||
|  | 			return fmt.Errorf("Broker %s not found", ctx.String("broker")) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 	if r, ok := Registries[c.String("registry")]; ok { | 		serverOpts = append(serverOpts, server.Broker(*c.opts.Broker)) | ||||||
| 		registry.DefaultRegistry = r(strings.Split(c.String("registry_address"), ",")) | 		clientOpts = append(clientOpts, client.Broker(*c.opts.Broker)) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if s, ok := Selectors[c.String("selector")]; ok { | 	// Set the registry | ||||||
| 		selector.DefaultSelector = s(selector.Registry(registry.DefaultRegistry)) | 	if len(ctx.String("registry")) > 0 { | ||||||
|  | 		if r, ok := c.opts.Registries[ctx.String("registry")]; ok { | ||||||
|  | 			n := r(strings.Split(ctx.String("registry_address"), ",")) | ||||||
|  | 			c.opts.Registry = &n | ||||||
|  | 		} else { | ||||||
|  | 			return fmt.Errorf("Registry %s not found", ctx.String("registry")) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 	if t, ok := Transports[c.String("transport")]; ok { | 		serverOpts = append(serverOpts, server.Registry(*c.opts.Registry)) | ||||||
| 		transport.DefaultTransport = t(strings.Split(c.String("transport_address"), ",")) | 		clientOpts = append(clientOpts, client.Registry(*c.opts.Registry)) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Set the selector | ||||||
|  | 	if len(ctx.String("selector")) > 0 { | ||||||
|  | 		if s, ok := c.opts.Selectors[ctx.String("selector")]; ok { | ||||||
|  | 			n := s(selector.Registry(*c.opts.Registry)) | ||||||
|  | 			c.opts.Selector = &n | ||||||
|  | 		} else { | ||||||
|  | 			return fmt.Errorf("Selector %s not found", ctx.String("selector")) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// No server option here. Should there be? | ||||||
|  | 		clientOpts = append(clientOpts, client.Selector(*c.opts.Selector)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Set the transport | ||||||
|  | 	if len(ctx.String("transport")) > 0 { | ||||||
|  | 		if t, ok := c.opts.Transports[ctx.String("transport")]; ok { | ||||||
|  | 			n := t(strings.Split(ctx.String("transport_address"), ",")) | ||||||
|  | 			c.opts.Transport = &n | ||||||
|  | 		} else { | ||||||
|  | 			return fmt.Errorf("Transport %s not found", ctx.String("transport")) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		serverOpts = append(serverOpts, server.Transport(*c.opts.Transport)) | ||||||
|  | 		clientOpts = append(clientOpts, client.Transport(*c.opts.Transport)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Parse the server options | ||||||
| 	metadata := make(map[string]string) | 	metadata := make(map[string]string) | ||||||
| 	for _, d := range c.StringSlice("server_metadata") { | 	for _, d := range ctx.StringSlice("server_metadata") { | ||||||
| 		var key, val string | 		var key, val string | ||||||
| 		parts := strings.Split(d, "=") | 		parts := strings.Split(d, "=") | ||||||
| 		key = parts[0] | 		key = parts[0] | ||||||
| @@ -188,47 +291,59 @@ func Setup(c *cli.Context) error { | |||||||
| 		metadata[key] = val | 		metadata[key] = val | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	server.DefaultServer = server.NewServer( | 	if len(metadata) > 0 { | ||||||
| 		server.Name(c.String("server_name")), | 		serverOpts = append(serverOpts, server.Metadata(metadata)) | ||||||
| 		server.Version(c.String("server_version")), | 	} | ||||||
| 		server.Id(c.String("server_id")), |  | ||||||
| 		server.Address(c.String("server_address")), |  | ||||||
| 		server.Advertise(c.String("server_advertise")), |  | ||||||
| 		server.Metadata(metadata), |  | ||||||
| 	) |  | ||||||
|  |  | ||||||
| 	client.DefaultClient = client.NewClient() | 	if len(ctx.String("server_name")) > 0 { | ||||||
|  | 		serverOpts = append(serverOpts, server.Name(ctx.String("server_name"))) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(ctx.String("server_version")) > 0 { | ||||||
|  | 		serverOpts = append(serverOpts, server.Version(ctx.String("server_version"))) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(ctx.String("server_id")) > 0 { | ||||||
|  | 		serverOpts = append(serverOpts, server.Id(ctx.String("server_id"))) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(ctx.String("server_address")) > 0 { | ||||||
|  | 		serverOpts = append(serverOpts, server.Address(ctx.String("server_address"))) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(ctx.String("server_advertise")) > 0 { | ||||||
|  | 		serverOpts = append(serverOpts, server.Advertise(ctx.String("server_advertise"))) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// We have some command line opts for the server. | ||||||
|  | 	// Lets set it up | ||||||
|  | 	if len(serverOpts) > 0 { | ||||||
|  | 		(*c.opts.Server).Init(serverOpts...) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Use an init option? | ||||||
|  | 	if len(clientOpts) > 0 { | ||||||
|  | 		(*c.opts.Client).Init(clientOpts...) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func Init() { | func (c *cmd) Init(opts ...Option) error { | ||||||
| 	cli.AppHelpTemplate = ` | 	for _, o := range opts { | ||||||
| GLOBAL OPTIONS: | 		o(&c.opts) | ||||||
|    {{range .Flags}}{{.}} |  | ||||||
|    {{end}} |  | ||||||
| ` |  | ||||||
|  |  | ||||||
| 	cli.HelpPrinter = func(writer io.Writer, templ string, data interface{}) { |  | ||||||
| 		w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0) |  | ||||||
| 		t := template.Must(template.New("help").Parse(templ)) |  | ||||||
| 		err := t.Execute(w, data) |  | ||||||
| 		if err != nil { |  | ||||||
| 			panic(err) |  | ||||||
| 	} | 	} | ||||||
| 		w.Flush() | 	c.app.Name = c.opts.Name | ||||||
| 		os.Exit(2) | 	c.app.Version = c.opts.Version | ||||||
| 	} | 	c.app.Usage = c.opts.Description | ||||||
|  | 	c.app.RunAndExitOnError() | ||||||
| 	app := cli.NewApp() | 	return nil | ||||||
| 	app.HideVersion = true | } | ||||||
| 	app.Usage = "a go micro app" |  | ||||||
| 	app.Action = func(c *cli.Context) { | func Init(opts ...Option) error { | ||||||
| 		for _, action := range Actions { | 	return DefaultCmd.Init(opts...) | ||||||
| 			action(c) | } | ||||||
| 		} |  | ||||||
| 	} | func NewCmd(opts ...Option) Cmd { | ||||||
| 	app.Before = Setup | 	return newCmd(opts...) | ||||||
| 	app.Flags = Flags |  | ||||||
| 	app.RunAndExitOnError() |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										115
									
								
								cmd/options.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								cmd/options.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | |||||||
|  | package cmd | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/micro/go-micro/broker" | ||||||
|  | 	"github.com/micro/go-micro/client" | ||||||
|  | 	"github.com/micro/go-micro/registry" | ||||||
|  | 	"github.com/micro/go-micro/selector" | ||||||
|  | 	"github.com/micro/go-micro/server" | ||||||
|  | 	"github.com/micro/go-micro/transport" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Options struct { | ||||||
|  | 	// For the Command Line itself | ||||||
|  | 	Name        string | ||||||
|  | 	Description string | ||||||
|  | 	Version     string | ||||||
|  |  | ||||||
|  | 	// We need pointers to things so we can swap them out if needed. | ||||||
|  | 	Broker    *broker.Broker | ||||||
|  | 	Registry  *registry.Registry | ||||||
|  | 	Selector  *selector.Selector | ||||||
|  | 	Transport *transport.Transport | ||||||
|  | 	Client    *client.Client | ||||||
|  | 	Server    *server.Server | ||||||
|  |  | ||||||
|  | 	Brokers    map[string]func([]string, ...broker.Option) broker.Broker | ||||||
|  | 	Registries map[string]func([]string, ...registry.Option) registry.Registry | ||||||
|  | 	Selectors  map[string]func(...selector.Option) selector.Selector | ||||||
|  | 	Transports map[string]func([]string, ...transport.Option) transport.Transport | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Command line Name | ||||||
|  | func Name(n string) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Name = n | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Command line Description | ||||||
|  | func Description(d string) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Description = d | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Command line Version | ||||||
|  | func Version(v string) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Version = v | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Broker(b *broker.Broker) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Broker = b | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Selector(s *selector.Selector) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Selector = s | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Registry(r *registry.Registry) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Registry = r | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Transport(t *transport.Transport) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Transport = t | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Client(c *client.Client) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Client = c | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Server(s *server.Server) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Server = s | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // New broker func | ||||||
|  | func NewBroker(name string, b func([]string, ...broker.Option) broker.Broker) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Brokers[name] = b | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // New registry func | ||||||
|  | func NewRegistry(name string, r func([]string, ...registry.Option) registry.Registry) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Registries[name] = r | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // New selector func | ||||||
|  | func NewSelector(name string, s func(...selector.Option) selector.Selector) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Selectors[name] = s | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // New transport func | ||||||
|  | func NewTransport(name string, t func([]string, ...transport.Option) transport.Transport) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Transports[name] = t | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -6,40 +6,12 @@ import ( | |||||||
| 	"github.com/micro/go-micro/examples/server/handler" | 	"github.com/micro/go-micro/examples/server/handler" | ||||||
| 	"github.com/micro/go-micro/examples/server/subscriber" | 	"github.com/micro/go-micro/examples/server/subscriber" | ||||||
| 	"github.com/micro/go-micro/server" | 	"github.com/micro/go-micro/server" | ||||||
| 	"golang.org/x/net/context" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func logWrapper(fn server.HandlerFunc) server.HandlerFunc { |  | ||||||
| 	return func(ctx context.Context, req server.Request, rsp interface{}) error { |  | ||||||
| 		log.Infof("[Log Wrapper] Before serving request method: %v", req.Method()) |  | ||||||
| 		err := fn(ctx, req, rsp) |  | ||||||
| 		log.Infof("[Log Wrapper] After serving request") |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func logSubWrapper(fn server.SubscriberFunc) server.SubscriberFunc { |  | ||||||
| 	return func(ctx context.Context, req server.Publication) error { |  | ||||||
| 		log.Infof("[Log Sub Wrapper] Before serving publication topic: %v", req.Topic()) |  | ||||||
| 		err := fn(ctx, req) |  | ||||||
| 		log.Infof("[Log Sub Wrapper] After serving publication") |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func main() { | func main() { | ||||||
| 	// optionally setup command line usage | 	// optionally setup command line usage | ||||||
| 	cmd.Init() | 	cmd.Init() | ||||||
|  |  | ||||||
| 	md := server.DefaultOptions().Metadata |  | ||||||
| 	md["datacenter"] = "local" |  | ||||||
|  |  | ||||||
| 	server.DefaultServer = server.NewServer( |  | ||||||
| 		server.WrapHandler(logWrapper), |  | ||||||
| 		server.WrapSubscriber(logSubWrapper), |  | ||||||
| 		server.Metadata(md), |  | ||||||
| 	) |  | ||||||
|  |  | ||||||
| 	// Initialise Server | 	// Initialise Server | ||||||
| 	server.Init( | 	server.Init( | ||||||
| 		server.Name("go.micro.srv.example"), | 		server.Name("go.micro.srv.example"), | ||||||
|   | |||||||
							
								
								
									
										78
									
								
								examples/server/wrapper/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								examples/server/wrapper/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	log "github.com/golang/glog" | ||||||
|  | 	"github.com/micro/go-micro/cmd" | ||||||
|  | 	"github.com/micro/go-micro/examples/server/handler" | ||||||
|  | 	"github.com/micro/go-micro/examples/server/subscriber" | ||||||
|  | 	"github.com/micro/go-micro/server" | ||||||
|  | 	"golang.org/x/net/context" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func logWrapper(fn server.HandlerFunc) server.HandlerFunc { | ||||||
|  | 	return func(ctx context.Context, req server.Request, rsp interface{}) error { | ||||||
|  | 		log.Infof("[Log Wrapper] Before serving request method: %v", req.Method()) | ||||||
|  | 		err := fn(ctx, req, rsp) | ||||||
|  | 		log.Infof("[Log Wrapper] After serving request") | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func logSubWrapper(fn server.SubscriberFunc) server.SubscriberFunc { | ||||||
|  | 	return func(ctx context.Context, req server.Publication) error { | ||||||
|  | 		log.Infof("[Log Sub Wrapper] Before serving publication topic: %v", req.Topic()) | ||||||
|  | 		err := fn(ctx, req) | ||||||
|  | 		log.Infof("[Log Sub Wrapper] After serving publication") | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	// optionally setup command line usage | ||||||
|  | 	cmd.Init() | ||||||
|  |  | ||||||
|  | 	md := server.DefaultOptions().Metadata | ||||||
|  | 	md["datacenter"] = "local" | ||||||
|  |  | ||||||
|  | 	server.DefaultServer = server.NewServer( | ||||||
|  | 		server.WrapHandler(logWrapper), | ||||||
|  | 		server.WrapSubscriber(logSubWrapper), | ||||||
|  | 		server.Metadata(md), | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	// Initialise Server | ||||||
|  | 	server.Init( | ||||||
|  | 		server.Name("go.micro.srv.example"), | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	// Register Handlers | ||||||
|  | 	server.Handle( | ||||||
|  | 		server.NewHandler( | ||||||
|  | 			new(handler.Example), | ||||||
|  | 		), | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	// Register Subscribers | ||||||
|  | 	if err := server.Subscribe( | ||||||
|  | 		server.NewSubscriber( | ||||||
|  | 			"topic.go.micro.srv.example", | ||||||
|  | 			new(subscriber.Example), | ||||||
|  | 		), | ||||||
|  | 	); err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err := server.Subscribe( | ||||||
|  | 		server.NewSubscriber( | ||||||
|  | 			"topic.go.micro.srv.example", | ||||||
|  | 			subscriber.Handler, | ||||||
|  | 		), | ||||||
|  | 	); err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Run server | ||||||
|  | 	if err := server.Run(); err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								examples/service/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								examples/service/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | # Service | ||||||
|  |  | ||||||
|  | This is an example of creating a micro service using the top level interface. | ||||||
|  |  | ||||||
|  | ## Prereqs | ||||||
|  |  | ||||||
|  | Micro services need a discovery system so they can find each other. Micro uses consul by default but  | ||||||
|  | its easily swapped out with etcd, kubernetes, or various other systems. We'll run consul for convenience. | ||||||
|  |  | ||||||
|  | 1. Follow the install instructions - [https://www.consul.io/intro/getting-started/install.html](https://www.consul.io/intro/getting-started/install.html) | ||||||
|  |  | ||||||
|  | 2. Run Consul | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | $ consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Run the example | ||||||
|  |  | ||||||
|  | 1. Get the service | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | go get github.com/micro/go-micro/examples/service | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 2. Run the server | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | $GOPATH/bin/service | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 3. Run the client | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | $GOPATH/bin/service --client | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | And that's all there is to it. | ||||||
							
								
								
									
										85
									
								
								examples/service/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								examples/service/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  |  | ||||||
|  | 	"github.com/micro/cli" | ||||||
|  | 	micro "github.com/micro/go-micro" | ||||||
|  | 	proto "github.com/micro/go-micro/examples/service/proto" | ||||||
|  | 	"golang.org/x/net/context" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  | ||||||
|  | Example usage of top level service initialisation | ||||||
|  |  | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | type Greeter struct{} | ||||||
|  |  | ||||||
|  | func (g *Greeter) Hello(ctx context.Context, req *proto.HelloRequest, rsp *proto.HelloResponse) error { | ||||||
|  | 	rsp.Greeting = "Hello " + req.Name | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Setup and the client | ||||||
|  | func client(service micro.Service) { | ||||||
|  | 	// Create new greeter client | ||||||
|  | 	greeter := proto.NewGreeterClient("greeter", service.Client()) | ||||||
|  |  | ||||||
|  | 	// Call the greeter | ||||||
|  | 	rsp, err := greeter.Hello(context.TODO(), &proto.HelloRequest{Name: "John"}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Println(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Print response | ||||||
|  | 	fmt.Println(rsp.Greeting) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	// Create a new service. Optionally include some options here. | ||||||
|  | 	service := micro.NewService( | ||||||
|  | 		micro.Name("greeter"), | ||||||
|  | 		micro.Version("latest"), | ||||||
|  | 		micro.Metadata(map[string]string{ | ||||||
|  | 			"type": "helloworld", | ||||||
|  | 		}), | ||||||
|  |  | ||||||
|  | 		// Setup some flags. Specify --client to run the client | ||||||
|  |  | ||||||
|  | 		// Add runtime flags | ||||||
|  | 		// We could do this below too | ||||||
|  | 		micro.Flags(cli.BoolFlag{ | ||||||
|  | 			Name:  "client", | ||||||
|  | 			Usage: "Launch the client", | ||||||
|  | 		}), | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	// Init will parse the command line flags. Any flags set will | ||||||
|  | 	// override the above settings. Options defined here will | ||||||
|  | 	// override anything set on the command line. | ||||||
|  | 	service.Init( | ||||||
|  | 		// Add runtime action | ||||||
|  | 		// We could actually do this above | ||||||
|  | 		micro.Action(func(c *cli.Context) { | ||||||
|  | 			if c.Bool("client") { | ||||||
|  | 				client(service) | ||||||
|  | 				os.Exit(0) | ||||||
|  | 			} | ||||||
|  | 		}), | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	// By default we'll run the server unless the flags catch us | ||||||
|  |  | ||||||
|  | 	// Setup the server | ||||||
|  |  | ||||||
|  | 	// Register handler | ||||||
|  | 	proto.RegisterGreeterHandler(service.Server(), new(Greeter)) | ||||||
|  |  | ||||||
|  | 	// Run the server | ||||||
|  | 	if err := service.Run(); err != nil { | ||||||
|  | 		fmt.Println(err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										124
									
								
								examples/service/proto/greeter.pb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								examples/service/proto/greeter.pb.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,124 @@ | |||||||
|  | // Code generated by protoc-gen-go. | ||||||
|  | // source: go-micro/examples/service/proto/greeter.proto | ||||||
|  | // DO NOT EDIT! | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | Package greeter is a generated protocol buffer package. | ||||||
|  |  | ||||||
|  | It is generated from these files: | ||||||
|  | 	go-micro/examples/service/proto/greeter.proto | ||||||
|  |  | ||||||
|  | It has these top-level messages: | ||||||
|  | 	HelloRequest | ||||||
|  | 	HelloResponse | ||||||
|  | */ | ||||||
|  | package greeter | ||||||
|  |  | ||||||
|  | import proto "github.com/golang/protobuf/proto" | ||||||
|  | import fmt "fmt" | ||||||
|  | import math "math" | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	client "github.com/micro/go-micro/client" | ||||||
|  | 	server "github.com/micro/go-micro/server" | ||||||
|  | 	context "golang.org/x/net/context" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Reference imports to suppress errors if they are not otherwise used. | ||||||
|  | var _ = proto.Marshal | ||||||
|  | var _ = fmt.Errorf | ||||||
|  | var _ = math.Inf | ||||||
|  |  | ||||||
|  | type HelloRequest struct { | ||||||
|  | 	Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *HelloRequest) Reset()                    { *m = HelloRequest{} } | ||||||
|  | func (m *HelloRequest) String() string            { return proto.CompactTextString(m) } | ||||||
|  | func (*HelloRequest) ProtoMessage()               {} | ||||||
|  | func (*HelloRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } | ||||||
|  |  | ||||||
|  | type HelloResponse struct { | ||||||
|  | 	Greeting string `protobuf:"bytes,2,opt,name=greeting" json:"greeting,omitempty"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m *HelloResponse) Reset()                    { *m = HelloResponse{} } | ||||||
|  | func (m *HelloResponse) String() string            { return proto.CompactTextString(m) } | ||||||
|  | func (*HelloResponse) ProtoMessage()               {} | ||||||
|  | func (*HelloResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } | ||||||
|  |  | ||||||
|  | func init() { | ||||||
|  | 	proto.RegisterType((*HelloRequest)(nil), "HelloRequest") | ||||||
|  | 	proto.RegisterType((*HelloResponse)(nil), "HelloResponse") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Reference imports to suppress errors if they are not otherwise used. | ||||||
|  | var _ context.Context | ||||||
|  | var _ client.Option | ||||||
|  | var _ server.Option | ||||||
|  |  | ||||||
|  | // Client API for Greeter service | ||||||
|  |  | ||||||
|  | type GreeterClient interface { | ||||||
|  | 	Hello(ctx context.Context, in *HelloRequest, opts ...client.CallOption) (*HelloResponse, error) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type greeterClient struct { | ||||||
|  | 	c           client.Client | ||||||
|  | 	serviceName string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewGreeterClient(serviceName string, c client.Client) GreeterClient { | ||||||
|  | 	if c == nil { | ||||||
|  | 		c = client.NewClient() | ||||||
|  | 	} | ||||||
|  | 	if len(serviceName) == 0 { | ||||||
|  | 		serviceName = "greeter" | ||||||
|  | 	} | ||||||
|  | 	return &greeterClient{ | ||||||
|  | 		c:           c, | ||||||
|  | 		serviceName: serviceName, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *greeterClient) Hello(ctx context.Context, in *HelloRequest, opts ...client.CallOption) (*HelloResponse, error) { | ||||||
|  | 	req := c.c.NewRequest(c.serviceName, "Greeter.Hello", in) | ||||||
|  | 	out := new(HelloResponse) | ||||||
|  | 	err := c.c.Call(ctx, req, out, opts...) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return out, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Server API for Greeter service | ||||||
|  |  | ||||||
|  | type GreeterHandler interface { | ||||||
|  | 	Hello(context.Context, *HelloRequest, *HelloResponse) error | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func RegisterGreeterHandler(s server.Server, hdlr GreeterHandler) { | ||||||
|  | 	s.Handle(s.NewHandler(&Greeter{hdlr})) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type Greeter struct { | ||||||
|  | 	GreeterHandler | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (h *Greeter) Hello(ctx context.Context, in *HelloRequest, out *HelloResponse) error { | ||||||
|  | 	return h.GreeterHandler.Hello(ctx, in, out) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var fileDescriptor0 = []byte{ | ||||||
|  | 	// 153 bytes of a gzipped FileDescriptorProto | ||||||
|  | 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xd2, 0x4d, 0xcf, 0xd7, 0xcd, | ||||||
|  | 	0xcd, 0x4c, 0x2e, 0xca, 0xd7, 0x4f, 0xad, 0x48, 0xcc, 0x2d, 0xc8, 0x49, 0x2d, 0xd6, 0x2f, 0x4e, | ||||||
|  | 	0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0xd7, 0x4f, 0x2f, 0x4a, 0x4d, | ||||||
|  | 	0x2d, 0x49, 0x2d, 0xd2, 0x03, 0xf3, 0x94, 0x64, 0xb8, 0x78, 0x3c, 0x52, 0x73, 0x72, 0xf2, 0x83, | ||||||
|  | 	0x52, 0x0b, 0x4b, 0x53, 0x8b, 0x4b, 0x84, 0x78, 0xb8, 0x58, 0xf2, 0x12, 0x73, 0x53, 0x25, 0x18, | ||||||
|  | 	0x15, 0x18, 0x35, 0x38, 0x95, 0x14, 0xb9, 0x78, 0xa1, 0xb2, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, | ||||||
|  | 	0x42, 0x02, 0x5c, 0x1c, 0x60, 0xfd, 0x99, 0x79, 0xe9, 0x12, 0x4c, 0x20, 0x25, 0x46, 0xc6, 0x5c, | ||||||
|  | 	0xec, 0xee, 0x10, 0x13, 0x85, 0x34, 0xb8, 0x58, 0xc1, 0xaa, 0x85, 0x78, 0xf5, 0x90, 0xcd, 0x94, | ||||||
|  | 	0xe2, 0xd3, 0x43, 0x31, 0x44, 0x89, 0x21, 0x89, 0x0d, 0x6c, 0xb9, 0x31, 0x20, 0x00, 0x00, 0xff, | ||||||
|  | 	0xff, 0x0f, 0xa9, 0x59, 0xb3, 0xad, 0x00, 0x00, 0x00, | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								examples/service/proto/greeter.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								examples/service/proto/greeter.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | syntax = "proto3"; | ||||||
|  |  | ||||||
|  | service Greeter { | ||||||
|  | 	rpc Hello(HelloRequest) returns (HelloResponse) {} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | message HelloRequest { | ||||||
|  | 	string name = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | message HelloResponse { | ||||||
|  | 	string greeting = 2; | ||||||
|  | } | ||||||
							
								
								
									
										47
									
								
								go-micro.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								go-micro.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | /* | ||||||
|  | Go micro provides a pluggable library to build microservices. | ||||||
|  |  | ||||||
|  | 	import ( | ||||||
|  | 		micro "github.com/micro/go-micro" | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	service := micro.NewService() | ||||||
|  | 	h := service.Server().NewHandler(&Greeter{}) | ||||||
|  | 	service.Server().Handle(h) | ||||||
|  | 	service.Run() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	req := service.Client().NewRequest(service, method, request) | ||||||
|  | 	rsp := response{} | ||||||
|  | 	err := service.Client().Call(req, rsp) | ||||||
|  |  | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | package micro | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/micro/go-micro/client" | ||||||
|  | 	"github.com/micro/go-micro/server" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Service is an interface that wraps the lower level libraries | ||||||
|  | // within go-micro. Its a convenience method for building | ||||||
|  | // and initialising services. | ||||||
|  | type Service interface { | ||||||
|  | 	Init(...Option) | ||||||
|  | 	Options() Options | ||||||
|  | 	Client() client.Client | ||||||
|  | 	Server() server.Server | ||||||
|  | 	Run() error | ||||||
|  | 	String() string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type Option func(*Options) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	HeaderPrefix = "X-Micro-" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func NewService(opts ...Option) Service { | ||||||
|  | 	return newService(opts...) | ||||||
|  | } | ||||||
							
								
								
									
										130
									
								
								options.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								options.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,130 @@ | |||||||
|  | package micro | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/micro/cli" | ||||||
|  | 	"github.com/micro/go-micro/broker" | ||||||
|  | 	"github.com/micro/go-micro/client" | ||||||
|  | 	"github.com/micro/go-micro/cmd" | ||||||
|  | 	"github.com/micro/go-micro/registry" | ||||||
|  | 	"github.com/micro/go-micro/server" | ||||||
|  | 	"github.com/micro/go-micro/transport" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Options struct { | ||||||
|  | 	Broker    broker.Broker | ||||||
|  | 	Cmd       cmd.Cmd | ||||||
|  | 	Client    client.Client | ||||||
|  | 	Server    server.Server | ||||||
|  | 	Registry  registry.Registry | ||||||
|  | 	Transport transport.Transport | ||||||
|  |  | ||||||
|  | 	// Before and After funcs | ||||||
|  | 	BeforeStart []func() error | ||||||
|  | 	AfterStop   []func() error | ||||||
|  |  | ||||||
|  | 	// Alternative options for those implementing the interface | ||||||
|  | 	Options map[string]string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func newOptions(opts ...Option) Options { | ||||||
|  | 	opt := Options{ | ||||||
|  | 		Broker:    broker.DefaultBroker, | ||||||
|  | 		Cmd:       cmd.DefaultCmd, | ||||||
|  | 		Client:    client.DefaultClient, | ||||||
|  | 		Server:    server.DefaultServer, | ||||||
|  | 		Registry:  registry.DefaultRegistry, | ||||||
|  | 		Transport: transport.DefaultTransport, | ||||||
|  | 		Options:   map[string]string{}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		o(&opt) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return opt | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Broker(b broker.Broker) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Broker = b | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Cmd(c cmd.Cmd) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Cmd = c | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Client(c client.Client) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Client = c | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Server(s server.Server) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Server = s | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Registry(r registry.Registry) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Registry = r | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Transport(t transport.Transport) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Transport = t | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Convenience options | ||||||
|  |  | ||||||
|  | // Name of the service | ||||||
|  | func Name(n string) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Server.Init(server.Name(n)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Version of the service | ||||||
|  | func Version(v string) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Server.Init(server.Version(v)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Metadata associated with the service | ||||||
|  | func Metadata(md map[string]string) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Server.Init(server.Metadata(md)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Flags(flags ...cli.Flag) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Cmd.App().Flags = append(o.Cmd.App().Flags, flags...) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Action(a func(*cli.Context)) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Cmd.App().Action = a | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Before and Afters | ||||||
|  |  | ||||||
|  | func BeforeStart(fn func() error) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.BeforeStart = append(o.BeforeStart, fn) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func AfterStop(fn func() error) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.AfterStop = append(o.AfterStop, fn) | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -27,7 +27,7 @@ type blackListSelector struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| 	cmd.Selectors["blacklist"] = NewSelector | 	cmd.DefaultSelectors["blacklist"] = NewSelector | ||||||
| 	rand.Seed(time.Now().Unix()) | 	rand.Seed(time.Now().Unix()) | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| 	cmd.Selectors["random"] = NewSelector | 	cmd.DefaultSelectors["random"] = NewSelector | ||||||
| } | } | ||||||
|  |  | ||||||
| func NewSelector(opts ...selector.Option) selector.Selector { | func NewSelector(opts ...selector.Option) selector.Selector { | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ type roundRobinSelector struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| 	cmd.Selectors["roundrobin"] = NewSelector | 	cmd.DefaultSelectors["roundrobin"] = NewSelector | ||||||
| } | } | ||||||
|  |  | ||||||
| func (r *roundRobinSelector) Select(service string, opts ...selector.SelectOption) (selector.Next, error) { | func (r *roundRobinSelector) Select(service string, opts ...selector.SelectOption) (selector.Next, error) { | ||||||
|   | |||||||
| @@ -105,15 +105,13 @@ func (s *rpcServer) Options() Options { | |||||||
| 	return opts | 	return opts | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *rpcServer) Init(opts ...Option) { | func (s *rpcServer) Init(opts ...Option) error { | ||||||
| 	s.Lock() | 	s.Lock() | ||||||
| 	for _, opt := range opts { | 	for _, opt := range opts { | ||||||
| 		opt(&s.opts) | 		opt(&s.opts) | ||||||
| 	} | 	} | ||||||
| 	if len(s.opts.Id) == 0 { |  | ||||||
| 		s.opts.Id = s.opts.Name + "-" + DefaultId |  | ||||||
| 	} |  | ||||||
| 	s.Unlock() | 	s.Unlock() | ||||||
|  | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *rpcServer) NewHandler(h interface{}) Handler { | func (s *rpcServer) NewHandler(h interface{}) Handler { | ||||||
| @@ -187,7 +185,7 @@ func (s *rpcServer) Register() error { | |||||||
|  |  | ||||||
| 	// register service | 	// register service | ||||||
| 	node := ®istry.Node{ | 	node := ®istry.Node{ | ||||||
| 		Id:       config.Id, | 		Id:       config.Name + "-" + config.Id, | ||||||
| 		Address:  addr, | 		Address:  addr, | ||||||
| 		Port:     port, | 		Port:     port, | ||||||
| 		Metadata: config.Metadata, | 		Metadata: config.Metadata, | ||||||
| @@ -260,7 +258,7 @@ func (s *rpcServer) Deregister() error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	node := ®istry.Node{ | 	node := ®istry.Node{ | ||||||
| 		Id:      config.Id, | 		Id:      config.Name + "-" + config.Id, | ||||||
| 		Address: addr, | 		Address: addr, | ||||||
| 		Port:    port, | 		Port:    port, | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -40,7 +40,7 @@ import ( | |||||||
|  |  | ||||||
| type Server interface { | type Server interface { | ||||||
| 	Options() Options | 	Options() Options | ||||||
| 	Init(...Option) | 	Init(...Option) error | ||||||
| 	Handle(Handler) error | 	Handle(Handler) error | ||||||
| 	NewHandler(interface{}) Handler | 	NewHandler(interface{}) Handler | ||||||
| 	NewSubscriber(string, interface{}) Subscriber | 	NewSubscriber(string, interface{}) Subscriber | ||||||
|   | |||||||
							
								
								
									
										120
									
								
								service.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								service.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,120 @@ | |||||||
|  | package micro | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"os" | ||||||
|  | 	"os/signal" | ||||||
|  | 	"syscall" | ||||||
|  |  | ||||||
|  | 	"github.com/micro/go-micro/client" | ||||||
|  | 	"github.com/micro/go-micro/context" | ||||||
|  | 	"github.com/micro/go-micro/server" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type service struct { | ||||||
|  | 	opts Options | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func newService(opts ...Option) Service { | ||||||
|  | 	options := newOptions(opts...) | ||||||
|  |  | ||||||
|  | 	options.Client = &clientWrapper{ | ||||||
|  | 		options.Client, | ||||||
|  | 		context.Metadata{ | ||||||
|  | 			HeaderPrefix + "From-Service": options.Server.Options().Name, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return &service{ | ||||||
|  | 		opts: options, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *service) Init(opts ...Option) { | ||||||
|  | 	// We might get more command flags or the action here | ||||||
|  | 	// This is pretty ugly, find a better way | ||||||
|  | 	options := newOptions() | ||||||
|  | 	options.Cmd = s.opts.Cmd | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		o(&options) | ||||||
|  | 	} | ||||||
|  | 	s.opts.Cmd = options.Cmd | ||||||
|  |  | ||||||
|  | 	// Initialise the command flags, overriding new service | ||||||
|  | 	s.opts.Cmd.Init() | ||||||
|  |  | ||||||
|  | 	// Update any options to override command flags | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		o(&s.opts) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *service) Options() Options { | ||||||
|  | 	return s.opts | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *service) Client() client.Client { | ||||||
|  | 	return s.opts.Client | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *service) Server() server.Server { | ||||||
|  | 	return s.opts.Server | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *service) String() string { | ||||||
|  | 	return "go-micro" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *service) Start() error { | ||||||
|  | 	for _, fn := range s.opts.BeforeStart { | ||||||
|  | 		if err := fn(); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err := s.opts.Server.Start(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err := s.opts.Server.Register(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *service) Stop() error { | ||||||
|  | 	if err := s.opts.Server.Deregister(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err := s.opts.Server.Stop(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var gerr error | ||||||
|  | 	for _, fn := range s.opts.AfterStop { | ||||||
|  | 		if err := fn(); err != nil { | ||||||
|  | 			// should we bail if it fails? | ||||||
|  | 			// other funcs will not be executed | ||||||
|  | 			// seems wrong | ||||||
|  | 			gerr = err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return gerr | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *service) Run() error { | ||||||
|  | 	if err := s.Start(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ch := make(chan os.Signal, 1) | ||||||
|  | 	signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL) | ||||||
|  | 	<-ch | ||||||
|  |  | ||||||
|  | 	if err := s.Stop(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
							
								
								
									
										28
									
								
								wrapper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								wrapper.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | package micro | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/micro/go-micro/client" | ||||||
|  | 	cx "github.com/micro/go-micro/context" | ||||||
|  |  | ||||||
|  | 	"golang.org/x/net/context" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type clientWrapper struct { | ||||||
|  | 	client.Client | ||||||
|  | 	headers cx.Metadata | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *clientWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error { | ||||||
|  | 	ctx = cx.WithMetadata(ctx, c.headers) | ||||||
|  | 	return c.Client.Call(ctx, req, rsp, opts...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *clientWrapper) Stream(ctx context.Context, req client.Request, opts ...client.CallOption) (client.Streamer, error) { | ||||||
|  | 	ctx = cx.WithMetadata(ctx, c.headers) | ||||||
|  | 	return c.Client.Stream(ctx, req, opts...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *clientWrapper) Publish(ctx context.Context, p client.Publication, opts ...client.PublishOption) error { | ||||||
|  | 	ctx = cx.WithMetadata(ctx, c.headers) | ||||||
|  | 	return c.Client.Publish(ctx, p, opts...) | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user