Merge lp:~themue/juju-core/026-transaction-resumer into lp:~go-bot/juju-core/trunk

Proposed by Frank Mueller
Status: Merged
Approved by: Frank Mueller
Approved revision: no longer in the source branch.
Merged at revision: 1312
Proposed branch: lp:~themue/juju-core/026-transaction-resumer
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 175 lines (+149/-0)
4 files modified
state/state.go (+5/-0)
worker/resumer/export_test.go (+16/-0)
worker/resumer/resumer.go (+71/-0)
worker/resumer/resumer_test.go (+57/-0)
To merge this branch: bzr merge lp:~themue/juju-core/026-transaction-resumer
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+169234@code.launchpad.net

Commit message

resumer: periodically resume transaction

The resumer is a periodically worker which is
resuming pending transactions in state each
minute.

https://codereview.appspot.com/10266043/

Description of the change

resumer: periodically resume transaction

The resumer is a periodically worker which is
resuming pending transactions in state each
minute.

https://codereview.appspot.com/10266043/

To post a comment you must log in.
Revision history for this message
Frank Mueller (themue) wrote :
Download full text (3.4 KiB)

Reviewers: mp+169234_code.launchpad.net,

Message:
Please take a look.

Description:
resumer: periodically resume transaction

The resumer is a periodically worker which is
resuming pending transactions in state each
minute.

https://code.launchpad.net/~themue/juju-core/026-transaction-resumer/+merge/169234

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/10266043/

Affected files:
   A [revision details]
   M state/state.go
   A worker/resumer/resumer.go
   A worker/resumer/resumer_test.go

Index: [revision details]
=== added file '[revision details]'
--- [revision details] 2012-01-01 00:00:00 +0000
+++ [revision details] 2012-01-01 00:00:00 +0000
@@ -0,0 +1,2 @@
+Old revision: tarmac-20130613115315-e58eqa122kc07o1a
+New revision: <email address hidden>

Index: state/state.go
=== modified file 'state/state.go'
--- state/state.go 2013-06-12 02:45:22 +0000
+++ state/state.go 2013-06-13 15:29:49 +0000
@@ -1123,6 +1123,11 @@
   return nil
  }

