diff --git a/cache.go b/cache.go index 2bd93f3..4e679b8 100644 --- a/cache.go +++ b/cache.go @@ -97,8 +97,11 @@ func (c *cache) Put(svc *Service, now time.Time) { } func (c *cache) setNow(now time.Time) { - if now.Before(c.now) { - return // Time jumped backwards, not allowed + if !now.After(c.now) { + // Time jumped backwards. Increment instead to preserve causality while we wait for + // the clock to sync up. Existing expiries will be delayed, but this amount should be + // miniscule. + now = c.now.Add(1) } c.now = now } diff --git a/client.go b/client.go index bb82da4..d992937 100644 --- a/client.go +++ b/client.go @@ -67,7 +67,10 @@ loop: for { var ( isPeriodic bool - now time.Time + + // Use wall time exclusively in order to restore accurate state when waking from sleep, + // (time jumps forward) such as cache expiry. + now time.Time ) select { case <-c.reload: @@ -82,12 +85,11 @@ loop: } c.opts.logger.Debug("reload", "ifaces", c.conn.ifaces) case msg, ok := <-msgCh: - now = time.Now() + now = time.Now().Round(0) if !ok { break loop } - // Handle the message _ = c.handleQuery(msg) if c.handleResponse(now, msg) && timer.Stop() { // If the cache was touched, we want the update soon @@ -95,14 +97,10 @@ loop: } continue case now = <-timer.C: + now = now.Round(0) } // Invariant: the timer is stopped. - // Use wall time exclusively in order to restore accurate state when waking from sleep, - // (time jumps forward) such as cache expiry. However, the user still needs to monitor time - // and reload in order to reset the periodic announcements and queries. - now = now.Round(0) - isPeriodic = bo.advance(now) // Publish initial announcements