//process recreates the request that should be sent to the target host //it stores the response in the store of replies. func (c *Consumer) process(petition *Petition) { var ( req *http.Request resp *http.Response reply *Reply start = bson.Now() ) db := c.SessionSeed.DB(c.Cfg.Database) petColl := db.C(c.Cfg.Instance + c.Cfg.PetitionsColl) replyColl := db.C(c.Cfg.ResponsesColl) errColl := db.C(c.Cfg.ErrorsColl) mylog.Debugf("processing petition %+v", petition) req, err := petition.Request() if err != nil { mylog.Alert(petition.ID, err) return } mylog.Debugf("restored request %+v", req) mylog.Debug("before making request", petition.ID) resp, err = c.doRequest(req, petition.ID) if err == nil { mylog.Debug("after making request", petition.ID) defer func() { mylog.Debug("closing response body", petition.ID) resp.Body.Close() }() } reply = newReply(resp, petition, err) reply.Created = start mylog.Debugf("created reply %+v", reply) if err != nil || resp.StatusCode < 200 || resp.StatusCode >= 300 { e := errColl.Insert(reply) if e != nil { mylog.Alert("ERROR inserting erroneous reply", petition.ID, err) c.SessionSeed.Refresh() } } mylog.Debugf("before insert reply %+v", reply) err = replyColl.Insert(reply) mylog.Debugf("after insert reply %+v", reply) if err != nil { mylog.Alert("ERROR inserting reply", petition.ID, err) c.SessionSeed.Refresh() } mylog.Debugf("before remove petition %+v", petition) err = petColl.Remove(bson.M{"id": petition.ID}) mylog.Debugf("after remove petition %+v", petition) if err != nil { mylog.Alert("ERROR removing petition", petition.ID, err) c.SessionSeed.Refresh() } }
//ServeHTTP implements HTTP handler interface func (l *Listener) ServeHTTP(w http.ResponseWriter, r *http.Request) { mylog.Debugf("received request %+v", r) w.Header().Set("Content-Type", "application/json") if l.Stopped() { mylog.Debug("warning client server is stopping") http.Error(w, `{"error":"Server is shutting down"}`, 503) return } relayedRequest, e := newPetition(r) if e != nil { mylog.Debug("petition with error", e) http.Error(w, fmt.Sprintf(`{"error": %q }`, e), 400) return } db := l.SessionSeed.DB(l.Cfg.Database) petColl := db.C(l.Cfg.Instance + l.Cfg.PetitionsColl) mylog.Debugf("petition created %+v", relayedRequest) e = petColl.Insert(relayedRequest) if e != nil { http.Error(w, fmt.Sprintf(`{"error": %q, "ref":%q }`, e, relayedRequest.ID), 500) mylog.Alert("ERROR inserting", relayedRequest.ID, e) l.SessionSeed.Refresh() return } select { case l.SendTo <- relayedRequest: mylog.Debug("enqueued petition", relayedRequest) fmt.Fprintf(w, "{\"id\":%q}\n", relayedRequest.ID) default: mylog.Alert("server is busy") http.Error(w, `{"error":"Server is busy"}`, 500) mylog.Debugf("before remove petition", relayedRequest.ID) err := petColl.Remove(bson.M{"id": relayedRequest.ID}) mylog.Debugf("after remove petition", relayedRequest.ID) if err != nil { mylog.Alert("ERROR removing petition", relayedRequest.ID, e) l.SessionSeed.Refresh() return } return } }
func main() { var cfgFile = flag.String("config", "./gridas.yaml", "configuration file") flag.Parse() cfg, err := config.ReadConfig(*cfgFile) if err != nil { mylog.Alert(err) os.Exit(-1) } fmt.Printf("configuration %q %+v\n", *cfgFile, cfg) mylog.SetLevel(cfg.LogLevel) mylog.Alert("hello World!") reqChan := make(chan *gridas.Petition, cfg.QueueSize) session, err := mgo.Dial(cfg.Mongo) if err != nil { mylog.Alert(err) panic(err) } defer func() { session.Close() mylog.Debugf("mongo session closed %+v", session) }() mylog.Debugf("mongo session %+v", session) db := session.DB(cfg.Database) mylog.Debug("mongo database", db) listener := &gridas.Listener{SendTo: reqChan, Cfg: cfg, SessionSeed: session} mylog.Debugf("listener %+v", listener) consumer := &gridas.Consumer{GetFrom: reqChan, Cfg: cfg, SessionSeed: session} mylog.Debugf("consumer %+v", consumer) rplyr := &gridas.Replyer{Cfg: cfg, SessionSeed: session} mylog.Debugf("replyer %+v", rplyr) rcvr := &gridas.Recoverer{SendTo: reqChan, Cfg: cfg, SessionSeed: session} mylog.Debugf("recoverer %+v", rcvr) endConsumers := consumer.Start(cfg.Consumers) if err := rcvr.Recover(); err != nil { mylog.Alert(err) os.Exit(-1) } http.Handle("/", listener) http.Handle("/responses/", http.StripPrefix("/responses/", rplyr)) go func() { mylog.Debug("starting HTTP server (listener)") err := http.ListenAndServe(":"+cfg.Port, nil) if err != nil { mylog.Alert(err) os.Exit(-1) } }() onEnd(func() { mylog.Info("shutting down gridas ...") listener.Stop() mylog.Debug("listener stopped") consumer.Stop() mylog.Debug("consumer stopped") }) <-endConsumers mylog.Alert("bye World!") }