@@ -36,6 +36,7 @@ import (
3636 "github.com/lightningnetwork/lnd/channeldb/models"
3737 "github.com/lightningnetwork/lnd/channelnotifier"
3838 "github.com/lightningnetwork/lnd/clock"
39+ "github.com/lightningnetwork/lnd/cluster"
3940 "github.com/lightningnetwork/lnd/contractcourt"
4041 "github.com/lightningnetwork/lnd/discovery"
4142 "github.com/lightningnetwork/lnd/feature"
@@ -484,8 +485,8 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
484485 nodeKeyDesc * keychain.KeyDescriptor ,
485486 chansToRestore walletunlocker.ChannelsToRecover ,
486487 chanPredicate chanacceptor.ChannelAcceptor ,
487- torController * tor.Controller , tlsManager * TLSManager ) ( * server ,
488- error ) {
488+ torController * tor.Controller , tlsManager * TLSManager ,
489+ leaderElector cluster. LeaderElector ) ( * server , error ) {
489490
490491 var (
491492 err error
@@ -1674,7 +1675,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
16741675 }
16751676
16761677 // Create liveness monitor.
1677- s .createLivenessMonitor (cfg , cc )
1678+ s .createLivenessMonitor (cfg , cc , leaderElector )
16781679
16791680 // Create the connection manager which will be responsible for
16801681 // maintaining persistent outbound connections and also accepting new
@@ -1721,7 +1722,9 @@ func (s *server) signAliasUpdate(u *lnwire.ChannelUpdate) (*ecdsa.Signature,
17211722//
17221723// If a health check has been disabled by setting attempts to 0, our monitor
17231724// will not run it.
1724- func (s * server ) createLivenessMonitor (cfg * Config , cc * chainreg.ChainControl ) {
1725+ func (s * server ) createLivenessMonitor (cfg * Config , cc * chainreg.ChainControl ,
1726+ leaderElector cluster.LeaderElector ) {
1727+
17251728 chainBackendAttempts := cfg .HealthChecks .ChainCheck .Attempts
17261729 if cfg .Bitcoin .Node == "nochainbackend" {
17271730 srvrLog .Info ("Disabling chain backend checks for " +
@@ -1837,6 +1840,49 @@ func (s *server) createLivenessMonitor(cfg *Config, cc *chainreg.ChainControl) {
18371840 checks = append (checks , remoteSignerConnectionCheck )
18381841 }
18391842
1843+ // If we have a leader elector, we add a health check to ensure we are
1844+ // still the leader. During normal operation, we should always be the
1845+ // leader, but there are circumstances where this may change, such as
1846+ // when we lose network connectivity for long enough expiring out lease.
1847+ if leaderElector != nil {
1848+ leaderCheck := healthcheck .NewObservation (
1849+ "leader status" ,
1850+ func () error {
1851+ // Check if we are still the leader. Note that
1852+ // we don't need to use a timeout context here
1853+ // as the healthcheck observer will handle the
1854+ // timeout case for us.
1855+ timeoutCtx , cancel := context .WithTimeout (
1856+ context .Background (),
1857+ cfg .HealthChecks .LeaderCheck .Timeout ,
1858+ )
1859+ defer cancel ()
1860+
1861+ leader , err := leaderElector .IsLeader (
1862+ timeoutCtx ,
1863+ )
1864+ if err != nil {
1865+ return fmt .Errorf ("unable to check if " +
1866+ "still leader: %v" , err )
1867+ }
1868+
1869+ if ! leader {
1870+ srvrLog .Debug ("Not the current leader" )
1871+ return fmt .Errorf ("not the current " +
1872+ "leader" )
1873+ }
1874+
1875+ return nil
1876+ },
1877+ cfg .HealthChecks .LeaderCheck .Interval ,
1878+ cfg .HealthChecks .LeaderCheck .Timeout ,
1879+ cfg .HealthChecks .LeaderCheck .Backoff ,
1880+ cfg .HealthChecks .LeaderCheck .Attempts ,
1881+ )
1882+
1883+ checks = append (checks , leaderCheck )
1884+ }
1885+
18401886 // If we have not disabled all of our health checks, we create a
18411887 // liveness monitor with our configured checks.
18421888 s .livenessMonitor = healthcheck .NewMonitor (
0 commit comments