github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/common/counters/langs.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 var LangViewCounter *DefaultLangViewCounter 13 14 var langCodes = []string{ 15 "unknown", 16 "", 17 "af", 18 "ar", 19 "az", 20 "be", 21 "bg", 22 "bs", 23 "ca", 24 "cs", 25 "cy", 26 "da", 27 "de", 28 "dv", 29 "el", 30 "en", 31 "eo", 32 "es", 33 "et", 34 "eu", 35 "fa", 36 "fi", 37 "fo", 38 "fr", 39 "gl", 40 "gu", 41 "he", 42 "hi", 43 "hr", 44 "hu", 45 "hy", 46 "id", 47 "is", 48 "it", 49 "ja", 50 "ka", 51 "kk", 52 "kn", 53 "ko", 54 "kok", 55 "kw", 56 "ky", 57 "lt", 58 "lv", 59 "mi", 60 "mk", 61 "mn", 62 "mr", 63 "ms", 64 "mt", 65 "nb", 66 "nl", 67 "nn", 68 "ns", 69 "pa", 70 "pl", 71 "ps", 72 "pt", 73 "qu", 74 "ro", 75 "ru", 76 "sa", 77 "se", 78 "sk", 79 "sl", 80 "sq", 81 "sr", 82 "sv", 83 "sw", 84 "syr", 85 "ta", 86 "te", 87 "th", 88 "tl", 89 "tn", 90 "tr", 91 "tt", 92 "ts", 93 "uk", 94 "ur", 95 "uz", 96 "vi", 97 "xh", 98 "zh", 99 "zu", 100 } 101 102 type DefaultLangViewCounter struct { 103 //buckets []*MutexCounterBucket //[OSID]count 104 buckets []int64 //[OSID]count 105 codesToIndices map[string]int 106 107 insert *sql.Stmt 108 } 109 110 func NewDefaultLangViewCounter(acc *qgen.Accumulator) (*DefaultLangViewCounter, error) { 111 codesToIndices := make(map[string]int, len(langCodes)) 112 for index, code := range langCodes { 113 codesToIndices[code] = index 114 } 115 co := &DefaultLangViewCounter{ 116 buckets: make([]int64, len(langCodes)), 117 codesToIndices: codesToIndices, 118 insert: acc.Insert("viewchunks_langs").Columns("count,createdAt,lang").Fields("?,UTC_TIMESTAMP(),?").Prepare(), 119 } 120 121 c.Tasks.FifteenMin.Add(co.Tick) 122 //c.Tasks.Sec.Add(co.Tick) 123 c.Tasks.Shutdown.Add(co.Tick) 124 return co, acc.FirstError() 125 } 126 127 func (co *DefaultLangViewCounter) Tick() error { 128 for id := 0; id < len(co.buckets); id++ { 129 count := atomic.SwapInt64(&co.buckets[id], 0) 130 e := co.insertChunk(count, id) // TODO: Bulk insert for speed? 131 if e != nil { 132 return errors.Wrap(errors.WithStack(e), "langview counter") 133 } 134 } 135 return nil 136 } 137 138 func (co *DefaultLangViewCounter) insertChunk(count int64, id int) error { 139 if count == 0 { 140 return nil 141 } 142 langCode := langCodes[id] 143 if langCode == "" { 144 langCode = "none" 145 } 146 c.DebugLogf("Inserting a vchunk with a count of %d for lang %s (%d)", count, langCode, id) 147 _, e := co.insert.Exec(count, langCode) 148 return e 149 } 150 151 func (co *DefaultLangViewCounter) Bump(langCode string) (validCode bool) { 152 validCode = true 153 id, ok := co.codesToIndices[langCode] 154 if !ok { 155 // TODO: Tell the caller that the code's invalid 156 id = 0 // Unknown 157 validCode = false 158 } 159 160 // TODO: Test this check 161 c.DebugDetail("buckets ", id, ": ", co.buckets[id]) 162 if len(co.buckets) <= id || id < 0 { 163 return validCode 164 } 165 atomic.AddInt64(&co.buckets[id], 1) 166 167 return validCode 168 } 169 170 func (co *DefaultLangViewCounter) Bump2(id int) { 171 // TODO: Test this check 172 c.DebugDetail("bucket ", id, ": ", co.buckets[id]) 173 if len(co.buckets) <= id || id < 0 { 174 return 175 } 176 atomic.AddInt64(&co.buckets[id], 1) 177 }