+// ResumeTransactions resumes all pending transactions.
+func (st *State) ResumeTransactions() error {
+ return st.runner.ResumeAll()
+}
+
  var tagPrefix = map[byte]string{
   'm': "machine-",
   's': "service-",

Index: worker/resumer/resumer.go
=== added file 'worker/resumer/resumer.go'
--- worker/resumer/resumer.go 1970-01-01 00:00:00 +0000
+++ worker/resumer/resumer.go 2013-06-13 15:29:49 +0000
@@ -0,0 +1,62 @@
+// Copyright 2012, 2013 Canonical Ltd.
+// Licensed under the AGPLv3, see LICENCE file for details.
+
+package resumer
+
+import (
+ "fmt"
+ "launchpad.net/juju-core/log"
+ "launchpad.net/juju-core/state"
+ "launchpad.net/tomb"
+ "time"
+)
+
+// interval sets how often the resuming is called.
+const interval = time.Minute
+
+// Resumer is responsible for a periodical resuming of pending
transactions.
+type Resumer struct {
+ tomb tomb.Tomb
+ st *state.State
+}
+
+// NewResumer ...
+func NewResumer(st *state.State) *Resumer {
+ rr := &Resumer{st: st}
+ go func() {
+ defer rr.tomb.Done()
+ rr.tomb.Kill(rr.loop())
+ }()
+ return rr
+}
+
+func (rr *Resumer) String() string {
+ return fmt.Sprintf("resumer")
+}
+
+func (rr *Resumer) Kill() {
+ rr.tomb.Kill(nil)
+}
+
+func (rr *Resumer) Stop() error {
+ rr.tomb.Kill(nil)
+ return rr.tomb.Wait()
+}
+
+func (rr *Resumer) Wait() error {
+ return rr.tomb.Wait()
+}
+
+func (rr *Resumer) loop() error {
+ for {
+ select {
+ case <-rr.tomb.Dying():
+ return tomb.ErrDying
+ case <-time.After(interval):
+ if err := rr.st.ResumeTransactions(); err != nil {
+ log.Errorf("worker/resumer: cannot resume transactions: %v", err)
+ }
+ }
+ }
+ panic("unreachable")
+}

Index: worker/resumer/resumer_test.go
=== added file 'worker/resumer/resumer_test.go'
--- worker/resumer/resumer_test.go 1970-01-01 00:00:00 +0000
+++ worker/resumer/resumer_test.go 2013-06-13 15:29:49 +0000
@@ -0,0 +1,28 @@
+// Copyright 2013 Canonical Ltd.
+// Licensed under the AGPLv3, see LICENCE file for details.
+
+package resumer_test
+
+import (
+ . "launchpad.net/gocheck"
+ "launchpad.net/juju-core/juju/testing"
+ coretesting "launchpad.net/juju-core/testing"
+ "launchpad.net/juju-c...

Read more...

Revision history for this message
William Reade (fwereade) wrote :
Revision history for this message
Roger Peppe (rogpeppe) wrote :

LGTM with updated doc comment and better tests.

https://codereview.appspot.com/10266043/diff/1/worker/resumer/resumer.go
File worker/resumer/resumer.go (right):

https://codereview.appspot.com/10266043/diff/1/worker/resumer/resumer.go#newcode23
worker/resumer/resumer.go:23: // NewResumer ...
... ?

https://codereview.appspot.com/10266043/diff/1/worker/resumer/resumer.go#newcode57
worker/resumer/resumer.go:57: log.Errorf("worker/resumer: cannot resume
transactions: %v", err)
to be consistent with the other workers, this error would be fatal.
any particular reason why it's not?

https://codereview.appspot.com/10266043/diff/1/worker/resumer/resumer_test.go
File worker/resumer/resumer_test.go (right):

https://codereview.appspot.com/10266043/diff/1/worker/resumer/resumer_test.go#newcode25
worker/resumer/resumer_test.go:25: rr := resumer.NewResumer(s.State)
how does this test that ResumeTransactions is actually called? (given
that it actually isn't in this test)

https://codereview.appspot.com/10266043/

Revision history for this message
William Reade (fwereade) wrote :

quick responses to rog's comments

https://codereview.appspot.com/10266043/diff/1/worker/resumer/resumer.go
File worker/resumer/resumer.go (right):

https://codereview.appspot.com/10266043/diff/1/worker/resumer/resumer.go#newcode57
worker/resumer/resumer.go:57: log.Errorf("worker/resumer: cannot resume
transactions: %v", err)
On 2013/06/14 15:46:07, rog wrote:
> to be consistent with the other workers, this error would be fatal.
> any particular reason why it's not?

I don't think an error is important enough to justify retrying so much
sooner.

https://codereview.appspot.com/10266043/diff/1/worker/resumer/resumer_test.go
File worker/resumer/resumer_test.go (right):

https://codereview.appspot.com/10266043/diff/1/worker/resumer/resumer_test.go#newcode25
worker/resumer/resumer_test.go:25: rr := resumer.NewResumer(s.State)
On 2013/06/14 15:46:07, rog wrote:
> how does this test that ResumeTransactions is actually called? (given
that it
> actually isn't in this test)

Ha. We should ofc use `type Resumer interface { ResumeTransactions()
error}` and check at least that a suitable method gets called on a mock.

https://codereview.appspot.com/10266043/

Revision history for this message
Frank Mueller (themue) wrote :

Please take a look.

https://codereview.appspot.com/10266043/diff/1/worker/resumer/resumer.go
File worker/resumer/resumer.go (right):

https://codereview.appspot.com/10266043/diff/1/worker/resumer/resumer.go#newcode23
worker/resumer/resumer.go:23: // NewResumer ...
On 2013/06/14 15:46:07, rog wrote:
> ... ?

Done.

https://codereview.appspot.com/10266043/

Revision history for this message
William Reade (fwereade) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'state/state.go'
2--- state/state.go 2013-06-18 19:49:00 +0000
3+++ state/state.go 2013-06-19 11:55:35 +0000
4@@ -1203,6 +1203,11 @@
5 return nil
6 }
7
8+// ResumeTransactions resumes all pending transactions.
9+func (st *State) ResumeTransactions() error {
10+ return st.runner.ResumeAll()
11+}
12+
13 var tagPrefix = map[byte]string{
14 'm': "machine-",
15 's': "service-",
16
17=== added directory 'worker/resumer'
18=== added file 'worker/resumer/export_test.go'
19--- worker/resumer/export_test.go 1970-01-01 00:00:00 +0000
20+++ worker/resumer/export_test.go 2013-06-19 11:55:35 +0000
21@@ -0,0 +1,16 @@
22+// Copyright 2012, 2013 Canonical Ltd.
23+// Licensed under the AGPLv3, see LICENCE file for details.
24+
25+package resumer
26+
27+import (
28+ "time"
29+)
30+
31+func SetInterval(i time.Duration) {
32+ interval = i
33+}
34+
35+func RestoreInterval() {
36+ interval = defaultInterval
37+}
38
39=== added file 'worker/resumer/resumer.go'
40--- worker/resumer/resumer.go 1970-01-01 00:00:00 +0000
41+++ worker/resumer/resumer.go 2013-06-19 11:55:35 +0000
42@@ -0,0 +1,71 @@
43+// Copyright 2012, 2013 Canonical Ltd.
44+// Licensed under the AGPLv3, see LICENCE file for details.
45+
46+package resumer
47+
48+import (
49+ "fmt"
50+ "launchpad.net/juju-core/log"
51+ "launchpad.net/tomb"
52+ "time"
53+)
54+
55+// defaultInterval is the standard value for the interval setting.
56+const defaultInterval = time.Minute
57+
58+// interval sets how often the resuming is called.
59+var interval = defaultInterval
60+
61+// TransactionResumer defines the interface for types capable to
62+// resume transactions.
63+type TransactionResumer interface {
64+ // ResumeTransactions resumes all pending transactions.
65+ ResumeTransactions() error
66+}
67+
68+// Resumer is responsible for a periodical resuming of pending transactions.
69+type Resumer struct {
70+ tomb tomb.Tomb
71+ tr TransactionResumer
72+}
73+
74+// NewResumer periodically resumes pending transactions.
75+func NewResumer(tr TransactionResumer) *Resumer {
76+ rr := &Resumer{tr: tr}
77+ go func() {
78+ defer rr.tomb.Done()
79+ rr.tomb.Kill(rr.loop())
80+ }()
81+ return rr
82+}
83+
84+func (rr *Resumer) String() string {
85+ return fmt.Sprintf("resumer")
86+}
87+
88+func (rr *Resumer) Kill() {
89+ rr.tomb.Kill(nil)
90+}
91+
92+func (rr *Resumer) Stop() error {
93+ rr.tomb.Kill(nil)
94+ return rr.tomb.Wait()
95+}
96+
97+func (rr *Resumer) Wait() error {
98+ return rr.tomb.Wait()
99+}
100+
101+func (rr *Resumer) loop() error {
102+ for {
103+ select {
104+ case <-rr.tomb.Dying():
105+ return tomb.ErrDying
106+ case <-time.After(interval):
107+ if err := rr.tr.ResumeTransactions(); err != nil {
108+ log.Errorf("worker/resumer: cannot resume transactions: %v", err)
109+ }
110+ }
111+ }
112+ panic("unreachable")
113+}
114
115=== added file 'worker/resumer/resumer_test.go'
116--- worker/resumer/resumer_test.go 1970-01-01 00:00:00 +0000
117+++ worker/resumer/resumer_test.go 2013-06-19 11:55:35 +0000
118@@ -0,0 +1,57 @@
119+// Copyright 2013 Canonical Ltd.
120+// Licensed under the AGPLv3, see LICENCE file for details.
121+
122+package resumer_test
123+
124+import (
125+ stdtesting "testing"
126+ "time"
127+
128+ . "launchpad.net/gocheck"
129+ "launchpad.net/juju-core/juju/testing"
130+ coretesting "launchpad.net/juju-core/testing"
131+ "launchpad.net/juju-core/worker/resumer"
132+)
133+
134+func TestPackage(t *stdtesting.T) {
135+ coretesting.MgoTestPackage(t)
136+}
137+
138+type ResumerSuite struct {
139+ testing.JujuConnSuite
140+}
141+
142+var _ = Suite(&ResumerSuite{})
143+
144+func (s *ResumerSuite) TestRunStopWithState(c *C) {
145+ // Test with state ensures that state fulfills the
146+ // TransactionResumer interface.
147+ rr := resumer.NewResumer(s.State)
148+
149+ c.Assert(rr.Stop(), IsNil)
150+}
151+
152+func (s *ResumerSuite) TestResumerCalls(c *C) {
153+ // Shorter interval and mock help to count
154+ // the resumer calls in a given timespan.
155+ resumer.SetInterval(10 * time.Millisecond)
156+ defer resumer.RestoreInterval()
157+
158+ tr := &transactionResumerMock{0}
159+ rr := resumer.NewResumer(tr)
160+ defer func() { c.Assert(rr.Stop(), IsNil) }()
161+
162+ time.Sleep(55 * time.Millisecond)
163+ c.Assert(tr.counter, Equals, 5)
164+}
165+
166+// transactionResumerMock is used to check the
167+// calls of ResumeTransactions().
168+type transactionResumerMock struct {
169+ counter int
170+}
171+
172+func (t *transactionResumerMock) ResumeTransactions() error {
173+ t.counter++
174+ return nil
175+}

Subscribers

People subscribed via source and target branches

to status/vote changes: