From 80cf699a732117151dca13c02e6f7fc2ee52343c Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 25 Jun 2023 15:49:19 +0200 Subject: [PATCH] feat(backend): cache user/member counts --- backend/db/db.go | 5 +++++ backend/db/metrics.go | 41 +++++++++++++++++++++++++++++++++++++ backend/routes/meta/meta.go | 27 +----------------------- 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/backend/db/db.go b/backend/db/db.go index 5f7af5a..13e12f2 100644 --- a/backend/db/db.go +++ b/backend/db/db.go @@ -6,6 +6,7 @@ import ( "fmt" "net/url" "os" + "sync" "codeberg.org/pronounscc/pronouns.cc/backend/log" "emperror.dev/errors" @@ -41,6 +42,10 @@ type DB struct { baseURL *url.URL TotalRequests prometheus.Counter + + activeUsersDay, activeUsersWeek, activeUsersMonth int64 + usersTotal, membersTotal int64 + countMu sync.RWMutex } func New() (*DB, error) { diff --git a/backend/db/metrics.go b/backend/db/metrics.go index c2a4cf9..e9e34ef 100644 --- a/backend/db/metrics.go +++ b/backend/db/metrics.go @@ -21,6 +21,11 @@ func (db *DB) initMetrics() (err error) { if err != nil { log.Errorf("getting user count for metrics: %v", err) } + + db.countMu.Lock() + db.usersTotal = count + db.countMu.Unlock() + return float64(count) })) if err != nil { @@ -35,6 +40,11 @@ func (db *DB) initMetrics() (err error) { if err != nil { log.Errorf("getting member count for metrics: %v", err) } + + db.countMu.Lock() + db.membersTotal = count + db.countMu.Unlock() + return float64(count) })) if err != nil { @@ -49,6 +59,11 @@ func (db *DB) initMetrics() (err error) { if err != nil { log.Errorf("getting active user count for metrics: %v", err) } + + db.countMu.Lock() + db.activeUsersMonth = count + db.countMu.Unlock() + return float64(count) })) if err != nil { @@ -63,6 +78,11 @@ func (db *DB) initMetrics() (err error) { if err != nil { log.Errorf("getting active user count for metrics: %v", err) } + + db.countMu.Lock() + db.activeUsersWeek = count + db.countMu.Unlock() + return float64(count) })) if err != nil { @@ -77,6 +97,11 @@ func (db *DB) initMetrics() (err error) { if err != nil { log.Errorf("getting active user count for metrics: %v", err) } + + db.countMu.Lock() + db.activeUsersDay = count + db.countMu.Unlock() + return float64(count) })) if err != nil { @@ -107,6 +132,22 @@ func (db *DB) initMetrics() (err error) { return nil } +func (db *DB) Counts(ctx context.Context) (numUsers, numMembers, usersDay, usersWeek, usersMonth int64) { + db.countMu.Lock() + if numUsers != 0 { + defer db.countMu.Unlock() + return db.usersTotal, db.membersTotal, db.activeUsersDay, db.activeUsersWeek, db.activeUsersMonth + } + db.countMu.Unlock() + + numUsers, _ = db.TotalUserCount(ctx) + numMembers, _ = db.TotalMemberCount(ctx) + usersDay, _ = db.ActiveUsers(ctx, ActiveDay) + usersWeek, _ = db.ActiveUsers(ctx, ActiveWeek) + usersMonth, _ = db.ActiveUsers(ctx, ActiveMonth) + return numUsers, numMembers, usersDay, usersWeek, usersMonth +} + func (db *DB) TotalUserCount(ctx context.Context) (numUsers int64, err error) { err = db.QueryRow(ctx, "SELECT COUNT(*) FROM users WHERE deleted_at IS NULL").Scan(&numUsers) if err != nil { diff --git a/backend/routes/meta/meta.go b/backend/routes/meta/meta.go index da59f8d..ebae428 100644 --- a/backend/routes/meta/meta.go +++ b/backend/routes/meta/meta.go @@ -4,9 +4,7 @@ import ( "net/http" "os" - "codeberg.org/pronounscc/pronouns.cc/backend/db" "codeberg.org/pronounscc/pronouns.cc/backend/server" - "emperror.dev/errors" "github.com/go-chi/chi/v5" "github.com/go-chi/render" ) @@ -39,30 +37,7 @@ type MetaUsers struct { func (s *Server) meta(w http.ResponseWriter, r *http.Request) error { ctx := r.Context() - numUsers, err := s.DB.TotalUserCount(ctx) - if err != nil { - return errors.Wrap(err, "querying user count") - } - - activeMonth, err := s.DB.ActiveUsers(ctx, db.ActiveMonth) - if err != nil { - return errors.Wrap(err, "querying user count") - } - - activeWeek, err := s.DB.ActiveUsers(ctx, db.ActiveWeek) - if err != nil { - return errors.Wrap(err, "querying user count") - } - - activeDay, err := s.DB.ActiveUsers(ctx, db.ActiveDay) - if err != nil { - return errors.Wrap(err, "querying user count") - } - - numMembers, err := s.DB.TotalMemberCount(ctx) - if err != nil { - return errors.Wrap(err, "querying user count") - } + numUsers, numMembers, activeDay, activeWeek, activeMonth := s.DB.Counts(ctx) render.JSON(w, r, MetaResponse{ GitRepository: server.Repository,