vitess.io/vitess@v0.16.2/go/vt/vttablet/tabletserver/repltracker/poller.go (about)

     1  /*
     2  Copyright 2020 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package repltracker
    18  
    19  import (
    20  	"sync"
    21  	"time"
    22  
    23  	"vitess.io/vitess/go/stats"
    24  
    25  	"vitess.io/vitess/go/vt/mysqlctl"
    26  	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
    27  	"vitess.io/vitess/go/vt/vterrors"
    28  )
    29  
    30  var replicationLagSeconds = stats.NewGauge("replicationLagSec", "replication lag in seconds")
    31  
    32  type poller struct {
    33  	mysqld mysqlctl.MysqlDaemon
    34  
    35  	mu           sync.Mutex
    36  	lag          time.Duration
    37  	timeRecorded time.Time
    38  }
    39  
    40  func (p *poller) InitDBConfig(mysqld mysqlctl.MysqlDaemon) {
    41  	p.mysqld = mysqld
    42  }
    43  
    44  func (p *poller) Status() (time.Duration, error) {
    45  	p.mu.Lock()
    46  	defer p.mu.Unlock()
    47  
    48  	status, err := p.mysqld.ReplicationStatus()
    49  	if err != nil {
    50  		return 0, err
    51  	}
    52  
    53  	// If replication is not currently running or we don't know what the lag is -- most commonly
    54  	// because the replica mysqld is in the process of trying to start replicating from its source
    55  	// but it hasn't yet reached the point where it can calculate the seconds_behind_master
    56  	// value and it's thus NULL -- then we will estimate the lag ourselves using the last seen
    57  	// value + the time elapsed since.
    58  	if !status.Healthy() || status.ReplicationLagUnknown {
    59  		if p.timeRecorded.IsZero() {
    60  			return 0, vterrors.Errorf(vtrpcpb.Code_UNAVAILABLE, "replication is not running")
    61  		}
    62  		return time.Since(p.timeRecorded) + p.lag, nil
    63  	}
    64  
    65  	p.lag = time.Duration(status.ReplicationLagSeconds) * time.Second
    66  	p.timeRecorded = time.Now()
    67  	replicationLagSeconds.Set(int64(p.lag.Seconds()))
    68  	return p.lag, nil
    69  }