func campaign(conn db.Conn, store Store) { watch := store.Watch(leaderKey, 1*time.Second) trigg := conn.TriggerTick(electionTTL/2, db.EtcdTable) oldMaster := false for { select { case <-watch: case <-trigg.C: } etcdRows := conn.SelectFromEtcd(nil) minion, err := conn.MinionSelf() master := err == nil && minion.Role == db.Master && len(etcdRows) == 1 if !master { if oldMaster { commitLeader(conn, false, "") } continue } IP := minion.PrivateIP if IP == "" { continue } ttl := electionTTL * time.Second if etcdRows[0].Leader { err = store.Update(leaderKey, IP, ttl) } else { err = store.Create(leaderKey, IP, ttl) } if err == nil { commitLeader(conn, true, IP) } else { clientErr, ok := err.(client.Error) if !ok || clientErr.Code != client.ErrorCodeNodeExist { log.WithError(err).Warn("Error setting leader key") commitLeader(conn, false, "") // Give things a chance to settle down. time.Sleep(electionTTL * time.Second) } else { commitLeader(conn, false) } } } }