// RunQuery is a function that is launched as a goroutine to perform // the MongoDB work. func RunQuery(query int, waitGroup *sync.WaitGroup, mongoSession *mgo.Session) { // Decrement the wait group count so the program knows this // has been completed once the goroutine exits. defer waitGroup.Done() // Request a socket connection from the session to process our query. // Close the session when the goroutine exits and put the connection back // into the pool. sessionCopy := mongoSession.Copy() defer sessionCopy.Close() // Get a collection to execute the query against. collection := sessionCopy.DB(TestDatabase).C("buoy_stations") log.Printf("RunQuery : %d : Executing\n", query) // Retrieve the list of stations. var buoyStations []BuoyStation err := collection.Find(nil).All(&buoyStations) if err != nil { log.Printf("RunQuery : ERROR : %s\n", err) return } log.Printf("RunQuery : %d : Count[%d]\n", query, len(buoyStations)) }
/* * makeHandler warps around handlers providing them with a session, and automatically closing that session * to prevent loosing memory. */ func makeHandler(fn func(http.ResponseWriter, *http.Request, *mgo.Session), session *mgo.Session) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { s := session.Copy() // Create a copy of the session fn(w, r, s) s.Close() // Close the copy } }
func CopySession(s *mgo.Session) *mgo.Session { for i := 0; i < CopySessionMaxRetry; i++ { res := s.Copy() err := checkSession(res) if err == nil { return res } CloseSession(res) log.Print("[MGO2_COPY_SESSION] copy session and check failed:", err) if isServersFailed(err) { panic("[MGO2_COPY_SESSION_FAILED] servers failed") } } msg := fmt.Sprintf("[MGO2_COPY_SESSION_FAILED] failed after %d retries", CopySessionMaxRetry) log.Fatal(msg) panic(msg) }
func MakeTodoProducer(b *Broker, session *mgo.Session) RequestFunc { return func(resp http.ResponseWriter, req *http.Request) { ProduceTodos(resp, req, b, session.Copy()) } }
func main() { flag.Parse() defer func() { if err := recover(); err != nil { panic(err) } }() var session *mgo.Session var err error go func() { for session == nil { log.Println("Connecting to mongo..") session, err = mgo.Dial(os.Getenv("CU_DB")) if err != nil { if session != nil { session.Close() session = nil } log.Printf("Database connection failed (%q), retrying..", err) time.Sleep(10 * time.Second) } } log.Println("Connected to mongo.") }() http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // Query boxes splitted := strings.SplitN(r.URL.Path[1:], "/", 2) if len(splitted) < 2 { w.WriteHeader(http.StatusBadRequest) return } if session == nil { log.Printf("%v StatusServiceUnavailable session == nil", splitted[0]) w.WriteHeader(http.StatusServiceUnavailable) return } validTokenQuery := bson.M{ "$and": []bson.M{ bson.M{"name": splitted[0]}, bson.M{"boxJSON.publish_token": splitted[1]}}} err := ErrDbTimeout var n int done := make(chan struct{}) go func() { this_session := session.Copy() defer this_session.Close() db := this_session.DB("") n, err = db.C("boxes").Find(validTokenQuery).Count() close(done) }() select { case <-time.After(5 * time.Second): case <-done: } if err != nil { log.Printf("%v StatusServiceUnavailable %q", splitted[0], err) w.WriteHeader(http.StatusServiceUnavailable) return } if n == 0 { log.Printf("%v StatusForbidden", splitted[0]) w.WriteHeader(http.StatusForbidden) return } w.WriteHeader(http.StatusOK) }) println("Listening...") err = http.ListenAndServe(":23423", nil) check(err) }
func FastCopySession(s *mgo.Session) *mgo.Session { return s.Copy() }