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