chore: metrics performance improvements

This commit is contained in:
Ferdinand Mütsch 2022-03-19 10:30:32 +01:00
parent ec70d024fa
commit bbc85de34b
9 changed files with 751 additions and 723 deletions

File diff suppressed because it is too large Load Diff

View File

@ -20,8 +20,8 @@ func (m *HeartbeatServiceMock) InsertBatch(heartbeats []*models.Heartbeat) error
return args.Error(0)
}
func (m *HeartbeatServiceMock) Count() (int64, error) {
args := m.Called()
func (m *HeartbeatServiceMock) Count(a bool) (int64, error) {
args := m.Called(a)
return int64(args.Int(0)), args.Error(1)
}

View File

@ -1,6 +1,7 @@
package repositories
import (
conf "github.com/muety/wakapi/config"
"github.com/muety/wakapi/models"
"gorm.io/gorm"
"gorm.io/gorm/clause"
@ -8,11 +9,12 @@ import (
)
type HeartbeatRepository struct {
db *gorm.DB
db *gorm.DB
config *conf.Config
}
func NewHeartbeatRepository(db *gorm.DB) *HeartbeatRepository {
return &HeartbeatRepository{db: db}
return &HeartbeatRepository{config: conf.Get(), db: db}
}
// Use with caution!!
@ -116,12 +118,19 @@ func (r *HeartbeatRepository) GetLastByUsers() ([]*models.TimeByUser, error) {
return result, nil
}
func (r *HeartbeatRepository) Count() (int64, error) {
var count int64
if err := r.db.
Model(&models.Heartbeat{}).
Count(&count).Error; err != nil {
return 0, err
func (r *HeartbeatRepository) Count(approximate bool) (count int64, err error) {
if r.config.Db.IsMySQL() && approximate {
err = r.db.Table("information_schema.tables").
Select("table_rows").
Where("table_schema = ?", r.config.Db.Name).
Where("table_name = 'heartbeats'").
Scan(&count).Error
}
if count == 0 {
err = r.db.
Model(&models.Heartbeat{}).
Count(&count).Error
}
return count, nil
}
@ -145,6 +154,10 @@ func (r *HeartbeatRepository) CountByUsers(users []*models.User) ([]*models.Coun
userIds[i] = u.ID
}
if len(userIds) == 0 {
return counts, nil
}
if err := r.db.
Model(&models.Heartbeat{}).
Select("user_id as user, count(id) as count").
@ -153,6 +166,7 @@ func (r *HeartbeatRepository) CountByUsers(users []*models.User) ([]*models.Coun
Find(&counts).Error; err != nil {
return counts, err
}
return counts, nil
}

View File

@ -25,7 +25,7 @@ type IHeartbeatRepository interface {
GetLastByUsers() ([]*models.TimeByUser, error)
GetLatestByUser(*models.User) (*models.Heartbeat, error)
GetLatestByOriginAndUser(string, *models.User) (*models.Heartbeat, error)
Count() (int64, error)
Count(bool) (int64, error)
CountByUser(*models.User) (int64, error)
CountByUsers([]*models.User) ([]*models.CountByUser, error)
GetEntitySetByUser(uint8, *models.User) ([]string, error)

View File

@ -98,10 +98,9 @@ func (r *UserRepository) GetByLoggedInAfter(t time.Time) ([]*models.User, error)
// Returns a list of user ids, whose last heartbeat is not older than t
// NOTE: Only ID field will be populated
func (r *UserRepository) GetByLastActiveAfter(t time.Time) ([]*models.User, error) {
subQuery1 := r.db.Model(&models.User{}).
Select("users.id as user, max(time) as time").
Joins("left join heartbeats on users.id = heartbeats.user_id").
Group("user")
subQuery1 := r.db.Model(&models.Heartbeat{}).
Select("user_id as user, max(time) as time").
Group("user_id")
var userIds []string
if err := r.db.

View File

@ -273,7 +273,7 @@ func (h *MetricsHandler) getAdminMetrics(user *models.User) (*mm.Metrics, error)
}
totalUsers, _ := h.userSrvc.Count()
totalHeartbeats, _ := h.heartbeatSrvc.Count()
totalHeartbeats, _ := h.heartbeatSrvc.Count(true)
activeUsers, err := h.userSrvc.GetActive(false)
if err != nil {

View File

@ -73,12 +73,12 @@ func (srv *HeartbeatService) InsertBatch(heartbeats []*models.Heartbeat) error {
return err
}
func (srv *HeartbeatService) Count() (int64, error) {
func (srv *HeartbeatService) Count(approximate bool) (int64, error) {
result, ok := srv.cache.Get(srv.countTotalCacheKey())
if ok {
return result.(int64), nil
}
count, err := srv.repository.Count()
count, err := srv.repository.Count(approximate)
if err == nil {
srv.cache.Set(srv.countTotalCacheKey(), count, srv.countCacheTtl())
}

View File

@ -29,7 +29,7 @@ type IAliasService interface {
type IHeartbeatService interface {
Insert(*models.Heartbeat) error
InsertBatch([]*models.Heartbeat) error
Count() (int64, error)
Count(bool) (int64, error)
CountByUser(*models.User) (int64, error)
CountByUsers([]*models.User) ([]*models.CountByUser, error)
GetAllWithin(time.Time, time.Time, *models.User) ([]*models.Heartbeat, error)

View File

@ -1 +1 @@
2.3.0
2.3.1