fix: prevent duplicate summaries from being counted twice (resolve #179)

This commit is contained in:
Ferdinand Mütsch 2021-04-19 20:48:07 +02:00
parent 0e3ce1e9e4
commit 1a10a4fb21
3 changed files with 58 additions and 1 deletions

View File

@ -3,6 +3,7 @@ package services
import (
"crypto/md5"
"errors"
"github.com/emvi/logbuch"
"github.com/muety/wakapi/config"
"github.com/muety/wakapi/models"
"github.com/muety/wakapi/repositories"
@ -236,7 +237,15 @@ func (srv *SummaryService) mergeSummaries(summaries []*models.Summary) (*models.
Machines: make([]*models.SummaryItem, 0),
}
var processed = map[int64]bool{}
for _, s := range summaries {
hash := s.FromTime.T().UnixNano() ^ s.ToTime.T().UnixNano()
if _, found := processed[hash]; found {
logbuch.Warn("summary from %v to %v (user '%s') was attempted to be processed more often than once", s.FromTime, s.ToTime, s.UserID)
continue
}
if s.UserID != finalSummary.UserID {
return nil, errors.New("users don't match")
}
@ -254,6 +263,8 @@ func (srv *SummaryService) mergeSummaries(summaries []*models.Summary) (*models.
finalSummary.Editors = srv.mergeSummaryItems(finalSummary.Editors, s.Editors)
finalSummary.OperatingSystems = srv.mergeSummaryItems(finalSummary.OperatingSystems, s.OperatingSystems)
finalSummary.Machines = srv.mergeSummaryItems(finalSummary.Machines, s.Machines)
processed[hash] = true
}
finalSummary.FromTime = models.CustomTime(minTime)

View File

@ -291,6 +291,52 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Retrieve() {
suite.HeartbeatService.AssertNumberOfCalls(suite.T(), "GetAllWithin", 2+1+1)
}
func (suite *SummaryServiceTestSuite) TestSummaryService_Retrieve_DuplicateSummaries() {
sut := NewSummaryService(suite.SummaryRepository, suite.HeartbeatService, suite.AliasService)
var (
summaries []*models.Summary
from time.Time
to time.Time
result *models.Summary
err error
)
from, to = suite.TestStartTime.Add(-12*time.Hour), suite.TestStartTime.Add(12*time.Hour)
summaries = []*models.Summary{
{
ID: uint(rand.Uint32()),
UserID: TestUserId,
FromTime: models.CustomTime(from.Add(10 * time.Minute)),
ToTime: models.CustomTime(to.Add(-10 * time.Minute)),
Projects: []*models.SummaryItem{
{
Type: models.SummaryProject,
Key: TestProject1,
Total: 45 * time.Minute / time.Second, // hack
},
},
Languages: []*models.SummaryItem{},
Editors: []*models.SummaryItem{},
OperatingSystems: []*models.SummaryItem{},
Machines: []*models.SummaryItem{},
},
}
summaries = append(summaries, &(*summaries[0])) // add same summary again -> mustn't be counted twice!
suite.SummaryRepository.On("GetByUserWithin", suite.TestUser, from, to).Return(summaries, nil)
suite.HeartbeatService.On("GetAllWithin", from, summaries[0].FromTime.T(), suite.TestUser).Return([]*models.Heartbeat{}, nil)
suite.HeartbeatService.On("GetAllWithin", summaries[0].ToTime.T(), to, suite.TestUser).Return([]*models.Heartbeat{}, nil)
result, err = sut.Retrieve(from, to, suite.TestUser)
assert.Nil(suite.T(), err)
assert.NotNil(suite.T(), result)
assert.Len(suite.T(), result.Projects, 1)
assert.Equal(suite.T(), summaries[0].Projects[0].Total*time.Second, result.TotalTime())
suite.HeartbeatService.AssertNumberOfCalls(suite.T(), "GetAllWithin", 2)
}
func (suite *SummaryServiceTestSuite) TestSummaryService_Aliased() {
sut := NewSummaryService(suite.SummaryRepository, suite.HeartbeatService, suite.AliasService)

View File

@ -1 +1 @@
1.26.5
1.26.6