bf851bd9fc
Added support for dyntmpl to the template system. The Account Dashboard now sort of uses dyntmpl, more work needed here. Renamed the pre_render_view_topic hook to pre_render_topic. Added the GetCurrentLangPack() function. Added the alerts_no_new_alerts phrase. Added the account_level_list phrase. Refactored the route rename logic in the patcher to cut down on the amount of boilerplate. Added more route renames to the patcher. You will need to run the patcher / updater in this commit.
119 lines
3.2 KiB
Go
119 lines
3.2 KiB
Go
package counters
|
|
|
|
import (
|
|
"database/sql"
|
|
"sync"
|
|
|
|
"github.com/Azareal/Gosora/common"
|
|
"github.com/Azareal/Gosora/query_gen"
|
|
)
|
|
|
|
var ForumViewCounter *DefaultForumViewCounter
|
|
|
|
// TODO: Unload forum counters without any views over the past 15 minutes, if the admin has configured the forumstore with a cap and it's been hit?
|
|
// Forums can be reloaded from the database at any time, so we want to keep the counters separate from them
|
|
type DefaultForumViewCounter struct {
|
|
oddMap map[int]*RWMutexCounterBucket // map[fid]struct{counter,sync.RWMutex}
|
|
evenMap map[int]*RWMutexCounterBucket
|
|
oddLock sync.RWMutex
|
|
evenLock sync.RWMutex
|
|
|
|
insert *sql.Stmt
|
|
}
|
|
|
|
func NewDefaultForumViewCounter() (*DefaultForumViewCounter, error) {
|
|
acc := qgen.NewAcc()
|
|
counter := &DefaultForumViewCounter{
|
|
oddMap: make(map[int]*RWMutexCounterBucket),
|
|
evenMap: make(map[int]*RWMutexCounterBucket),
|
|
insert: acc.Insert("viewchunks_forums").Columns("count, createdAt, forum").Fields("?,UTC_TIMESTAMP(),?").Prepare(),
|
|
}
|
|
common.AddScheduledFifteenMinuteTask(counter.Tick) // There could be a lot of routes, so we don't want to be running this every second
|
|
//common.AddScheduledSecondTask(counter.Tick)
|
|
common.AddShutdownTask(counter.Tick)
|
|
return counter, acc.FirstError()
|
|
}
|
|
|
|
func (counter *DefaultForumViewCounter) Tick() error {
|
|
counter.oddLock.RLock()
|
|
oddMap := counter.oddMap
|
|
counter.oddLock.RUnlock()
|
|
for forumID, forum := range oddMap {
|
|
var count int
|
|
forum.RLock()
|
|
count = forum.counter
|
|
forum.RUnlock()
|
|
// TODO: Only delete the bucket when it's zero to avoid hitting popular forums?
|
|
counter.oddLock.Lock()
|
|
delete(counter.oddMap, forumID)
|
|
counter.oddLock.Unlock()
|
|
err := counter.insertChunk(count, forumID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
counter.evenLock.RLock()
|
|
evenMap := counter.evenMap
|
|
counter.evenLock.RUnlock()
|
|
for forumID, forum := range evenMap {
|
|
var count int
|
|
forum.RLock()
|
|
count = forum.counter
|
|
forum.RUnlock()
|
|
// TODO: Only delete the bucket when it's zero to avoid hitting popular forums?
|
|
counter.evenLock.Lock()
|
|
delete(counter.evenMap, forumID)
|
|
counter.evenLock.Unlock()
|
|
err := counter.insertChunk(count, forumID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (counter *DefaultForumViewCounter) insertChunk(count int, forum int) error {
|
|
if count == 0 {
|
|
return nil
|
|
}
|
|
common.DebugLogf("Inserting a viewchunk with a count of %d for forum %d", count, forum)
|
|
_, err := counter.insert.Exec(count, forum)
|
|
return err
|
|
}
|
|
|
|
func (counter *DefaultForumViewCounter) Bump(forumID int) {
|
|
// Is the ID even?
|
|
if forumID%2 == 0 {
|
|
counter.evenLock.RLock()
|
|
forum, ok := counter.evenMap[forumID]
|
|
counter.evenLock.RUnlock()
|
|
if ok {
|
|
forum.Lock()
|
|
forum.counter++
|
|
forum.Unlock()
|
|
} else {
|
|
counter.evenLock.Lock()
|
|
counter.evenMap[forumID] = &RWMutexCounterBucket{counter: 1}
|
|
counter.evenLock.Unlock()
|
|
}
|
|
return
|
|
}
|
|
|
|
counter.oddLock.RLock()
|
|
forum, ok := counter.oddMap[forumID]
|
|
counter.oddLock.RUnlock()
|
|
if ok {
|
|
forum.Lock()
|
|
forum.counter++
|
|
forum.Unlock()
|
|
} else {
|
|
counter.oddLock.Lock()
|
|
counter.oddMap[forumID] = &RWMutexCounterBucket{counter: 1}
|
|
counter.oddLock.Unlock()
|
|
}
|
|
}
|
|
|
|
// TODO: Add a forum counter backed by two maps which grow as forums are created but never shrinks
|