func (s *SRVLoader) getConfig() (*pb.NodeConfig, error) { nconfig := &pb.NodeConfig{} var opts []grpc.DialOption var creds credentials.TransportAuthenticator creds = credentials.NewTLS(&tls.Config{ InsecureSkipVerify: true, }) opts = append(opts, grpc.WithTransportCredentials(creds)) conn, err := grpc.Dial(s.SyndicateURL, opts...) if err != nil { return nconfig, fmt.Errorf("Failed to dial ring server for config: %s", err) } defer conn.Close() client := pb.NewSyndicateClient(conn) ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) rr := &pb.RegisterRequest{} rr.Hostname, _ = os.Hostname() addrs, _ := net.InterfaceAddrs() for k, _ := range addrs { rr.Addrs = append(rr.Addrs, addrs[k].String()) } rr.Hardware, err = GetHardwareProfile() if err != nil { return nconfig, err } rr.Tiers = []string{rr.Hostname} nconfig, err = client.RegisterNode(ctx, rr) return nconfig, err }
func New() (*SyndClient, error) { var err error var opts []grpc.DialOption var creds credentials.TransportAuthenticator creds = credentials.NewTLS(&tls.Config{ InsecureSkipVerify: true, }) opts = append(opts, grpc.WithTransportCredentials(creds)) s := SyndClient{} s.conn, err = grpc.Dial(*syndicateAddr, opts...) if err != nil { return &SyndClient{}, fmt.Errorf("Failed to dial ring server for config: %v", err) } s.client = pb.NewSyndicateClient(s.conn) return &s, nil }
func (rs *ReplValueStore) ringServerConnector(exitChan chan struct{}) { sleeperTicks := 2 sleeperTicker := time.NewTicker(time.Second) sleeper := func() { for i := sleeperTicks; i > 0; i-- { select { case <-exitChan: break case <-sleeperTicker.C: } } if sleeperTicks < 60 { sleeperTicks *= 2 } } for { select { case <-exitChan: break default: } ringServer := rs.ringServer if ringServer == "" { var err error ringServer, err = oort.GetRingServer("value") if err != nil { rs.logError("replValueStore: error resolving ring service: %s", err) sleeper() continue } } conn, err := grpc.Dial(ringServer, rs.ringServerGRPCOpts...) if err != nil { rs.logError("replValueStore: error connecting to ring service %q: %s", ringServer, err) sleeper() continue } stream, err := synpb.NewSyndicateClient(conn).GetRingStream(context.Background(), &synpb.SubscriberID{Id: rs.ringClientID}) if err != nil { rs.logError("replValueStore: error creating stream with ring service %q: %s", ringServer, err) sleeper() continue } connDoneChan := make(chan struct{}) somethingICanTakeAnAddressOf := int32(0) activity := &somethingICanTakeAnAddressOf // This goroutine will detect when the exitChan is closed so it can // close the conn so that the blocking stream.Recv will get an error // and everything will unwind properly. // However, if the conn errors out on its own and exitChan isn't // closed, we're going to loop back around and try a new conn, but we // need to clear out this goroutine, which is what the connDoneChan is // for. // One last thing is that if nothing happens for fifteen minutes, we // can assume the conn has gone stale and close it, causing a loop // around to try a new conn. // It would be so much easier if Recv could use a timeout Context... go func(c *grpc.ClientConn, a *int32, cdc chan struct{}) { for { select { case <-exitChan: case <-cdc: case <-time.After(15 * time.Minute): // I'm comfortable with time.After here since it's just // once per fifteen minutes or new conn. v := atomic.LoadInt32(a) if v != 0 { atomic.AddInt32(a, -v) continue } } break } c.Close() }(conn, activity, connDoneChan) for { select { case <-exitChan: break default: } res, err := stream.Recv() if err != nil { rs.logDebug("replValueStore: error with stream to ring service %q: %s", ringServer, err) break } atomic.AddInt32(activity, 1) if res != nil { if r, err := ring.LoadRing(bytes.NewBuffer(res.Ring)); err != nil { rs.logDebug("replValueStore: error with ring received from stream to ring service %q: %s", ringServer, err) } else { // This will cache the ring if ringCachePath is not empty. rs.SetRing(r) // Resets the exponential sleeper since we had success. sleeperTicks = 2 rs.logDebug("replValueStore: got new ring from stream to ring service %q: %d", ringServer, res.Version) } } } close(connDoneChan) sleeper() } }