Sleep schedule: store 'next check' timestamp in UTC

SQLite doesn't parse the timezone info, so timestamps should always be in
UTC.
This commit is contained in:
Sybren A. Stüvel 2022-07-18 19:30:17 +02:00
parent 3baac0a2d8
commit 83467e4c60
4 changed files with 22 additions and 6 deletions

View File

@ -63,6 +63,11 @@ func (db *DB) SetWorkerSleepSchedule(ctx context.Context, workerUUID string, sch
schedule.WorkerID = worker.ID schedule.WorkerID = worker.ID
schedule.Worker = worker schedule.Worker = worker
// Only store timestamps in UTC.
if schedule.NextCheck.Location() != time.UTC {
schedule.NextCheck = schedule.NextCheck.UTC()
}
tx := db.gormDB.WithContext(ctx). tx := db.gormDB.WithContext(ctx).
Clauses(clause.OnConflict{ Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "worker_id"}}, Columns: []clause.Column{{Name: "worker_id"}},
@ -73,6 +78,11 @@ func (db *DB) SetWorkerSleepSchedule(ctx context.Context, workerUUID string, sch
} }
func (db *DB) SetWorkerSleepScheduleNextCheck(ctx context.Context, schedule *SleepSchedule) error { func (db *DB) SetWorkerSleepScheduleNextCheck(ctx context.Context, schedule *SleepSchedule) error {
// Only store timestamps in UTC.
if schedule.NextCheck.Location() != time.UTC {
schedule.NextCheck = schedule.NextCheck.UTC()
}
tx := db.gormDB.WithContext(ctx). tx := db.gormDB.WithContext(ctx).
Select("next_check"). Select("next_check").
Updates(schedule) Updates(schedule)
@ -92,10 +102,12 @@ func (db *DB) FetchSleepScheduleWorker(ctx context.Context, schedule *SleepSched
// FetchSleepSchedulesToCheck returns the sleep schedules that are due for a check. // FetchSleepSchedulesToCheck returns the sleep schedules that are due for a check.
func (db *DB) FetchSleepSchedulesToCheck(ctx context.Context) ([]*SleepSchedule, error) { func (db *DB) FetchSleepSchedulesToCheck(ctx context.Context) ([]*SleepSchedule, error) {
log.Trace().Msg("fetching sleep schedules that need checking")
now := db.gormDB.NowFunc() now := db.gormDB.NowFunc()
log.Debug().
Str("timeout", now.String()).
Msg("fetching sleep schedules that need checking")
schedules := []*SleepSchedule{} schedules := []*SleepSchedule{}
tx := db.gormDB.WithContext(ctx). tx := db.gormDB.WithContext(ctx).
Model(&SleepSchedule{}). Model(&SleepSchedule{}).

View File

@ -243,7 +243,7 @@ func TestFetchSleepSchedulesToCheck(t *testing.T) {
ctx, finish, db := persistenceTestFixtures(t, 1*time.Second) ctx, finish, db := persistenceTestFixtures(t, 1*time.Second)
defer finish() defer finish()
mockedNow := mustParseTime("2022-06-07T11:14:47+02:00") mockedNow := mustParseTime("2022-06-07T11:14:47+02:00").UTC()
mockedPast := mockedNow.Add(-10 * time.Second) mockedPast := mockedNow.Add(-10 * time.Second)
mockedFuture := mockedNow.Add(10 * time.Second) mockedFuture := mockedNow.Add(10 * time.Second)

View File

@ -69,7 +69,7 @@ func calculateNextCheck(now time.Time, schedule *persistence.SleepSchedule) time
nextChecks := []time.Time{ nextChecks := []time.Time{
// Always check at the end of the day. // Always check at the end of the day.
calcNext(persistence.TimeOfDay{Hour: 24, Minute: 0}), endOfDay(now),
} }
// No start time means "start of the day", which is already covered by // No start time means "start of the day", which is already covered by
@ -96,3 +96,8 @@ func earliestTime(timestamps []time.Time) time.Time {
} }
return earliest return earliest
} }
// endOfDay returns the next midnight at UTC.
func endOfDay(now time.Time) time.Time {
return time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC).AddDate(0, 0, 1)
}

View File

@ -232,12 +232,11 @@ type TestMocks struct {
func (m *TestMocks) todayAt(hour, minute int) time.Time { func (m *TestMocks) todayAt(hour, minute int) time.Time {
now := m.clock.Now() now := m.clock.Now()
return time.Date(now.Year(), now.Month(), now.Day(), hour, minute, 0, 0, now.Location()) return time.Date(now.Year(), now.Month(), now.Day(), hour, minute, 0, 0, now.Location())
} }
// endOfDay returns midnight of the day after whatever the mocked clock's "now" is set to. // endOfDay returns midnight of the day after whatever the mocked clock's "now" is set to.
func (m *TestMocks) endOfDay() time.Time { func (m *TestMocks) endOfDay() time.Time {
now := m.clock.Now() now := m.clock.Now().UTC()
return time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).AddDate(0, 0, 1) return time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).AddDate(0, 0, 1)
} }