gosora/common/requests.go

76 lines
1.8 KiB
Go

package common
import (
"sync"
"sync/atomic"
)
// Add ReferrerItems here after they've had zero views for a while
var referrersToDelete = make(map[string]ReferrerDeletable)
type ReferrerDeletable struct {
item *ReferrerItem
scheduledAt int64 //unixtime
}
type ReferrerItem struct {
Counter int64
}
// ? We'll track referrer domains here rather than the exact URL they arrived from for now, we'll think about expanding later
// ? Referrers are fluid and ever-changing so we have to use string keys rather than 'enum' ints
type DefaultReferrerTracker struct {
odd map[string]*ReferrerItem
even map[string]*ReferrerItem
oddLock sync.RWMutex
evenLock sync.RWMutex
}
func NewDefaultReferrerTracker() *DefaultReferrerTracker {
return &DefaultReferrerTracker{
odd: make(map[string]*ReferrerItem),
even: make(map[string]*ReferrerItem),
}
}
func (ref *DefaultReferrerTracker) Tick() (err error) {
for _, del := range referrersToDelete {
_ = del
// TODO: Calculate the gap between now and the times they were scheduled
}
// TODO: Run the queries and schedule zero view refs for deletion from memory
return nil
}
func (ref *DefaultReferrerTracker) Bump(referrer string) {
if referrer == "" {
return
}
var refItem *ReferrerItem
// Slightly crude and rudimentary, but it should give a basic degree of sharding
if referrer[0]%2 == 0 {
ref.evenLock.RLock()
refItem = ref.even[referrer]
ref.evenLock.RUnlock()
if ref != nil {
atomic.AddInt64(&refItem.Counter, 1)
} else {
ref.evenLock.Lock()
ref.even[referrer] = &ReferrerItem{Counter: 1}
ref.evenLock.Unlock()
}
} else {
ref.oddLock.RLock()
refItem = ref.odd[referrer]
ref.oddLock.RUnlock()
if ref != nil {
atomic.AddInt64(&refItem.Counter, 1)
} else {
ref.oddLock.Lock()
ref.odd[referrer] = &ReferrerItem{Counter: 1}
ref.oddLock.Unlock()
}
}
}