2018-02-19 04:26:01 +00:00
|
|
|
package counters
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
|
|
|
"sync/atomic"
|
|
|
|
|
2018-10-27 03:21:02 +00:00
|
|
|
"github.com/Azareal/Gosora/common"
|
2019-07-11 21:26:05 +00:00
|
|
|
qgen "github.com/Azareal/Gosora/query_gen"
|
2018-02-19 04:26:01 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// TODO: Rename this?
|
|
|
|
var GlobalViewCounter *DefaultViewCounter
|
|
|
|
|
|
|
|
// TODO: Rename this and shard it?
|
|
|
|
type DefaultViewCounter struct {
|
|
|
|
buckets [2]int64
|
|
|
|
currentBucket int64
|
|
|
|
|
|
|
|
insert *sql.Stmt
|
|
|
|
}
|
|
|
|
|
2018-05-27 09:36:35 +00:00
|
|
|
func NewGlobalViewCounter(acc *qgen.Accumulator) (*DefaultViewCounter, error) {
|
2018-02-19 04:26:01 +00:00
|
|
|
counter := &DefaultViewCounter{
|
|
|
|
currentBucket: 0,
|
2019-07-11 21:26:05 +00:00
|
|
|
insert: acc.Insert("viewchunks").Columns("count, createdAt, route").Fields("?,UTC_TIMESTAMP(),''").Prepare(),
|
2018-02-19 04:26:01 +00:00
|
|
|
}
|
|
|
|
common.AddScheduledFifteenMinuteTask(counter.Tick) // This is run once every fifteen minutes to match the frequency of the RouteViewCounter
|
|
|
|
//common.AddScheduledSecondTask(counter.Tick)
|
|
|
|
common.AddShutdownTask(counter.Tick)
|
|
|
|
return counter, acc.FirstError()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (counter *DefaultViewCounter) Tick() (err error) {
|
|
|
|
var oldBucket = counter.currentBucket
|
|
|
|
var nextBucket int64 // 0
|
|
|
|
if counter.currentBucket == 0 {
|
|
|
|
nextBucket = 1
|
|
|
|
}
|
|
|
|
atomic.AddInt64(&counter.buckets[oldBucket], counter.buckets[nextBucket])
|
|
|
|
atomic.StoreInt64(&counter.buckets[nextBucket], 0)
|
|
|
|
atomic.StoreInt64(&counter.currentBucket, nextBucket)
|
|
|
|
|
|
|
|
var previousViewChunk = counter.buckets[oldBucket]
|
|
|
|
atomic.AddInt64(&counter.buckets[oldBucket], -previousViewChunk)
|
|
|
|
return counter.insertChunk(previousViewChunk)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (counter *DefaultViewCounter) Bump() {
|
|
|
|
atomic.AddInt64(&counter.buckets[counter.currentBucket], 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (counter *DefaultViewCounter) insertChunk(count int64) error {
|
|
|
|
if count == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
common.DebugLogf("Inserting a viewchunk with a count of %d", count)
|
|
|
|
_, err := counter.insert.Exec(count)
|
|
|
|
return err
|
|
|
|
}
|