178 lines
2.8 KiB
Go
178 lines
2.8 KiB
Go
package counters
|
|
|
|
import (
|
|
"database/sql"
|
|
"sync/atomic"
|
|
|
|
c "git.tuxpa.in/a/gosora/common"
|
|
qgen "git.tuxpa.in/a/gosora/query_gen"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
var LangViewCounter *DefaultLangViewCounter
|
|
|
|
var langCodes = []string{
|
|
"unknown",
|
|
"",
|
|
"af",
|
|
"ar",
|
|
"az",
|
|
"be",
|
|
"bg",
|
|
"bs",
|
|
"ca",
|
|
"cs",
|
|
"cy",
|
|
"da",
|
|
"de",
|
|
"dv",
|
|
"el",
|
|
"en",
|
|
"eo",
|
|
"es",
|
|
"et",
|
|
"eu",
|
|
"fa",
|
|
"fi",
|
|
"fo",
|
|
"fr",
|
|
"gl",
|
|
"gu",
|
|
"he",
|
|
"hi",
|
|
"hr",
|
|
"hu",
|
|
"hy",
|
|
"id",
|
|
"is",
|
|
"it",
|
|
"ja",
|
|
"ka",
|
|
"kk",
|
|
"kn",
|
|
"ko",
|
|
"kok",
|
|
"kw",
|
|
"ky",
|
|
"lt",
|
|
"lv",
|
|
"mi",
|
|
"mk",
|
|
"mn",
|
|
"mr",
|
|
"ms",
|
|
"mt",
|
|
"nb",
|
|
"nl",
|
|
"nn",
|
|
"ns",
|
|
"pa",
|
|
"pl",
|
|
"ps",
|
|
"pt",
|
|
"qu",
|
|
"ro",
|
|
"ru",
|
|
"sa",
|
|
"se",
|
|
"sk",
|
|
"sl",
|
|
"sq",
|
|
"sr",
|
|
"sv",
|
|
"sw",
|
|
"syr",
|
|
"ta",
|
|
"te",
|
|
"th",
|
|
"tl",
|
|
"tn",
|
|
"tr",
|
|
"tt",
|
|
"ts",
|
|
"uk",
|
|
"ur",
|
|
"uz",
|
|
"vi",
|
|
"xh",
|
|
"zh",
|
|
"zu",
|
|
}
|
|
|
|
type DefaultLangViewCounter struct {
|
|
//buckets []*MutexCounterBucket //[OSID]count
|
|
buckets []int64 //[OSID]count
|
|
codesToIndices map[string]int
|
|
|
|
insert *sql.Stmt
|
|
}
|
|
|
|
func NewDefaultLangViewCounter(acc *qgen.Accumulator) (*DefaultLangViewCounter, error) {
|
|
codesToIndices := make(map[string]int, len(langCodes))
|
|
for index, code := range langCodes {
|
|
codesToIndices[code] = index
|
|
}
|
|
co := &DefaultLangViewCounter{
|
|
buckets: make([]int64, len(langCodes)),
|
|
codesToIndices: codesToIndices,
|
|
insert: acc.Insert("viewchunks_langs").Columns("count,createdAt,lang").Fields("?,UTC_TIMESTAMP(),?").Prepare(),
|
|
}
|
|
|
|
c.Tasks.FifteenMin.Add(co.Tick)
|
|
//c.Tasks.Sec.Add(co.Tick)
|
|
c.Tasks.Shutdown.Add(co.Tick)
|
|
return co, acc.FirstError()
|
|
}
|
|
|
|
func (co *DefaultLangViewCounter) Tick() error {
|
|
for id := 0; id < len(co.buckets); id++ {
|
|
count := atomic.SwapInt64(&co.buckets[id], 0)
|
|
e := co.insertChunk(count, id) // TODO: Bulk insert for speed?
|
|
if e != nil {
|
|
return errors.Wrap(errors.WithStack(e), "langview counter")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (co *DefaultLangViewCounter) insertChunk(count int64, id int) error {
|
|
if count == 0 {
|
|
return nil
|
|
}
|
|
langCode := langCodes[id]
|
|
if langCode == "" {
|
|
langCode = "none"
|
|
}
|
|
c.DebugLogf("Inserting a vchunk with a count of %d for lang %s (%d)", count, langCode, id)
|
|
_, e := co.insert.Exec(count, langCode)
|
|
return e
|
|
}
|
|
|
|
func (co *DefaultLangViewCounter) Bump(langCode string) (validCode bool) {
|
|
validCode = true
|
|
id, ok := co.codesToIndices[langCode]
|
|
if !ok {
|
|
// TODO: Tell the caller that the code's invalid
|
|
id = 0 // Unknown
|
|
validCode = false
|
|
}
|
|
|
|
// TODO: Test this check
|
|
c.DebugDetail("buckets ", id, ": ", co.buckets[id])
|
|
if len(co.buckets) <= id || id < 0 {
|
|
return validCode
|
|
}
|
|
atomic.AddInt64(&co.buckets[id], 1)
|
|
|
|
return validCode
|
|
}
|
|
|
|
func (co *DefaultLangViewCounter) Bump2(id int) {
|
|
// TODO: Test this check
|
|
c.DebugDetail("bucket ", id, ": ", co.buckets[id])
|
|
if len(co.buckets) <= id || id < 0 {
|
|
return
|
|
}
|
|
atomic.AddInt64(&co.buckets[id], 1)
|
|
}
|