do not sync time multiple times

This commit is contained in:
Siyuan 2025-10-08 12:54:48 +00:00
parent f128343187
commit 8cc7ead032
2 changed files with 31 additions and 9 deletions

View File

@ -38,6 +38,7 @@ type TimeSync struct {
rtcLock *sync.Mutex rtcLock *sync.Mutex
syncSuccess bool syncSuccess bool
timer *time.Timer
preCheckFunc PreCheckFunc preCheckFunc PreCheckFunc
preCheckIPv4 PreCheckFunc preCheckIPv4 PreCheckFunc
@ -78,6 +79,7 @@ func NewTimeSync(opts *TimeSyncOptions) *TimeSync {
preCheckIPv4: opts.PreCheckIPv4, preCheckIPv4: opts.PreCheckIPv4,
preCheckIPv6: opts.PreCheckIPv6, preCheckIPv6: opts.PreCheckIPv6,
networkConfig: opts.NetworkConfig, networkConfig: opts.NetworkConfig,
timer: time.NewTimer(timeSyncWaitNetUpInt),
} }
if t.rtcDevicePath != "" { if t.rtcDevicePath != "" {
@ -130,45 +132,51 @@ func (t *TimeSync) getSyncMode() SyncMode {
return syncMode return syncMode
} }
func (t *TimeSync) doTimeSync() { func (t *TimeSync) timeSyncLoop() {
metricTimeSyncStatus.Set(0) metricTimeSyncStatus.Set(0)
for {
// use a timer here instead of sleep
for range t.timer.C {
if ok, err := t.preCheckFunc(); !ok { if ok, err := t.preCheckFunc(); !ok {
if err != nil { if err != nil {
t.l.Error().Err(err).Msg("pre-check failed") t.l.Error().Err(err).Msg("pre-check failed")
} }
time.Sleep(timeSyncWaitNetChkInt) t.timer.Reset(timeSyncWaitNetChkInt)
continue continue
} }
t.l.Info().Msg("syncing system time") t.l.Info().Msg("syncing system time")
start := time.Now() start := time.Now()
err := t.Sync() err := t.sync()
if err != nil { if err != nil {
t.l.Error().Str("error", err.Error()).Msg("failed to sync system time") t.l.Error().Str("error", err.Error()).Msg("failed to sync system time")
// retry after a delay // retry after a delay
timeSyncRetryInterval += timeSyncRetryStep timeSyncRetryInterval += timeSyncRetryStep
time.Sleep(timeSyncRetryInterval) t.timer.Reset(timeSyncRetryInterval)
// reset the retry interval if it exceeds the max interval // reset the retry interval if it exceeds the max interval
if timeSyncRetryInterval > timeSyncRetryMaxInt { if timeSyncRetryInterval > timeSyncRetryMaxInt {
timeSyncRetryInterval = 0 timeSyncRetryInterval = 0
} }
continue continue
} }
isInitialSync := !t.syncSuccess
t.syncSuccess = true t.syncSuccess = true
t.l.Info().Str("now", time.Now().Format(time.RFC3339)). t.l.Info().Str("now", time.Now().Format(time.RFC3339)).
Str("time_taken", time.Since(start).String()). Str("time_taken", time.Since(start).String()).
Bool("is_initial_sync", isInitialSync).
Msg("time sync successful") Msg("time sync successful")
metricTimeSyncStatus.Set(1) metricTimeSyncStatus.Set(1)
time.Sleep(timeSyncInterval) // after the first sync is done t.timer.Reset(timeSyncInterval) // after the first sync is done
} }
} }
func (t *TimeSync) Sync() error { func (t *TimeSync) sync() error {
t.syncLock.Lock() t.syncLock.Lock()
defer t.syncLock.Unlock() defer t.syncLock.Unlock()
@ -256,12 +264,25 @@ Orders:
return nil return nil
} }
// Sync triggers a manual time sync
func (t *TimeSync) Sync() error {
if !t.syncLock.TryLock() {
t.l.Warn().Msg("sync already in progress, skipping")
return nil
}
t.syncLock.Unlock()
return t.sync()
}
// IsSyncSuccess returns true if the system time is synchronized
func (t *TimeSync) IsSyncSuccess() bool { func (t *TimeSync) IsSyncSuccess() bool {
return t.syncSuccess return t.syncSuccess
} }
// Start starts the time sync
func (t *TimeSync) Start() { func (t *TimeSync) Start() {
go t.doTimeSync() go t.timeSyncLoop()
} }
func (t *TimeSync) setSystemTime(now time.Time) error { func (t *TimeSync) setSystemTime(now time.Time) error {

View File

@ -118,6 +118,7 @@ func (l *Link) AddrList(family int) ([]netlink.Addr, error) {
return netlink.AddrList(l.Link, family) return netlink.AddrList(l.Link, family)
} }
// IsSame checks if the link is the same as another link
func (l *Link) IsSame(other *Link) bool { func (l *Link) IsSame(other *Link) bool {
if l == nil || other == nil { if l == nil || other == nil {
return false return false