func (m *LogTask) WriteLoop(exitchan chan int) { hystrix.ConfigureCommand("NSQWriter", hystrix.CommandConfig{ Timeout: 1000, MaxConcurrentRequests: 1000, ErrorPercentThreshold: 25, }) for { select { case <-m.exitChan: return case <-exitchan: return case msg := <-m.msgChan: resultChan := make(chan int, 1) var err error errChan := hystrix.Go("NSQWriter", func() error { err = m.Writer.MultiPublish(msg.topic, msg.body) if err != nil { return err } resultChan <- 1 return nil }, nil) select { case <-resultChan: case err = <-errChan: log.Println("writeNSQ Error", err) } msg.ResultChan <- err } } }
func (c *Client) requestHystrix(method string, urlStr string, body interface{}) (*goreq.Response, error) { token, err := c.TokenManager.GetToken() if err != nil { return nil, err } output := make(chan *goreq.Response, 1) errors := hystrix.Go(c.Options.HystrixConfig.Name, func() error { resp, err := c.request(token.Authorization, method, urlStr, body) if err != nil { return err } output <- resp return nil }, nil) select { case out := <-output: return out, nil case err := <-errors: return nil, err } }
//LoopOverCmd emulate calls to command func LoopOverCmd(cmdName string, baseDurationMs, floorDurationMs int) { defer log.Printf("!!!!!!Exiting command loop for: %s\n", cmdName) for { output := make(chan string, 1) errors := hystrix.Go(cmdName, func() error { if err := printSleep(int64(baseDurationMs), int64(floorDurationMs)); err != nil { output <- "Ko" return err } output <- "Ok" return nil }, func(err error) error { output <- "Degraded mode" return nil }) select { case out := <-output: log.Printf("Result: %v\n", out) case err := <-errors: log.Printf("Hystrix Error: %v\n", err) } } }
func (c Client) FromPlace(place string) (Location, error) { output := make(chan Location, 1) hystrix.ConfigureCommand("geocodeFromPlace", hystrix.CommandConfig{ Timeout: c.Timeout, MaxConcurrentRequests: 100, ErrorPercentThreshold: 25, }) errs := hystrix.Go("geocodeFromPlace", func() error { geoLoc, err := c.GCli.Get(place) if err != nil { return err } output <- geoLoc return nil }, nil) select { case out := <-output: return out, nil case err := <-errs: return Location{}, err } }
// Sends a spade Event to kafka. func (l *KafkaLogger) Log(e *spade.Event) error { c, err := spade.Marshal(e) if err != nil { return err } hystrix.Go(hystrixCommandName, func() error { return l.Producer.SendMessage(sarama.StringEncoder(e.Uuid), sarama.ByteEncoder(c)) }, nil) return nil }
func ping(c web.C, w http.ResponseWriter, r *http.Request) { hystrix.Go("call_backend", func() error { res, err := http.Get("http://backend/") if err == nil && res != nil { fmt.Fprintln(w, "Response from backend: \n") fmt.Println("Response from backend: ") res.Write(w) return nil } return err }, func(err error) error { // do this when services are down fmt.Fprintf(w, "Hello from backup function!") return nil }) }
func handle(w http.ResponseWriter, r *http.Request) { done := make(chan struct{}, 1) errChan := hystrix.Go("test", func() error { delta := rand.Intn(deltaWindow) time.Sleep(time.Duration(delay+delta) * time.Millisecond) done <- struct{}{} return nil }, func(err error) error { done <- struct{}{} return nil }) select { case err := <-errChan: http.Error(w, err.Error(), 500) case <-done: w.Write([]byte("OK")) } }
// Hystrix returns an endpoint.Middleware that implements the circuit // breaker pattern using the afex/hystrix-go package. // // When using this circuit breaker, please configure your commands separately. // // See https://godoc.org/github.com/afex/hystrix-go/hystrix for more // information. func Hystrix(commandName string) endpoint.Middleware { return func(next endpoint.Endpoint) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (response interface{}, err error) { output := make(chan interface{}, 1) errors := hystrix.Go(commandName, func() error { resp, err := next(ctx, request) if err == nil { output <- resp } return err }, nil) select { case resp := <-output: return resp, nil case err := <-errors: return nil, err } } } }
func (tm *OAuthTokenManager) requestHystrix() (*goreq.Response, error) { output := make(chan *goreq.Response, 1) errors := hystrix.Go(tm.Options.HystrixConfig.Name, func() error { resp, err := tm.request() if err != nil { return err } output <- resp return nil }, nil) select { case out := <-output: return out, nil case err := <-errors: return nil, err } }
func (c Client) FromIP(ip string) (Location, error) { output := make(chan Location, 1) hystrix.ConfigureCommand("geocodeFromIP", hystrix.CommandConfig{ Timeout: c.Timeout, MaxConcurrentRequests: 100, ErrorPercentThreshold: 25, }) errs := hystrix.Go("geocodeFromIP", func() error { ipLoc, err := c.IPCli.Get(ip) if err != nil { return err } combined := Location{ IP: ip, City: ipLoc.City, Region: ipLoc.Region, Latitude: ipLoc.Latitude, Longitude: ipLoc.Longitude, } output <- combined return nil }, nil) select { case out := <-output: return out, nil case err := <-errs: return Location{}, err } }
func (m *Builder) writeLoop() { db, err := client.NewHTTPClient(client.HTTPConfig{ Addr: m.InfluxdbAddress, Username: m.InfluxdbUser, Password: m.InfluxdbPassword, UserAgent: fmt.Sprintf("smartinfo-%s", VERSION), }) if err != nil { log.Println("NewHTTPClient error:", err) } defer db.Close() q := client.NewQuery(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", m.InfluxdbDatabase), "", "s") if response, err := db.Query(q); err != nil || response.Error() != nil { log.Fatal("create influxdb database failed:", response.Results) } for { bp, _ := client.NewBatchPoints(client.BatchPointsConfig{ Database: m.InfluxdbDatabase, Precision: "s", }) select { case msg := <-m.msgChannel: dataset := make(map[string]interface{}) var err error err = json.Unmarshal(msg.Body, &dataset) if err != nil { log.Println("wrong data struct:", string(msg.Body)) msg.ErrorChannel <- nil continue } hostname := dataset["Hostname"].(string) t := dataset["Checktime"].(string) timestamp := time.Now() for k, v := range dataset { tags := make(map[string]string) fields := make(map[string]interface{}) if diskinfo, ok := v.(map[string]interface{}); ok { tags["Hostname"] = hostname tags["Postion"] = k tags["Checktime"] = t for dk, dv := range diskinfo { if value, ok := dv.(string); ok { tags[dk] = value } else { fields[dk] = dv } } } var pt *client.Point pt, err = client.NewPoint("diskstat", tags, fields, timestamp) if err == nil { bp.AddPoint(pt) } } if err == nil { resultChan := make(chan int, 1) errChan := hystrix.Go("InsetInfluxdb", func() error { err = db.Write(bp) if err != nil { return err } resultChan <- 1 return nil }, nil) select { case <-resultChan: case err = <-errChan: log.Println("InsetInfluxdb Error", err) } } msg.ErrorChannel <- err case <-m.exitChannel: return } } }
func (m *MetricDeliver) writeLoop() { db, err := client.NewHTTPClient(client.HTTPConfig{ Addr: m.InfluxdbAddress, Username: m.InfluxdbUser, Password: m.InfluxdbPassword, UserAgent: fmt.Sprintf("metrictools-%s", VERSION), }) if err != nil { log.Println("NewHTTPClient error:", err) } defer db.Close() q := client.NewQuery(fmt.Sprintf("CREATE DATABASE %s", m.InfluxdbDatabase), "", "s") if response, err := db.Query(q); err != nil { if response != nil { log.Println(response.Error()) } log.Fatal("create influxdb database failed:", err) } for { bp, _ := client.NewBatchPoints(client.BatchPointsConfig{ Database: m.InfluxdbDatabase, Precision: "s", }) select { case <-m.exitChannel: return case msg := <-m.msgChannel: data := string(msg.Body.([]byte)) index := strings.IndexAny(data, "|") if index < 1 { log.Println("no user:"******"wrong data struct:", string(msg.Body.([]byte))) msg.ErrorChannel <- nil continue } for _, c := range dataset { timestamp := time.Unix(int64(c.Timestamp), 0) fields := make(map[string]interface{}) tags := m.GenTags(&c, user) for i, _ := range c.DataSetNames { tags["data_set_type"] = c.DataSetTypes[i] fields[c.DataSetNames[i]] = c.Values[i] } var pt *client.Point pt, err = client.NewPoint(c.Plugin, tags, fields, timestamp) if err != nil { log.Println("NewPoint Error:", err) break } bp.AddPoint(pt) if err != nil { break } } if err == nil { resultChan := make(chan int, 1) errChan := hystrix.Go("InsetInfluxdb", func() error { err = db.Write(bp) if err != nil { return err } resultChan <- 1 return nil }, nil) select { case <-resultChan: case err = <-errChan: log.Println("InsetInfluxdb Error", err) } } msg.ErrorChannel <- err } } }
func HandleCrossCompile(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { log.Printf("[INFO] invalid method: %s", r.Method) w.WriteHeader(http.StatusMethodNotAllowed) msg := fmt.Sprintf("Invalid method: %s\n", r.Method) w.Write([]byte(msg)) return } // Handle root request, show project page if r.URL.Path == "/" { http.Redirect(w, r, "https://github.com/tcnksm/gox-server", 301) return } // Check correct request comes repoComponent := strings.Split(strings.Trim(r.URL.Path, "/"), "/") if len(repoComponent) != 2 { log.Printf("[INFO] faild to parse as repository name: %s", r.URL.Path) w.WriteHeader(http.StatusBadRequest) w.Write([]byte("Invalid request: request must be https://gox-server.herokuapp.com/USER/REPO format\n")) return } // Detect platform from user agent targetOS, targetArch := guessPlatform(r.UserAgent()) // Set hystrix configuration hystrix.ConfigureCommand("gox", goxHystrixConfig) // Run resultCh := make(chan string, 1) errCh := hystrix.Go("gox", func() error { // Get source code from github if err := goGet(repoComponent[0], repoComponent[1]); err != nil { return nil } // Run gox and generate binary output, err := gox(repoComponent[0], repoComponent[1], targetOS, targetArch) if err != nil { return nil } resultCh <- output return nil }, nil) select { case output := <-resultCh: log.Printf("[INFO] cross compile is done: %s", output) w.WriteHeader(http.StatusOK) http.ServeFile(w, r, output) case err := <-errCh: log.Printf("[ERROR] failed to cross compiling: %s", err) w.WriteHeader(http.StatusServiceUnavailable) switch err { case hystrix.ErrTimeout: w.Write([]byte("Timeout: gox-server can't handle build which takes more than 120s.\n")) case hystrix.ErrMaxConcurrency: w.Write([]byte("Too many access: gox-server can't handle more than 100 requests at one time.\n")) case hystrix.ErrCircuitOpen: w.Write([]byte("Too many errors: gox-server is unavailable now because of too many errors.\n")) default: msg := fmt.Sprintf("Build failed: %s\n", err.Error()) w.Write([]byte(msg)) } } }