Example #1
0
func main() {
	flag.Parse()

	channel, err := tchannel.NewChannel("worker", &tchannel.ChannelOptions{
	// Logger: tchannel.NewLevelLogger(tchannel.SimpleLogger, tchannel.LogLevelWarn),
	})
	if err != nil {
		log.Fatalf("could not create channel: %v", err)
	}

	worker := newWorker(*hostport, channel)
	server := thrift.NewServer(channel.GetSubChannel("pingpong"))
	server.Register(pingpong.NewTChanPingPongServer(worker))

	if err := channel.ListenAndServe(*hostport); err != nil {
		log.Fatalf("could not listen on hostport: %v", err)
	}

	bsopts := new(ringpop.BootstrapOptions)
	bsopts.File = *hostfile
	bsopts.Stopped = true
	if _, err := worker.ringpop.Bootstrap(bsopts); err != nil {
		log.Fatalf("could not bootstrap ringpop: %v", err)
	}

	// block
	select {}
}
Example #2
0
func main() {
	flag.Parse()

	channel, err := tchannel.NewChannel("pingpong", &tchannel.ChannelOptions{})
	if err != nil {
		log.Fatalf("could not create channel: %v", err)
	}
	server := thrift.NewServer(channel)

	// The actual service implementation
	worker := newWorker(*hostport, channel)
	// wrap the PingPong worker by a ringpop adapter for routing RPC calls
	// NewRingpopPingPongAdapter is in the package containing the generated code
	// Its name is derived from the thrift service name as follows: `NewRingpop[Service Name]Adapter`
	adapter, err := gen.NewRingpopPingPongAdapter(worker, worker.ringpop, channel,
		// PingPongConfiguration contains the configuration for ringpop forwarding regaring this service
		// The name is derived as follows `[Service Name]Configuration`
		gen.PingPongConfiguration{
			// The ping member of the configuration refers to the Ping endpoint within the service.
			// Configuring an endpoint is optional and unconfigured endpoints will work but not be
			// forwarded to a different ringpop node during invocation
			// The name of the configuration struct passed in here is derived as follows:
			// `[Service Name][Endpoint Name]Configuration`
			Ping: &gen.PingPongPingConfiguration{
				// The configuration structs only member is the Key closure. The purpose of this closure
				// is to return the key used for ringpop sharding and forwarding. Calls that are sharded
				// on the same key are guaranteed to be forwarded to the same node.
				// The input signature for this closure is the same as the signature for your
				// implementation. The output is always the tuple (shardKey string, err error).
				Key: func(ctx thrift.Context, request *gen.Ping) (shardKey string, err error) {
					// The body of the Key closure can perform whatever logic is needed to come to a
					// meaningful shardKey for the the request
					if request == nil {
						return "", errors.New("missing request in call to Ping")
					}

					// Here we route the ping's for the same key to the same machine
					return request.Key, nil
				},
			},
		},
	)
	if err != nil {
		log.Fatalf("unable to wrap the worker: %q", err)
	}

	// now pass the ringpop adapter into the TChannel Thrift server for the PingPong Service
	server.Register(gen.NewTChanPingPongServer(adapter))

	if err := channel.ListenAndServe(*hostport); err != nil {
		log.Fatalf("could not listen on hostport: %v", err)
	}

	bsopts := new(swim.BootstrapOptions)
	bsopts.File = *hostfile
	bsopts.Stopped = true
	if _, err := worker.ringpop.Bootstrap(bsopts); err != nil {
		log.Fatalf("could not bootstrap ringpop: %v", err)
	}

	// block
	select {}
}