76 lines
1.8 KiB
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()
|
||
|
}
|
||
|
}
|
||
|
}
|