Make sure the metrics map accesses only happen explicitly

This commit is contained in:
kolaente 2020-07-02 21:16:39 +02:00
parent 5d900fd40d
commit 7141050f8b
No known key found for this signature in database
GPG key ID: F40E70337AB24C9B

View file

@ -23,6 +23,7 @@ import (
"encoding/gob" "encoding/gob"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promauto"
"sync"
"time" "time"
) )
@ -39,13 +40,19 @@ type ActiveUser struct {
} }
// ActiveUsersMap is the type used to save active users // ActiveUsersMap is the type used to save active users
type ActiveUsersMap map[int64]*ActiveUser type ActiveUsers struct {
users map[int64]*ActiveUser
mutex *sync.Mutex
}
// activeUsers holds a map with all active users // activeUsers holds a map with all active users
var activeUsers ActiveUsersMap var activeUsers *ActiveUsers
func init() { func init() {
activeUsers = make(ActiveUsersMap) activeUsers = &ActiveUsers{
users: make(map[int64]*ActiveUser),
mutex: &sync.Mutex{},
}
promauto.NewGaugeFunc(prometheus.GaugeOpts{ promauto.NewGaugeFunc(prometheus.GaugeOpts{
Name: "vikunja_active_users", Name: "vikunja_active_users",
@ -56,8 +63,11 @@ func init() {
if err != nil { if err != nil {
log.Error(err.Error()) log.Error(err.Error())
} }
if allActiveUsers == nil {
return 0
}
activeUsersCount := 0 activeUsersCount := 0
for _, u := range allActiveUsers { for _, u := range allActiveUsers.users {
if time.Since(u.LastSeen) < SecondsUntilInactive*time.Second { if time.Since(u.LastSeen) < SecondsUntilInactive*time.Second {
activeUsersCount++ activeUsersCount++
} }
@ -68,15 +78,17 @@ func init() {
// SetUserActive sets a user as active and pushes it to redis // SetUserActive sets a user as active and pushes it to redis
func SetUserActive(a web.Auth) (err error) { func SetUserActive(a web.Auth) (err error) {
activeUsers[a.GetID()] = &ActiveUser{ activeUsers.mutex.Lock()
activeUsers.users[a.GetID()] = &ActiveUser{
UserID: a.GetID(), UserID: a.GetID(),
LastSeen: time.Now(), LastSeen: time.Now(),
} }
activeUsers.mutex.Unlock()
return PushActiveUsers() return PushActiveUsers()
} }
// GetActiveUsers returns the active users from redis // GetActiveUsers returns the active users from redis
func GetActiveUsers() (users ActiveUsersMap, err error) { func GetActiveUsers() (users *ActiveUsers, err error) {
activeUsersR, err := r.Get(ActiveUsersKey).Bytes() activeUsersR, err := r.Get(ActiveUsersKey).Bytes()
if err != nil { if err != nil {
@ -102,7 +114,9 @@ func GetActiveUsers() (users ActiveUsersMap, err error) {
func PushActiveUsers() (err error) { func PushActiveUsers() (err error) {
var b bytes.Buffer var b bytes.Buffer
e := gob.NewEncoder(&b) e := gob.NewEncoder(&b)
if err := e.Encode(activeUsers); err != nil { activeUsers.mutex.Lock()
defer activeUsers.mutex.Unlock()
if err := e.Encode(activeUsers.users); err != nil {
return err return err
} }