func (s *ReconSuite) pollConvergence(c *gc.C, peer1, peer2 *recon.Peer, peer1Needs, peer2Needs *cf.ZSet, timeout time.Duration) error { var t tomb.Tomb t.Go(func() error { defer peer1.Stop() defer peer2.Stop() timer := time.NewTimer(timeout) POLLING: for { select { case r1, ok := <-peer1.RecoverChan: if !ok { break POLLING } c.Logf("peer1 recover: %v", r1) peer1.Insert(r1.RemoteElements...) peer1Needs.RemoveSlice(r1.RemoteElements) case r2, ok := <-peer2.RecoverChan: if !ok { break POLLING } c.Logf("peer2 recover: %v", r2) peer2.Insert(r2.RemoteElements...) peer2Needs.RemoveSlice(r2.RemoteElements) case _ = <-timer.C: c.Log("peer1 still needed ", peer1Needs.Len(), ":", peer1Needs) c.Log("peer2 still needed ", peer2Needs.Len(), ":", peer2Needs) return fmt.Errorf("timeout waiting for convergence") default: } if peer1Needs.Len() == 0 && peer2Needs.Len() == 0 { c.Log("all done!") return nil } time.Sleep(ShortDelay) } return fmt.Errorf("set reconciliation did not converge") }) return t.Wait() }