diff --git a/agent/consul/state/tombstone_gc.go b/agent/consul/state/tombstone_gc.go index 459321bda3..3b141c2bdf 100644 --- a/agent/consul/state/tombstone_gc.go +++ b/agent/consul/state/tombstone_gc.go @@ -135,7 +135,9 @@ func (t *TombstoneGC) PendingExpiration() bool { // granularity that is set. This allows us to bin expirations and avoid a ton // of timers. func (t *TombstoneGC) nextExpires() time.Time { - expires := time.Now().Add(t.ttl) + // The Round(0) call here is to shed the monotonic time so that we + // can safely use these as map keys. See #3670 for more details. + expires := time.Now().Add(t.ttl).Round(0) remain := expires.UnixNano() % int64(t.granularity) adj := expires.Add(t.granularity - time.Duration(remain)) return adj diff --git a/agent/consul/state/tombstone_gc_test.go b/agent/consul/state/tombstone_gc_test.go index b05d0c2773..d1aa5581d6 100644 --- a/agent/consul/state/tombstone_gc_test.go +++ b/agent/consul/state/tombstone_gc_test.go @@ -1,7 +1,6 @@ package state import ( - "os" "testing" "time" ) @@ -24,10 +23,6 @@ func TestTombstoneGC_invalid(t *testing.T) { } func TestTombstoneGC(t *testing.T) { - if os.Getenv("TRAVIS") == "true" { - t.Skip("GC test is flaky on travis-ci (see #3670)") - } - ttl := 20 * time.Millisecond gran := 5 * time.Millisecond gc, err := NewTombstoneGC(ttl, gran) @@ -65,6 +60,14 @@ func TestTombstoneGC(t *testing.T) { gc.Hint(120) gc.Hint(125) + // Check that we only have a single bin (this cross-checks #3670). + gc.Lock() + bins := len(gc.expires) + gc.Unlock() + if got, want := bins, 1; got != want { + t.Fatalf("got %d want %d", got, want) + } + if !gc.PendingExpiration() { t.Fatalf("should be pending") }