github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/common/counters/requests.go (about) 1 package counters 2 3 import ( 4 "database/sql" 5 "sync/atomic" 6 7 c "github.com/Azareal/Gosora/common" 8 qgen "github.com/Azareal/Gosora/query_gen" 9 "github.com/pkg/errors" 10 ) 11 12 // TODO: Rename this? 13 var GlobalViewCounter *DefaultViewCounter 14 15 // TODO: Rename this and shard it? 16 type DefaultViewCounter struct { 17 buckets [2]int64 18 currentBucket int64 19 20 insert *sql.Stmt 21 } 22 23 func NewGlobalViewCounter(acc *qgen.Accumulator) (*DefaultViewCounter, error) { 24 co := &DefaultViewCounter{ 25 currentBucket: 0, 26 insert: acc.Insert("viewchunks").Columns("count,createdAt,route").Fields("?,UTC_TIMESTAMP(),''").Prepare(), 27 } 28 c.Tasks.FifteenMin.Add(co.Tick) // This is run once every fifteen minutes to match the frequency of the RouteViewCounter 29 //c.Tasks.Sec.Add(co.Tick) 30 c.Tasks.Shutdown.Add(co.Tick) 31 return co, acc.FirstError() 32 } 33 34 // TODO: Simplify the atomics used here 35 func (co *DefaultViewCounter) Tick() (err error) { 36 oldBucket := co.currentBucket 37 var nextBucket int64 // 0 38 if co.currentBucket == 0 { 39 nextBucket = 1 40 } 41 atomic.AddInt64(&co.buckets[oldBucket], co.buckets[nextBucket]) 42 atomic.StoreInt64(&co.buckets[nextBucket], 0) 43 atomic.StoreInt64(&co.currentBucket, nextBucket) 44 45 previousViewChunk := co.buckets[oldBucket] 46 atomic.AddInt64(&co.buckets[oldBucket], -previousViewChunk) 47 err = co.insertChunk(previousViewChunk) 48 if err != nil { 49 return errors.Wrap(errors.WithStack(err), "req counter") 50 } 51 return nil 52 } 53 54 func (co *DefaultViewCounter) Bump() { 55 atomic.AddInt64(&co.buckets[co.currentBucket], 1) 56 } 57 58 func (co *DefaultViewCounter) insertChunk(count int64) error { 59 if count == 0 { 60 return nil 61 } 62 c.DebugLogf("Inserting a vchunk with a count of %d", count) 63 _, err := co.insert.Exec(count) 64 return err 65 }