//TODO: Need concurrency, we should just fire of replicates in goroutines // and collects the results. On a failure we still need to send the rollback // or have the slave's commit deadline trigger. func (s *Server) replicateRing(r ring.Ring, rb, bb *[]byte) error { failcount := 0 for _, slave := range s.slaves { ctx, _ := context.WithTimeout(context.Background(), time.Duration(_SYN_REGISTER_TIMEOUT)*time.Second) i := &pb.RingMsg{ Version: r.Version(), Ring: *rb, Builder: *bb, Deadline: time.Now().Add(60 * time.Second).Unix(), Rollback: s.r.Version(), } res, err := slave.client.Store(ctx, i) if err != nil { log.Println(err) failcount++ continue } if res.Version != r.Version() { log.Printf("Version or master on remote node %+v did not match local entries. Got %+v.", slave, res) failcount++ continue } if !res.Ring || !res.Builder { log.Printf("res is: %#v\n", res) log.Printf("Slave failed to store ring or builder: %s", res.ErrMsg) failcount++ continue } log.Printf("<-- Slave response: %+v", res) slave.version = res.Version slave.last = time.Now() slave.status = true } if failcount > (len(s.slaves) / 2) { return fmt.Errorf("Failed to get replication majority") } return nil }