У меня проблемы с передачей переменной из основного пакета в другой.
Что я пытаюсь сделать:
У меня есть простой 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(&qApiConfig)
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
}
}
Спасибо!