Example #1
0
// WatchValue returns a NotifyWatcher that triggers
// when the given value changes. Its Wait and Err methods
// never return a non-nil error.
func WatchValue(val *voyeur.Value) state.NotifyWatcher {
	n := &notifier{
		w:       val.Watch(),
		changes: make(chan struct{}),
	}
	go n.loop()
	return n
}
Example #2
0
func (s *workerSuite) TestSetMembersErrorIsNotFatal(c *gc.C) {
	st := newFakeState()
	initState(c, st, 3)
	st.session.setStatus(mkStatuses("0p 1s 2s"))
	var isSet voyeur.Value
	count := 0
	setErrorFuncFor("Session.Set", func() error {
		isSet.Set(count)
		count++
		return errors.New("sample")
	})
	s.PatchValue(&initialRetryInterval, 10*time.Microsecond)
	s.PatchValue(&maxRetryInterval, coretesting.ShortWait/4)

	expectedIterations := 0
	for d := initialRetryInterval; d < maxRetryInterval*2; d *= 2 {
		expectedIterations++
	}

	w := newWorker(st, noPublisher{})
	defer func() {
		c.Check(worker.Stop(w), gc.IsNil)
	}()
	isSetWatcher := isSet.Watch()

	n0 := mustNext(c, isSetWatcher).(int)
	time.Sleep(maxRetryInterval * 2)
	n1 := mustNext(c, isSetWatcher).(int)

	// The worker should have backed off exponentially...
	c.Assert(n1-n0, jc.LessThan, expectedIterations+1)
	c.Logf("actual iterations %d; expected iterations %d", n1-n0, expectedIterations)

	// ... but only up to the maximum retry interval
	n0 = mustNext(c, isSetWatcher).(int)
	time.Sleep(maxRetryInterval * 2)
	n1 = mustNext(c, isSetWatcher).(int)

	c.Assert(n1-n0, jc.LessThan, 3)
}