Пример #1
0
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
		}
	}
}
Пример #2
0
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
	}
}
Пример #3
0
//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)
		}
	}

}
Пример #4
0
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
	}
}
Пример #5
0
// 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
}
Пример #6
0
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
	})
}
Пример #7
0
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"))
	}
}
Пример #8
0
// 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
			}
		}
	}
}
Пример #9
0
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
	}
}
Пример #10
0
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
	}
}
Пример #11
0
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
		}
	}
}
Пример #12
0
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
		}
	}
}
Пример #13
0
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))
		}
	}
}