660f24acff
Experimenting with better cache busting for static resources. HTTPSRedirect requests are now counted in the route analytics. More scripts are loaded asynchronously now. Upped the default ReadTimeout to eight seconds. Reduce the number of unneccesary NewAcc calls. Added panel_before_head as an injection point for themes. Themes can now declare scripts to be loaded asynchronously. Tweaked the WS resumption algorithm to mae the backoffs a little less aggressive. Fixed an ordering issue in the WS resumption algorithm where backoffs weren't expiring as fast as they should have. Fixed a bug where template logs weren't being written due to a panic. You can now use byte slices in more places in the transpiled templates. Fixed a bug where Cosora's misc.js seemed to be erroring out. Fixed a bug where YT embeds were getting blocked by the CSP. Added the panel_back_to_site phrase. Added the panel_welcome phrase.
171 lines
2.9 KiB
Go
171 lines
2.9 KiB
Go
package counters
|
|
|
|
import "database/sql"
|
|
import "github.com/Azareal/Gosora/common"
|
|
import "github.com/Azareal/Gosora/query_gen"
|
|
|
|
var LangViewCounter *DefaultLangViewCounter
|
|
|
|
var langCodes = []string{
|
|
"unknown",
|
|
"none",
|
|
"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",
|
|
"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 []*RWMutexCounterBucket //[OSID]count
|
|
codesToIndices map[string]int
|
|
|
|
insert *sql.Stmt
|
|
}
|
|
|
|
func NewDefaultLangViewCounter(acc *qgen.Accumulator) (*DefaultLangViewCounter, error) {
|
|
var langBuckets = make([]*RWMutexCounterBucket, len(langCodes))
|
|
for bucketID, _ := range langBuckets {
|
|
langBuckets[bucketID] = &RWMutexCounterBucket{counter: 0}
|
|
}
|
|
var codesToIndices = make(map[string]int)
|
|
for index, code := range langCodes {
|
|
codesToIndices[code] = index
|
|
}
|
|
|
|
counter := &DefaultLangViewCounter{
|
|
buckets: langBuckets,
|
|
codesToIndices: codesToIndices,
|
|
insert: acc.Insert("viewchunks_langs").Columns("count, createdAt, lang").Fields("?,UTC_TIMESTAMP(),?").Prepare(),
|
|
}
|
|
|
|
common.AddScheduledFifteenMinuteTask(counter.Tick)
|
|
//common.AddScheduledSecondTask(counter.Tick)
|
|
common.AddShutdownTask(counter.Tick)
|
|
return counter, acc.FirstError()
|
|
}
|
|
|
|
func (counter *DefaultLangViewCounter) Tick() error {
|
|
for id, bucket := range counter.buckets {
|
|
var count int
|
|
bucket.RLock()
|
|
count = bucket.counter
|
|
bucket.counter = 0 // TODO: Add a SetZero method to reduce the amount of duplicate code between the OS and agent counters?
|
|
bucket.RUnlock()
|
|
|
|
err := counter.insertChunk(count, id) // TODO: Bulk insert for speed?
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (counter *DefaultLangViewCounter) insertChunk(count int, id int) error {
|
|
if count == 0 {
|
|
return nil
|
|
}
|
|
var langCode = langCodes[id]
|
|
common.DebugLogf("Inserting a viewchunk with a count of %d for lang %s (%d)", count, langCode, id)
|
|
_, err := counter.insert.Exec(count, langCode)
|
|
return err
|
|
}
|
|
|
|
func (counter *DefaultLangViewCounter) Bump(langCode string) (validCode bool) {
|
|
validCode = true
|
|
id, ok := counter.codesToIndices[langCode]
|
|
if !ok {
|
|
// TODO: Tell the caller that the code's invalid
|
|
id = 0 // Unknown
|
|
validCode = false
|
|
}
|
|
|
|
// TODO: Test this check
|
|
common.DebugDetail("counter.buckets[", id, "]: ", counter.buckets[id])
|
|
if len(counter.buckets) <= id || id < 0 {
|
|
return validCode
|
|
}
|
|
counter.buckets[id].Lock()
|
|
counter.buckets[id].counter++
|
|
counter.buckets[id].Unlock()
|
|
|
|
return validCode
|
|
}
|