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  }