gosora/common/counters/requests.go

65 lines
1.7 KiB
Go

package counters
import (
"database/sql"
"sync/atomic"
c "github.com/Azareal/Gosora/common"
qgen "github.com/Azareal/Gosora/query_gen"
"github.com/pkg/errors"
)
// TODO: Rename this?
var GlobalViewCounter *DefaultViewCounter
// TODO: Rename this and shard it?
type DefaultViewCounter struct {
buckets [2]int64
currentBucket int64
insert *sql.Stmt
}
func NewGlobalViewCounter(acc *qgen.Accumulator) (*DefaultViewCounter, error) {
co := &DefaultViewCounter{
currentBucket: 0,
insert: acc.Insert("viewchunks").Columns("count, createdAt, route").Fields("?,UTC_TIMESTAMP(),''").Prepare(),
}
c.AddScheduledFifteenMinuteTask(co.Tick) // This is run once every fifteen minutes to match the frequency of the RouteViewCounter
//c.AddScheduledSecondTask(co.Tick)
c.AddShutdownTask(co.Tick)
return co, acc.FirstError()
}
func (co *DefaultViewCounter) Tick() (err error) {
oldBucket := co.currentBucket
var nextBucket int64 // 0
if co.currentBucket == 0 {
nextBucket = 1
}
atomic.AddInt64(&co.buckets[oldBucket], co.buckets[nextBucket])
atomic.StoreInt64(&co.buckets[nextBucket], 0)
atomic.StoreInt64(&co.currentBucket, nextBucket)
previousViewChunk := co.buckets[oldBucket]
atomic.AddInt64(&co.buckets[oldBucket], -previousViewChunk)
err = co.insertChunk(previousViewChunk)
if err != nil {
return errors.Wrap(errors.WithStack(err), "req counter")
}
return nil
}
func (co *DefaultViewCounter) Bump() {
atomic.AddInt64(&co.buckets[co.currentBucket], 1)
}
func (co *DefaultViewCounter) insertChunk(count int64) error {
if count == 0 {
return nil
}
c.DebugLogf("Inserting a vchunk with a count of %d", count)
_, err := co.insert.Exec(count)
return err
}