/
check.go
75 lines (67 loc) · 1.95 KB
/
check.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package lease
import (
"github.com/juju/errors"
"github.com/juju/juju/core/lease"
)
// token implements lease.Token.
type token struct {
leaseKey lease.Key
holderName string
secretary Secretary
checks chan<- check
stop <-chan struct{}
}
// Check is part of the lease.Token interface.
func (t token) Check() error {
// This validation, which could be done at Token creation time, is deferred
// until this point for historical reasons. In particular, this code was
// extracted from a *leadership* implementation which has a LeadershipCheck
// method returning a token; if it returned an error as well it would seem
// to imply that the method implemented a check itself, rather than a check
// factory.
//
// Fixing that would be great but seems out of scope.
if err := t.secretary.CheckLease(t.leaseKey); err != nil {
return errors.Annotatef(err, "cannot check lease %q", t.leaseKey.Lease)
}
if err := t.secretary.CheckHolder(t.holderName); err != nil {
return errors.Annotatef(err, "cannot check holder %q", t.holderName)
}
return check{
leaseKey: t.leaseKey,
holderName: t.holderName,
response: make(chan error),
stop: t.stop,
}.invoke(t.checks)
}
// check is used to deliver lease-check requests to a manager's loop
// goroutine on behalf of a token (as returned by LeadershipCheck).
type check struct {
leaseKey lease.Key
holderName string
response chan error
stop <-chan struct{}
}
// invoke sends the check on the supplied channel and waits for an error
// response.
func (c check) invoke(ch chan<- check) error {
for {
select {
case <-c.stop:
return errStopped
case ch <- c:
ch = nil
case err := <-c.response:
return errors.Trace(err)
}
}
}
// respond notifies the originating invoke of completion status.
func (c check) respond(err error) {
select {
case <-c.stop:
case c.response <- err:
}
}