diff --git a/migrations/20211215_migrate_id_to_bigint.go b/migrations/20211215_migrate_id_to_bigint.go index 6298641..99cd043 100644 --- a/migrations/20211215_migrate_id_to_bigint.go +++ b/migrations/20211215_migrate_id_to_bigint.go @@ -15,6 +15,8 @@ func init() { return nil } + logbuch.Info("this may take a while!") + if cfg.Db.IsMySQL() { tx := db.Begin() if err := tx.Exec("ALTER TABLE heartbeats MODIFY COLUMN id BIGINT UNSIGNED AUTO_INCREMENT").Error; err != nil { diff --git a/migrations/20212212_total_summary_heartbeats.go b/migrations/20212212_total_summary_heartbeats.go new file mode 100644 index 0000000..b929d6e --- /dev/null +++ b/migrations/20212212_total_summary_heartbeats.go @@ -0,0 +1,48 @@ +package migrations + +import ( + "database/sql" + "github.com/emvi/logbuch" + "github.com/muety/wakapi/config" + "github.com/muety/wakapi/models" + "gorm.io/gorm" +) + +func init() { + const name = "20212212-total_summary_heartbeats" + f := migrationFunc{ + name: name, + f: func(db *gorm.DB, cfg *config.Config) error { + if hasRun(name, db) { + return nil + } + + logbuch.Info("this may take a while!") + + // this turns out to actually be way faster than using joins and instead has the benefit of being cross-dialect compatible + + var summaries []*models.Summary + if err := db.Model(&models.Summary{}). + Select("id, from_time, to_time, user_id"). + Scan(&summaries).Error; err != nil { + return err + } + + tx := db.Begin() + for _, s := range summaries { + query := "UPDATE summaries SET num_heartbeats = (SELECT count(id) AS num_heartbeats FROM heartbeats WHERE user_id = @user AND time BETWEEN @from AND @to) WHERE id = @id" + tx.Exec(query, sql.Named("from", s.FromTime), sql.Named("to", s.ToTime), sql.Named("id", s.ID), sql.Named("user", s.UserID)) + } + if err := tx.Commit().Error; err != nil { + tx.Rollback() + logbuch.Error("failed to retroactively determine total summary heartbeats") + return err + } + + setHasRun(name, db) + return nil + }, + } + + registerPostMigration(f) +} diff --git a/models/summary.go b/models/summary.go index f7d4bb0..f52a12e 100644 --- a/models/summary.go +++ b/models/summary.go @@ -31,7 +31,7 @@ type Summary struct { OperatingSystems SummaryItems `json:"operating_systems" gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` Machines SummaryItems `json:"machines" gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` Labels SummaryItems `json:"labels" gorm:"-"` // labels are not persisted, but calculated at runtime, i.e. when summary is retrieved - NumHeartbeats int `json:"-"` + NumHeartbeats int `json:"-" gorm:"default:0"` } type SummaryItems []*SummaryItem diff --git a/views/signup.tpl.html b/views/signup.tpl.html index 7387a52..2a527ae 100644 --- a/views/signup.tpl.html +++ b/views/signup.tpl.html @@ -81,9 +81,9 @@
- + -