Remove statistics and add frequent tags in memory

This commit is contained in:
Las Zenow 2016-09-03 15:08:10 -04:00
parent 284b649b69
commit 18baa2938b
10 changed files with 35 additions and 256 deletions

View file

@ -24,8 +24,6 @@ type Book struct {
Tsv string
}
// TODO: missing history
// AddBook to the database
func (db *pgDB) AddBook(book Book) error {
emptyTime := time.Time{}

View file

@ -22,22 +22,17 @@ type DB interface {
GetNews(num int, days int) (news []New, err error)
AddStats(stats interface{}) error
GetVisitedBooks() (books []Book, err error)
UpdateMostVisited() error
GetDownloadedBooks() (books []Book, err error)
UpdateDownloadedBooks() error
GetTags() ([]string, error)
UpdateTags() error
GetVisits(visitType VisitType) ([]Visits, error)
UpdateHourVisits() error
UpdateDayVisits() error
UpdateMonthVisits() error
UpdateHourDownloads() error
UpdateDayDownloads() error
UpdateMonthDownloads() error
}
const (
tagsDisplay = 50
)
type pgDB struct {
sql *pg.DB
sql *pg.DB
tags []string
}
// Options for the database
@ -57,7 +52,11 @@ func Init(options Options) (DB, error) {
Database: options.Name,
})
// TODO: create db
return &pgDB{sql}, nil
db := pgDB{sql, []string{}}
go db.tagUpdater()
return &db, nil
}
// Close the database connection

View file

@ -76,50 +76,10 @@ func (db *roDB) GetVisitedBooks() (books []Book, err error) {
return db.db.GetVisitedBooks()
}
func (db *roDB) UpdateMostVisited() error {
return errors.New("RO database")
}
func (db *roDB) GetDownloadedBooks() (books []Book, err error) {
return db.db.GetDownloadedBooks()
}
func (db *roDB) UpdateDownloadedBooks() error {
return errors.New("RO database")
}
func (db *roDB) GetTags() ([]string, error) {
return db.db.GetTags()
}
func (db *roDB) UpdateTags() error {
return errors.New("RO database")
}
func (db *roDB) GetVisits(visitType VisitType) ([]Visits, error) {
return db.db.GetVisits(visitType)
}
func (db *roDB) UpdateHourVisits() error {
return errors.New("RO database")
}
func (db *roDB) UpdateDayVisits() error {
return errors.New("RO database")
}
func (db *roDB) UpdateMonthVisits() error {
return errors.New("RO database")
}
func (db *roDB) UpdateHourDownloads() error {
return errors.New("RO database")
}
func (db *roDB) UpdateDayDownloads() error {
return errors.New("RO database")
}
func (db *roDB) UpdateMonthDownloads() error {
return errors.New("RO database")
}

View file

