func init() { Expect = make(map[string]chan []byte) // spawn worker to monitor key space change; KEY UPDATE go func() { regevent := redis.KeySpaceEventLoop() client := redis.NewClient() defer client.Close() for event := range regevent { target, ok := Expect[event.Key] if !ok { continue } switch event.Action { case "expired": close(target) break case "append": val, err := client.Get(event.Key).Result() if err != nil { panic(err) } target <- []byte(val) break } } }() Server.HandleFunc("/provision", Provision) Server.HandleFunc("/deprovision", Deprovision) }
func Deprovision(w http.ResponseWriter, r *http.Request) { if r.Method != "DELETE" { http.Error(w, "Method not allowd", 405) return } if err := r.ParseForm(); err != nil { http.Error(w, err.Error(), 503) return } client := redis.NewClient() defer client.Close() key := r.Form.Get("id") if key == "" { http.Error(w, "Bad request", 400) return } defer func() { if target, ok := Expect[key]; ok { delete(Expect, key) close(target) } }() if _, err := client.Del(key).Result(); err != nil { panic(err) } w.Write([]byte("ok")) }
func Provision(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { http.Error(w, "Method not allowd", 405) return } if err := r.ParseForm(); err != nil { http.Error(w, err.Error(), 503) return } client := redis.NewClient() defer client.Close() domain, tier, app := r.Form.Get("domain"), r.Form.Get("tier"), r.Form.Get("app") if domain == "" || tier == "" || app == "" { http.Error(w, "Bad request", 400) return } key := fmt.Sprintf("%s:%s:%s", tier, domain, app) if _, ok := Expect[key]; !ok { Expect[key] = make(chan []byte) } defer func() { delete(Expect, key) if err := recover(); err != nil { log.Println(err) switch t := err.(type) { default: http.Error(w, "Unexpected Error", 503) break case error: http.Error(w, t.Error(), 503) break case string: http.Error(w, t, 503) break } } }() exp, _ := time.ParseDuration(r.Form.Get("expire")) if state, err := client.SetNX(key, "", exp).Result(); err != nil { panic(err) } else if !state { panic(fmt.Errorf("KEY exist: %s", key)) } if response, ok := <-Expect[key]; !ok { panic(fmt.Errorf("Key expired before response %s", key)) } else { headers := w.Header() headers.Add("Content-Type", "application/json") w.Write(response) } }
func main() { log.Println("begin the redis keyspace tracker to RabbitMQ") client := redis.NewClient() defer client.Close() actions, confirm := rabbitmq.NamedRecvLoop("registry-complete") for oneact := range actions { var res registry.ResourceEvent confirm <- &rabbitmq.ConfirmedEvent{ DTag: oneact.DTag, Ack: true, } if err := oneact.Deserialize(&res); err != nil { log.Println(err) continue } if err := client.Append(res.VendorName, string(oneact.Val)).Err(); err != nil { log.Println(err) continue } log.Println("update:", res) } }