Выполните goroutine в цикле и передайте значение переменной в другой пакет - PullRequest
0 голосов
/ 23 декабря 2018

У меня проблемы с передачей переменной из основного пакета в другой.

Что я пытаюсь сделать:

У меня есть простой http-демон, который получает входящие запросы POST иотправляет их в экземпляр rabbitMQ, где сообщения будут обрабатываться каким-либо работником.Поскольку сообщения могут быть очень большими, я пытаюсь реализовать простой менеджер ресурсов.Он должен принять или отклонить запрос.

Вот как это выглядит:

package main

import (
    "flag"
    "fmt"
    "github.com/couchbaselabs/logg"
    "net/http"
    _ "net/http/pprof"
)

var resourceChannel = make(chan bool)
var ampqApiConfig = worker.DefaultResManagerConfig()
var ServiceCanAccept bool

func main() {
    var http_port int
    flagFunc := func() {
        flag.IntVar(
            &http_port,
            "http_port",
            8080,
            "The http port to listen on, eg, 8081",
        )
    }

    rabbitConfig := worker.DefaultConfigFlagsOverride(flagFunc)

    // any requests to root, just redirect to main page
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        text := `<h1>We are running!<h1>`
        fmt.Fprintf(w, text)
    })

    http.Handle("/req", worker.NewHttpHandler(rabbitConfig))
    http.Handle("/status", worker.NewHttpStatusHandler())
    listenAddr := fmt.Sprintf(":%d", http_port)

    logg.LogTo("HTTP", "Starting listener on %v", listenAddr)
    // start a goroutine which will decide if we have resources for future requests
    go func() {
        for {
            resourceChannel <- worker.AcceptRequest(&ampqApiConfig)
            ServiceCanAccept = <-resourceChannel
            worker.ServiceCanAccept = ServiceCanAccept
            time.Sleep(10 * time.Second)
        }
    }()
    logg.LogError(http.ListenAndServe(listenAddr, nil))
}

Я определяю над каналом и глобальной переменной.Затем я пытаюсь запускать логическую функцию (AcceptRequest) каждые 10 секунд и передаю переменную в переменную woker.ServiceCanAccept в пакете «worker».Но, к сожалению, это не работает.Goroutine выполняется только один раз (по крайней мере, я вижу журналы из менеджера ресурсов только один раз), и значение worker.ServiceCanAccept в целевом пакете не изменяется.Это проблема номер один.

Для каждого запроса будет вызываться http.Handle("/req", worker.NewHttpHandler(rabbitConfig)) и выполняется приведенный ниже ServeHTTP.Однако var ServiceCanAccept bool никогда не меняется.Нужно ли создавать канал с таким же именем, как в пакете main, и читать значение из него?

package worker

import (
    "encoding/json"
    "fmt"
    "github.com/couchbaselabs/logg"
    "net/http"
)

type HttpHandler struct {
    RabbitConfig RabbitConfig
}

func NewHttpHandler(r RabbitConfig) *HttpHandler {
    return &HttpHandler{
        RabbitConfig: r,
    }
}

var ServiceCanAccept bool

func (s *HttpHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {

    logg.LogTo("HTTP", "serveHttp called")
    defer req.Body.Close()

    Request := Request{}
    decoder := json.NewDecoder(req.Body)
    err := decoder.Decode(&Request)
    if err != nil {
        logg.LogError(err)
        http.Error(w, "Unable to unmarshal json", 500)
        return
    }

    Result, err := HandleRequest(Request, s.RabbitConfig)

    if err != nil {
        msg := "Unable to perform decode.  Error: %v"
        errMsg := fmt.Sprintf(msg, err)
        logg.LogError(fmt.Errorf(errMsg))
        http.Error(w, errMsg, 500)
        return
    }
    w.Header().Set("Content-Type", "application/json")
    js, err := json.Marshal(Result)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    w.Write(js)

}

func HandleRequest(Request Request, rabbitConfig RabbitConfig) (Result, error) {

    defaultResManagerConfig := DefaultResManagerConfig()
    if !ServiceCanAccept {
        err := fmt.Errorf("no ressources available to proced the request")
        return Result{}, err
    }

    switch Request.InplaceDecode {
    case true:
        Engine := NewEngine(Request.EngineType)

        Result, err := Engine.ProcessRequest(Request)

        if err != nil {
            msg := "Error processing request.  Error: %v"
            errMsg := fmt.Sprintf(msg, err)
            logg.LogError(fmt.Errorf(errMsg))
            return Result{}, err
        }

        return Result, nil
    default:
        Client, err := NewRpcClient(rabbitConfig)
        if err != nil {
            logg.LogError(err)
            return Result{}, err
        }
        Result, err := Client.DecodeImage(Request)
        if err != nil {
            logg.LogError(err)
            return Result{}, err
        }
        return Result, nil
    }
}

Спасибо!

...