Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(971)

Side by Side Diff: worker/stringsworker.go

Issue 12198044: worker: Introducing StringsWorker (Closed)
Patch Set: Created 11 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 Canonical Ltd.
2 // Licensed under the AGPLv3, see LICENCE file for details.
3
4 package worker
5
6 import (
7 "launchpad.net/tomb"
8
9 "launchpad.net/juju-core/state/api"
10 "launchpad.net/juju-core/state/watcher"
11 )
12
13 // stringsWorker is the internal implementation of the StringsWorker
14 // interface
15 type stringsWorker struct {
16 tomb tomb.Tomb
17
18 // handler is what will be called when events are triggered.
19 handler StringsWatchHandler
20
21 // closedHandler is set to watcher.MustErr, but that panic()s, so
22 // we let the test suite override it.
23 closedHandler func(watcher.Errer) error
rog 2013/08/01 11:18:47 s/closedHandler/mustErr/
dimitern 2013/08/01 12:53:54 Done.
24 }
25
26 // StringsWorker encapsulates the logic for a worker which is based on
27 // a StringsWatcher. We do a bit of setup, and then spin waiting for
28 // the watcher to trigger of for use to be killed, and then torn down
29 // cleanly.
30 type StringsWorker CommonWorker
31
32 // StringsWatchHandler implements the business logic triggered as part
33 // of watching a StringsWorker.
34 type StringsWatchHandler interface {
35 // SetUp starts the handler, this should create the watcher we
36 // will be waiting on for more events. SetUp can return a Watcher
37 // even if there is an error, and StringsWorker will make sure to
38 // stop the Watcher.
39 SetUp() (api.StringsWatcher, error)
40
41 // TearDown should cleanup any resources that are left around
42 TearDown() error
43
44 // Handle is called when the Watcher has indicated there are
45 // changes, do whatever work is necessary to process it
46 Handle(changes []string) error
47
48 // String is used when reporting. It is required because
49 // StringsWatcher is wrapping the StringsWatchHandler, but the
50 // StringsWatchHandler is the interesting (identifying) logic.
51 String() string
rog 2013/08/01 11:18:47 d
dimitern 2013/08/01 12:53:54 Done.
52 }
53
54 // NewStringsWorker starts a new worker running the business logic
55 // from the handler. The worker loop is started in another goroutine
56 // as a side effect of calling this.
57 func NewStringsWorker(handler StringsWatchHandler) StringsWorker {
rog 2013/08/01 11:18:47 I think this should return a Worker.
dimitern 2013/08/01 12:53:54 Done.
58 sw := &stringsWorker{
59 handler: handler,
60 closedHandler: watcher.MustErr,
61 }
62 go func() {
63 defer sw.tomb.Done()
64 sw.tomb.Kill(sw.loop())
65 }()
66 return sw
67 }
68
69 // Kill the loop with no-error
70 func (sw *stringsWorker) Kill() {
71 sw.tomb.Kill(nil)
72 }
73
74 // Stop kils the worker and waits for it to exit
75 func (sw *stringsWorker) Stop() error {
rog 2013/08/01 11:18:47 d
dimitern 2013/08/01 12:53:54 Done.
76 sw.tomb.Kill(nil)
77 return sw.tomb.Wait()
78 }
79
80 // Wait for the looping to finish
81 func (sw *stringsWorker) Wait() error {
82 return sw.tomb.Wait()
83 }
84
85 // String returns a nice description of this worker, taken from the
86 // underlying StringsWatchHandler
87 func (sw *stringsWorker) String() string {
rog 2013/08/01 11:18:47 d
dimitern 2013/08/01 12:53:54 Done.
88 return sw.handler.String()
89 }
90
91 func stringsHandlerTearDown(handler StringsWatchHandler, t *tomb.Tomb) {
rog 2013/08/01 11:18:47 d (given a generic version elsewhere)
dimitern 2013/08/01 12:53:54 Done.
92 // Tear down the handler, but ensure any error is propagated
93 if err := handler.TearDown(); err != nil {
94 t.Kill(err)
95 }
96 }
97
98 func (sw *stringsWorker) loop() error {
99 var w api.StringsWatcher
100 var err error
rog 2013/08/01 11:18:47 Rather than explicitly declaring these, how about:
dimitern 2013/08/01 12:53:54 Done.
101 defer stringsHandlerTearDown(sw.handler, &sw.tomb)
102 if w, err = sw.handler.SetUp(); err != nil {
103 if w != nil {
104 // We don't bother to propogate an error, because we
105 // already have an error
106 w.Stop()
107 }
108 return err
109 }
110 defer watcher.Stop(w, &sw.tomb)
111 for {
112 select {
113 case <-sw.tomb.Dying():
114 return tomb.ErrDying
115 case changes, ok := <-w.Changes():
116 if !ok {
117 return sw.closedHandler(w)
118 }
119 if err := sw.handler.Handle(changes); err != nil {
120 return err
121 }
122 }
123 }
124 }
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b