1
0
mirror of https://github.com/muety/wakapi.git synced 2023-08-10 21:12:56 +03:00

fix: critical summary computation bug (faulty intervals)

fix: doubly included heartbeats
fix: cross-day heartbeats are ignored for consistency
This commit is contained in:
Ferdinand Mütsch 2020-10-16 12:00:20 +02:00
parent 44b6efb6ee
commit 54a944ec41
3 changed files with 15 additions and 6 deletions

View File

@ -46,7 +46,7 @@ func (srv *HeartbeatService) GetAllWithin(from, to time.Time, user *models.User)
if err := srv.Db. if err := srv.Db.
Where(&models.Heartbeat{UserID: user.ID}). Where(&models.Heartbeat{UserID: user.ID}).
Where("time >= ?", from). Where("time >= ?", from).
Where("time <= ?", to). Where("time < ?", to).
Order("time asc"). Order("time asc").
Find(&heartbeats).Error; err != nil { Find(&heartbeats).Error; err != nil {
return nil, err return nil, err

View File

@ -14,6 +14,8 @@ import (
"github.com/muety/wakapi/models" "github.com/muety/wakapi/models"
) )
const HeartbeatDiffThreshold = 2 * time.Minute
type SummaryService struct { type SummaryService struct {
Config *config.Config Config *config.Config
Cache *cache.Cache Cache *cache.Cache
@ -218,9 +220,16 @@ func (srv *SummaryService) aggregateBy(heartbeats []*models.Heartbeat, summaryTy
continue continue
} }
timePassed := h.Time.Time().Sub(heartbeats[i-1].Time.Time()) t1, t2, tdiff := h.Time.Time(), heartbeats[i-1].Time.Time(), time.Duration(0)
timeThresholded := math.Min(float64(timePassed), float64(time.Duration(2)*time.Minute)) // This is a hack. The time difference between two heartbeats from two subsequent day (e.g. 23:59:59 and 00:00:01) are ignored.
durations[key] += time.Duration(int64(timeThresholded)) // This is to prevent a discrepancy between summaries computed solely from heartbeats and summaries involving pre-aggregated per-day summaries.
// For the latter, a duration is already pre-computed and information about individual heartbeats is lost, so there can be no cross-day overflow.
// Essentially, we simply ignore such edge-case heartbeats here, which makes the eventual total duration potentially a bit shorter.
if t1.Day() == t2.Day() {
timePassed := t1.Sub(t2)
tdiff = time.Duration(int64(math.Min(float64(timePassed), float64(HeartbeatDiffThreshold))))
}
durations[key] += tdiff
} }
items := make([]*models.SummaryItem, 0) items := make([]*models.SummaryItem, 0)
@ -269,7 +278,7 @@ func getMissingIntervals(from, to time.Time, existingSummaries []*models.Summary
// Post // Post
if to.After(existingSummaries[len(existingSummaries)-1].ToTime) { if to.After(existingSummaries[len(existingSummaries)-1].ToTime) {
intervals = append(intervals, &Interval{to, existingSummaries[len(existingSummaries)-1].ToTime}) intervals = append(intervals, &Interval{existingSummaries[len(existingSummaries)-1].ToTime, to})
} }
return intervals return intervals

View File

@ -1 +1 @@
1.12.3 1.12.4