mirror of
https://github.com/gojp/goreportcard.git
synced 2026-01-29 06:49:05 +08:00
First pass of writing to and loading from bolt
This commit is contained in:
@@ -2,12 +2,21 @@ package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gopkg.in/mgo.v2"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
"github.com/boltdb/bolt"
|
||||
)
|
||||
|
||||
const (
|
||||
// DBPath is the relative (or absolute) path to the bolt database file
|
||||
DBPath string = "goreportcard.db"
|
||||
|
||||
// RepoBucket is the bucket in which repos will be cached in the bolt DB
|
||||
RepoBucket string = "repos"
|
||||
)
|
||||
|
||||
// CheckHandler handles the request for checking a repo
|
||||
@@ -31,26 +40,34 @@ func CheckHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
b, err := json.Marshal(resp)
|
||||
respBytes, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
log.Println("ERROR: could not marshal json:", err)
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
w.Write(b)
|
||||
w.Write(respBytes)
|
||||
|
||||
// write to mongo
|
||||
session, err := mgo.Dial(mongoURL)
|
||||
// write to boltdb
|
||||
db, err := bolt.Open(DBPath, 0755, &bolt.Options{Timeout: 1 * time.Second})
|
||||
if err != nil {
|
||||
log.Println("Failed to get mongo collection: ", err)
|
||||
log.Println("Failed to open bolt database: ", err)
|
||||
return
|
||||
}
|
||||
defer session.Close()
|
||||
coll := session.DB(mongoDatabase).C(mongoCollection)
|
||||
log.Printf("Upserting repo %s...", repo)
|
||||
_, err = coll.Upsert(bson.M{"repo": repo}, resp)
|
||||
defer db.Close()
|
||||
|
||||
log.Printf("Saving repo %q to cache...", repo)
|
||||
|
||||
err = db.Update(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(RepoBucket))
|
||||
if b == nil {
|
||||
return fmt.Errorf("Repo bucket not found")
|
||||
}
|
||||
return b.Put([]byte(repo), respBytes)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Println("Mongo writing error:", err)
|
||||
return
|
||||
log.Println("Bolt writing error:", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
@@ -8,36 +11,51 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/gojp/goreportcard/check"
|
||||
"gopkg.in/mgo.v2"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
var (
|
||||
mongoURL = "mongodb://127.0.0.1:27017"
|
||||
mongoDatabase = "goreportcard"
|
||||
mongoCollection = "reports"
|
||||
)
|
||||
|
||||
func getFromCache(repo string) (checksResp, error) {
|
||||
// try and fetch from mongo
|
||||
session, err := mgo.Dial(mongoURL)
|
||||
// try and fetch from boltdb
|
||||
db, err := bolt.Open(DBPath, 0600, &bolt.Options{Timeout: 1 * time.Second})
|
||||
if err != nil {
|
||||
return checksResp{}, fmt.Errorf("Failed to get mongo collection during GET: %v", err)
|
||||
return checksResp{}, fmt.Errorf("Failed to open bolt database during GET: %v", err)
|
||||
}
|
||||
defer session.Close()
|
||||
coll := session.DB(mongoDatabase).C(mongoCollection)
|
||||
defer db.Close()
|
||||
|
||||
resp := checksResp{}
|
||||
err = coll.Find(bson.M{"repo": repo}).One(&resp)
|
||||
err = db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(RepoBucket))
|
||||
if b == nil {
|
||||
return errors.New("No repo bucket")
|
||||
}
|
||||
cached := b.Get([]byte(repo))
|
||||
if cached == nil {
|
||||
return fmt.Errorf("%q not found in cache", repo)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(cached, &resp)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse JSON for %q in cache", repo)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return checksResp{}, fmt.Errorf("Failed to fetch %q from mongo: %v", repo, err)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
resp.LastRefresh = resp.LastRefresh.UTC()
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// itob returns an 8-byte big endian representation of v.
|
||||
func itob(v int) []byte {
|
||||
b := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(b, uint64(v))
|
||||
return b
|
||||
}
|
||||
|
||||
type score struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
|
||||
@@ -2,13 +2,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"text/template"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"gopkg.in/mgo.v2"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
func add(x, y int) int {
|
||||
@@ -21,36 +15,36 @@ func formatScore(x float64) string {
|
||||
|
||||
// HighScoresHandler handles the stats page
|
||||
func HighScoresHandler(w http.ResponseWriter, r *http.Request) {
|
||||
session, err := mgo.Dial(mongoURL)
|
||||
if err != nil {
|
||||
log.Println("ERROR: could not get collection:", err)
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
defer session.Close()
|
||||
coll := session.DB(mongoDatabase).C(mongoCollection)
|
||||
|
||||
var highScores []struct {
|
||||
Repo string
|
||||
Files int
|
||||
Average float64
|
||||
}
|
||||
err = coll.Find(bson.M{"files": bson.M{"$gt": 100}}).Sort("-average").Limit(50).All(&highScores)
|
||||
if err != nil {
|
||||
log.Println("ERROR: could not get high scores: ", err)
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
|
||||
count, err := coll.Count()
|
||||
if err != nil {
|
||||
log.Println("ERROR: could not get count of high scores: ", err)
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
|
||||
funcs := template.FuncMap{"add": add, "formatScore": formatScore}
|
||||
t := template.Must(template.New("high_scores.html").Funcs(funcs).ParseFiles("templates/high_scores.html"))
|
||||
|
||||
t.Execute(w, map[string]interface{}{"HighScores": highScores, "Count": humanize.Comma(int64(count))})
|
||||
// session, err := mgo.Dial(mongoURL)
|
||||
// if err != nil {
|
||||
// log.Println("ERROR: could not get collection:", err)
|
||||
// http.Error(w, err.Error(), 500)
|
||||
// return
|
||||
// }
|
||||
// defer session.Close()
|
||||
// coll := session.DB(mongoDatabase).C(mongoCollection)
|
||||
//
|
||||
// var highScores []struct {
|
||||
// Repo string
|
||||
// Files int
|
||||
// Average float64
|
||||
// }
|
||||
// err = coll.Find(bson.M{"files": bson.M{"$gt": 100}}).Sort("-average").Limit(50).All(&highScores)
|
||||
// if err != nil {
|
||||
// log.Println("ERROR: could not get high scores: ", err)
|
||||
// http.Error(w, err.Error(), 500)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// count, err := coll.Count()
|
||||
// if err != nil {
|
||||
// log.Println("ERROR: could not get count of high scores: ", err)
|
||||
// http.Error(w, err.Error(), 500)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// funcs := template.FuncMap{"add": add, "formatScore": formatScore}
|
||||
// t := template.Must(template.New("high_scores.html").Funcs(funcs).ParseFiles("templates/high_scores.html"))
|
||||
//
|
||||
// t.Execute(w, map[string]interface{}{"HighScores": highScores, "Count": humanize.Comma(int64(count))})
|
||||
}
|
||||
|
||||
23
main.go
23
main.go
@@ -6,7 +6,9 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/gojp/goreportcard/handlers"
|
||||
)
|
||||
|
||||
@@ -31,11 +33,32 @@ func makeHandler(name string, fn func(http.ResponseWriter, *http.Request, string
|
||||
}
|
||||
}
|
||||
|
||||
// initDB opens the bolt database file (or creates it if it does not exist), and creates
|
||||
// a bucket for saving the repos, also only if it does not exist.
|
||||
func initDB() error {
|
||||
db, err := bolt.Open(handlers.DBPath, 0600, &bolt.Options{Timeout: 1 * time.Second})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
err = db.Update(func(tx *bolt.Tx) error {
|
||||
_, err := tx.CreateBucketIfNotExists([]byte(handlers.RepoBucket))
|
||||
return err
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := os.MkdirAll("repos/src/github.com", 0755); err != nil && !os.IsExist(err) {
|
||||
log.Fatal("ERROR: could not create repos dir: ", err)
|
||||
}
|
||||
|
||||
// initialize database
|
||||
if err := initDB(); err != nil {
|
||||
log.Fatal("ERROR: could not open bolt db: ", err)
|
||||
}
|
||||
|
||||
http.HandleFunc("/assets/", handlers.AssetsHandler)
|
||||
http.HandleFunc("/checks", handlers.CheckHandler)
|
||||
http.HandleFunc("/report/", makeHandler("report", handlers.ReportHandler))
|
||||
|
||||
Reference in New Issue
Block a user