func (w *dbWatcher) periodicRemoteDBProbing() {
	defer w.wg.Done()
	w.probeRemoteDB()
	for {
		select {
		case <-time.After(w.remoteDBProbingInterval):
			w.probeRemoteDB()
		case <-w.ctx.Done():
			return
		}
	}
}
periodicRemoteDBProbing runs in a separate go routine a period probing
of the connection to remoteDB.
package controller
import (
	"context"
	"errors"
	"reflect"
	"strings"
	"sync"
	"time"
	"github.com/golang/protobuf/proto"
	"go.ligato.io/cn-infra/v2/datasync"
	"go.ligato.io/cn-infra/v2/db/keyval"
	"go.ligato.io/cn-infra/v2/logging"
	"go.ligato.io/cn-infra/v2/servicelabel"
	"go.ligato.io/vpp-agent/v3/plugins/orchestrator"
	"github.com/contiv/vpp/dbresources"
	"github.com/contiv/vpp/plugins/controller/api"
	"github.com/contiv/vpp/plugins/ksr"
)
const (
	dbExtCfgSrc = "db"
	healthCheckProbeKey = "/probe-etcd-connection"
)
var (
	ksrPrefix = servicelabel.GetDifferentAgentPrefix(ksr.MicroserviceLabel)
)
type dbWatcher struct {
	sync.Mutex
	*dbWatcherArgs
	remoteIsConnected bool
	resyncCount       int
	resyncReqs        chan bool  
	ignoreChangesUntilResync bool
	remoteBroker  keyval.ProtoBroker
	remoteWatcher keyval.ProtoWatcher
	localBroker   keyval.ProtoBroker
	remoteChangeCh     chan datasync.ProtoWatchResp
	remoteWatchCloseCh chan string
	processedVals map[string]datasync.KeyVal  
	wg     sync.WaitGroup
	ctx    context.Context
	cancel context.CancelFunc
}
type dbWatcherArgs struct {
	log         logging.Logger
	agentPrefix string
	eventLoop api.EventLoop
	localDB  keyval.KvProtoPlugin
	remoteDB keyval.KvProtoPlugin
	delayLocalResync        time.Duration
	remoteDBProbingInterval time.Duration
}
var (
	ErrClosedWatcher = errors.New("dbWatcher was closed")
	ErrResyncReqQueueFull = errors.New("queue with resync requests is full")
)
func newDBWatcher(args *dbWatcherArgs) *dbWatcher {
	watcher := &dbWatcher{
		dbWatcherArgs:  args,
		resyncReqs:     make(chan bool, 10),
		localBroker:    args.localDB.NewBroker(""),
		remoteChangeCh: make(chan datasync.ProtoWatchResp, 1000),
		processedVals:  make(map[string]datasync.KeyVal),
	}
	watcher.ignoreChangesUntilResync = true
	watcher.ctx, watcher.cancel = context.WithCancel(context.Background())
	watcher.wg.Add(1)
	go watcher.watchDB()
	args.remoteDB.OnConnect(watcher.onFirstConnect)
	watcher.wg.Add(1)
	go watcher.scheduleLocalResync(args.delayLocalResync)
	return watcher
}
func (w *dbWatcher) scheduleLocalResync(delay time.Duration) {
	defer w.wg.Done()
	select {
	case <-w.ctx.Done():
		return
	case <-time.After(delay):
		err := w.requestResync(true)
		if err != nil {
			w.log.Errorf("Failed to request resync against local DB: %v", err)
		}
	}
}
func (w *dbWatcher) onFirstConnect() error {
	w.Lock()
	defer w.Unlock()
	w.remoteBroker = w.remoteDB.NewBroker("")
	w.remoteWatcher = w.remoteDB.NewWatcher("")
	w.wg.Add(1)
	go w.periodicRemoteDBProbing()
	return nil
}