github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/core/watcher/interface.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package watcher 5 6 import ( 7 "github.com/juju/worker/v3" 8 ) 9 10 // CoreWatcher encodes some features of a watcher. The most obvious one: 11 // 12 // Changes() <-chan <T> 13 // 14 // ...can't be expressed cleanly; and this is annoying because every such chan 15 // needs to share common behaviours for the abstraction to be generally helpful. 16 // The critical features of a Changes chan are as follows: 17 // 18 // - The channel should never be closed. 19 // 20 // - The channel should send a single baseline value, representing the change 21 // from a nil state; and subsequently send values representing deltas from 22 // whatever had previously been sent. 23 // 24 // - The channel should really never be closed. Many existing watchers *do* 25 // close their channels when the watcher stops; this is harmful because it 26 // mixes lifetime-handling into change-handling at the cost of clarity (and 27 // in some cases correctness). So long as a watcher implements Worker, it 28 // can be safely managed with the worker/catacomb package; of course, all 29 // sensible clients will still check for closed channels (never trust a 30 // contract...) but can treat that scenario as a simple error. 31 // 32 // (This rule only applies to watchers outside the API; watchers inside the 33 // API boundary need to close their changes channel so that the .Next() 34 // method implementations inside the API server (see apiserver/watcher.go) 35 // finish correctly.) 36 // 37 // To convert a state/watcher.Watcher to a CoreWatcher, ensure that the watcher 38 // no longer closes its Changes() channel; and replace Stop() and Err() with the 39 // usual worker boilerplate. Namely: 40 // 41 // // Kill is part of the worker.Worker interface. 42 // func (w *watcher) Kill() { 43 // w.tomb.Kill(nil) 44 // } 45 // 46 // // Wait is part of the worker.Worker interface. 47 // func (w *watcher) Wait() error { 48 // return w.tomb.Wait() 49 // } 50 // 51 // Tests using state/testing/{$Kind}WatcherC should be converted to use the 52 // equivalents in watcher/watchertest. 53 type CoreWatcher interface { 54 worker.Worker 55 }