@ -3,24 +3,10 @@ package database
import (
"time"
log "github.com/cihub/seelog"
)
type VisitType int
const (
Hourly_visits = iota
Daily_visits
Monthly_visits
Hourly_downloads
Daily_downloads
Monthly_downloads
)
type Visits struct {
Date time.Time "date"
Count int "count"
}
func (db *pgDB) AddStats(stats interface{}) error {
return nil
}
@ -31,52 +17,34 @@ func (db *pgDB) GetVisitedBooks() (books []Book, err error) {
return []Book{}, nil
}
func (db *pgDB) UpdateMostVisited() error {
return nil
}
/* Get the most downloaded books
*/
func (db *pgDB) GetDownloadedBooks() (books []Book, err error) {
return []Book{}, nil
}
func (db *pgDB) UpdateDownloadedBooks() error {
return nil
}
func (db *pgDB) GetTags() ([]string, error) {
return []string{}, nil
return db.tags, nil
}
func (db *pgDB) UpdateTags() error {
return nil
func (db *pgDB) updateTags() {
err := db.sql.Model(&Book{}).
ColumnExpr("unnest(tags) as tag").
Where("active = true").
Group("tag").
Order("count(*) DESC").
Limit(tagsDisplay).
Select(&db.tags)
if err != nil {
log.Error("Error updating tags: ", err)
}
}
func (db *pgDB) GetVisits(visitType VisitType) ([]Visits, error) {
return []Visits{}, nil
}
func (db *pgDB) tagUpdater() {
periodicity := 57 * time.Minute
func (db *pgDB) UpdateHourVisits() error {
return nil
}
func (db *pgDB) UpdateDayVisits() error {
return nil
}
func (db *pgDB) UpdateMonthVisits() error {
return nil
}
func (db *pgDB) UpdateHourDownloads() error {
return nil
}
func (db *pgDB) UpdateDayDownloads() error {
return nil
}
func (db *pgDB) UpdateMonthDownloads() error {
return nil
for true {
db.updateTags()
time.Sleep(periodicity)
}
}

View file

@ -4,7 +4,6 @@ import (
log "github.com/cihub/seelog"
"net/http"
"strconv"
"strings"
"time"
@ -93,65 +92,6 @@ func (sg StatsGatherer) worker() {
}
}
func statsHandler(h handler) {
data := statsData{
S: GetStatus(h),
HVisits: getVisits(hourlyLabel, h.db, database.Hourly_visits),
DVisits: getVisits(dailyLabel, h.db, database.Daily_visits),
MVisits: getVisits(monthlyLabel, h.db, database.Monthly_visits),
HDownloads: getVisits(hourlyLabel, h.db, database.Hourly_downloads),
DDownloads: getVisits(dailyLabel, h.db, database.Daily_downloads),
MDownloads: getVisits(monthlyLabel, h.db, database.Monthly_downloads),
}
data.S.Title = "Stats -- " + data.S.Title
data.S.Stats = true
h.template.load(h, "stats", data)
}
type statsData struct {
S Status
HVisits []visitData
DVisits []visitData
MVisits []visitData
HDownloads []visitData
DDownloads []visitData
MDownloads []visitData
}
type visitData struct {
Label string
Count int
}
func hourlyLabel(date time.Time) string {
return strconv.Itoa(date.Hour() + 1)
}
func dailyLabel(date time.Time) string {
return strconv.Itoa(date.Day())
}
func monthlyLabel(date time.Time) string {
return date.Month().String()
}
func getVisits(funcLabel func(time.Time) string, db database.DB, visitType database.VisitType) []visitData {
var visits []visitData
visit, err := db.GetVisits(visitType)
if err != nil {
log.Warn("GetVisits error (", visitType, "): ", err)
}
for _, v := range visit {
var elem visitData
elem.Label = funcLabel(v.Date.UTC())
elem.Count = v.Count
visits = append(visits, elem)
}
return visits
}
func appendFiles(r *http.Request, stats map[string]interface{}) {
if r.Method == "POST" && r.MultipartForm != nil {
files := r.MultipartForm.File

View file

@ -9,40 +9,19 @@ import (
)
const (
minutesUpdateTags = 11
minutesUpdateVisited = 41
minutesUpdateDownloaded = 47
minutesUpdateHourlyV = 31
minutesUpdateDailyV = 60*12 + 7
minutesUpdateMonthlyV = 60*24 + 11
minutesUpdateHourlyD = 29
minutesUpdateDailyD = 60*12 + 13
minutesUpdateMontlyD = 60*24 + 17
minutesUpdateLogger = 5
minutesUpdateLogger = 5
)
func InitTasks(db database.DB, loggerConfig string) {
updateLogger := func() error {
return UpdateLogger(loggerConfig)
}
periodicTask(updateLogger, minutesUpdateLogger*time.Minute)
periodicTask(db.UpdateTags, minutesUpdateTags*time.Minute)
periodicTask(db.UpdateMostVisited, minutesUpdateVisited*time.Minute)
periodicTask(db.UpdateDownloadedBooks, minutesUpdateDownloaded*time.Minute)
periodicTask(db.UpdateHourVisits, minutesUpdateHourlyV*time.Minute)
periodicTask(db.UpdateDayVisits, minutesUpdateDailyV*time.Minute)
periodicTask(db.UpdateMonthVisits, minutesUpdateMonthlyV*time.Minute)
periodicTask(db.UpdateHourDownloads, minutesUpdateHourlyD*time.Minute)
periodicTask(db.UpdateDayDownloads, minutesUpdateDailyD*time.Minute)
periodicTask(db.UpdateMonthDownloads, minutesUpdateMontlyD*time.Minute)
go tasker(updateLogger, minutesUpdateLogger)
}
func periodicTask(task func() error, periodicity time.Duration) {
go tasker(task, periodicity)
}
func tasker(task func() error, minutes int) {
periodicity := time.Duration(minutes) * time.Minute
func tasker(task func() error, periodicity time.Duration) {
for true {
time.Sleep(periodicity)
err := task()

View file

@ -73,7 +73,6 @@ func InitTemplate(assetsPath string) *Template {
path.Join(templatePath, "edit.html"),
path.Join(templatePath, "dashboard.html"),
path.Join(templatePath, "settings.html"),
path.Join(templatePath, "stats.html"),
path.Join(templatePath, "help.html"),
))

View file

@ -178,7 +178,6 @@ func InitRouter(db database.DB, sg *StatsGatherer, assetsPath string) {
r.HandleFunc("/help/", sg.Gather(helpHandler))
r.HandleFunc("/download/{id:"+idPattern+"}/{epub:.*}", sg.Gather(downloadHandler))
r.HandleFunc("/cover/{id:"+idPattern+"}/{size}/{img:.*}", sg.Gather(coverHandler))
r.HandleFunc("/stats/", sg.Gather(statsHandler))
r.HandleFunc("/login/", sg.Gather(loginHandler)).Methods("GET")
r.HandleFunc("/login/", sg.Gather(loginPostHandler)).Methods("POST")

View file

@ -57,7 +57,6 @@
<li {{if .About}}class="active"{{end}}><a href="/about/">About</a></li>
<li {{if .News}}class="active"{{end}}><a href="/news/">News</a></li>
<li {{if .Upload}}class="active"{{end}}><a href="/upload/">Upload</a></li>
<li {{if .Stats}}class="active"{{end}}><a href="/stats/">Statistics</a></li>
</ul>
<ul class="nav pull-right">

View file

@ -1,62 +0,0 @@
{{template "header.html" .S}}
<script src="/js/Chart.min.js"></script>
<div class="row">
<div id="visits" class="span6">
<h2>Visits</h2>
<h4>Hourly:</h4>
<canvas id="hvisits" height="400" width="500"></canvas>
<h4>Daily:</h4>
<canvas id="dvisits" height="400" width="500"></canvas>
<h4>Monthly:</h4>
<canvas id="mvisits" height="400" width="500"></canvas>
</div>
<div id="downloads" class="span6">
<h2>Downloads</h2>
<h4>Hourly:</h4>
<canvas id="hdownloads" height="400" width="500"></canvas>
<h4>Daily:</h4>
<canvas id="ddownloads" height="400" width="500"></canvas>
<h4>Monthly:</h4>
<canvas id="mdownlodas" height="400" width="500"></canvas>
</div>
</div>
<script type="text/javascript">
function chart(id, labels, counts) {
var data = {
labels : labels,
datasets : [
{
fillColor : "rgba(151,187,205,0.5)",
strokeColor : "rgba(151,187,205,1)",
pointColor : "rgba(151,187,205,1)",
pointStrokeColor : "#fff",
data : counts
}
]
}
var ctx = $(id).get(0).getContext("2d");
new Chart(ctx).Line(data);
}
$(document).ready(function() {
chart("#hvisits", [{{range .HVisits}}"{{.Label}}",{{end}}],
[{{range .HVisits}}{{.Count}},{{end}}])
chart("#dvisits", [{{range .DVisits}}"{{.Label}}",{{end}}],
[{{range .DVisits}}{{.Count}},{{end}}])
chart("#mvisits", [{{range .MVisits}}"{{.Label}}",{{end}}],
[{{range .MVisits}}{{.Count}},{{end}}])
chart("#hdownloads", [{{range .HDownloads}}"{{.Label}}",{{end}}],
[{{range .HDownloads}}{{.Count}},{{end}}])
chart("#ddownloads", [{{range .DDownloads}}"{{.Label}}",{{end}}],
[{{range .DDownloads}}{{.Count}},{{end}}])
chart("#mdownlodas", [{{range .MDownloads}}"{{.Label}}",{{end}}],
[{{range .MDownloads}}{{.Count}},{{end}}])
})
</script>
{{template "footer.html"}}