func apples(name string, addr string, master bool) { var role string if master { role = "master" } else { role = "slave" } client := redis.NewClient(&redis.Options{ Addr: addr, }) if err := client.Ping().Err(); err != nil { l2n.Printf("Error connecting to %s '%s' of pod %s\n", role, addr, name) pd("Error connecting to "+role, map[string]interface{}{ "Pod": name, "Address": addr, }) return } setRedisClientName(client) l2n.Printf("Connected to Redis '%s' @ %s", name, addr) ticker := time.NewTicker(time.Second * 30) for range ticker.C { blob := getInfoAsBlob(client) for _, section := range infoSections { dispatcher.Publish("redis-"+role, addr, section, blob[section]) } } l2n.Printf("Shouldn't be here - Stopped checking %s", name) }
func main() { log.Println("Starting Redis NOM NOM NOM...") if err := loadConfiguration(); err != nil { l2n.Printf("%v", err) os.Exit(-1) } logger2Nsq := l2n.NewLog2Nsq(&l2n.Options{ AppName: "redis-nom", Addr: cfg.Nsq.Address[0], }) l2n.Println("Configuration loaded") l2n.Printf("%+v", cfg) commons.HoldMeTillICantGetEnough(cfg.Cache.Mastername, cfg.Cache.Sentinel, cfg.General.Env) if err := getSentinelClient(); err != nil { l2n.Printf("%v", err) os.Exit(-1) } if masterPodList = retrievePodList(); masterPodList == nil { l2n.Println("Failed to retrieve pod list") os.Exit(-1) } l2n.Printf("%+v", masterPodList) nsqLock := make(chan bool, 1) dispatcher.InitPagerDutyInterface(cfg.PagerDuty.Key) dispatcher.StartNSQProducer(cfg.Nsq.Topic, cfg.Nsq.Address, nsqLock) monitor.StartSentinelMonitoring(cfg.Redis.Sentinel) monitor.StartRedisMonitoring(cfg.Redis.Sentinel) lock := make(chan bool, 1) sigRcv := make(chan os.Signal, 1) signal.Notify(sigRcv, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) // Routine to catch and handle signals go func(sigRcv chan os.Signal) { for sig := range sigRcv { l2n.Printf("Signal caught: %s", sig.String()) // TODO Clean all nsqLock <- true lock <- true } }(sigRcv) <-lock logger2Nsq.Close() }
func retrievePodList(client *redis.Client) map[string]*pod { podList := make(map[string]*pod) Pods := func(client *redis.Client) *redis.StringCmd { cmd := redis.NewStringCmd("INFO", "sentinel") client.Process(cmd) return cmd } if rsp, err := Pods(client).Result(); err == nil { lines := strings.Split(rsp, "\r\n") for i, line := range lines { if i > 4 && len(line) > 0 { contents1 := strings.SplitN(line, ":", 2) contents2 := strings.Split(contents1[1], ",") var slaveCount int if slaveCount, err = strconv.Atoi(contents2[3][7:]); err != nil { slaveCount = -1 } podList[contents2[0][5:]] = &pod{ Addr: contents2[2][8:], SlaveCount: slaveCount, } } } } else { l2n.Printf("Error retrieving POD list: %s", err.Error()) return nil } return podList }
func bananas(addrs []string, lock chan bool) { cfg := nsq.NewConfig() cfg.UserAgent = fmt.Sprintf("redis-nom/0.1 go-nsq/%s", nsq.VERSION) producers = make(map[string]*nsq.Producer) for _, addr := range addrs { if producer, err := nsq.NewProducer(addr, cfg); err == nil { producers[addr] = producer } else { l2n.Printf("Failed to connect to NSQ @ %s", addr) } } if len(producers) == 0 { l2n.Println("No NSQ available") return } l2n.Println("NSQ Producer is on the go!") <-lock for _, producer := range producers { producer.Stop() } }
func bananas(addr string) { var err error var psub *redis.PubSub client := redis.NewClient(&redis.Options{ Addr: addr, }) if err = client.Ping().Err(); err != nil { l2n.Printf("Error talking with sentinel @ %s", addr) pd("Error connecting to sentinel", map[string]interface{}{ "Addr": addr, }) return } setRedisClientName(client) if psub, err = client.PSubscribe("*"); err != nil { l2n.Printf("Error subscribing to * from sentinel @ %s", addr) pd("Error subscribing to sentinel", map[string]interface{}{ "Addr": addr, "Topic": "*", }) return } l2n.Printf("Subscribed to * from %s", addr) defer psub.Close() for { if msg, err := psub.ReceiveMessage(); err == nil { dispatcher.Publish("sentinel", addr, msg.Channel, msg.Payload) } else { time.Sleep(100 * time.Millisecond) } } }
// StartRedisMonitoring starts the monitoring of the buns func StartRedisMonitoring(sentinels []string) { if sentinel, err := getSentinelClient(sentinels); err == nil { masterPodList = retrievePodList(sentinel) l2n.Printf("Current POD list: %+v", masterPodList) for k, v := range masterPodList { retrieveSlaves(sentinel, k, v) go apples(k, v.Addr, true) for _, addr := range v.Slaves { go apples(k, addr, false) } } } }
// Publish send this to the interwebs func Publish(who string, where string, what string, details interface{}) { if len(producers) == 0 { return } msg := &log{ Who: who, Where: where, What: what, When: time.Now(), Details: details, } for _, producer := range producers { if jsonMsg, err := json.Marshal(msg); err == nil { if err = producer.Publish(topic, jsonMsg); err != nil { l2n.Printf("Error sending message: %s", string(jsonMsg)) } } } }
// HoldMeTillICantGetEnough will hold the application here, until he finds out he was left out alone to do all the work func HoldMeTillICantGetEnough(mastername string, sentinel []string, env string) { cache = redis.NewFailoverClient(&redis.FailoverOptions{ MasterName: mastername, SentinelAddrs: sentinel, }) if _, err := cache.Ping().Result(); err != nil { l2n.Printf("[CACHE] %s", err.Error()) os.Exit(1) } monkeyOutThere := false for cache.Get(env).Err() == nil { if !monkeyOutThere { l2n.Println("[HOLD] There's a monkey doing monkey's work...") monkeyOutThere = true } time.Sleep(5 * time.Second) } go iWillSurvive(env) go logImAlive() }