github.com/15mga/kiwi@v0.0.2-0.20240324021231-b95d5c3ac751/core/node_dialer.go (about)

     1  package core
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"github.com/15mga/kiwi"
     8  	"github.com/15mga/kiwi/util"
     9  )
    10  
    11  var (
    12  	_NetReconnectDur = time.Second
    13  	MaxReconnect     = 5
    14  	MaxSendRetry     = uint8(3)
    15  	SendRetryDur     = time.Second
    16  )
    17  
    18  type (
    19  	OnNetDialerConnected    func(*nodeDialer)
    20  	OnNetDialerDisconnected func(*nodeDialer, *util.Err)
    21  )
    22  
    23  func newNodeDialer(dialer kiwi.IDialer, svc kiwi.TSvc, nodeId int64, ver string, head util.M,
    24  	onConnected OnNetDialerConnected, onDisconnected OnNetDialerDisconnected) *nodeDialer {
    25  	d := &nodeDialer{
    26  		svc:            svc,
    27  		nodeId:         nodeId,
    28  		ver:            ver,
    29  		head:           head,
    30  		dialer:         dialer,
    31  		onConnected:    onConnected,
    32  		onDisconnected: onDisconnected,
    33  	}
    34  	d.ctx, d.cancel = context.WithCancel(util.Ctx())
    35  	dialer.Agent().BindConnected(d.onConn)
    36  	dialer.Agent().BindDisconnected(d.onDisConn)
    37  	return d
    38  }
    39  
    40  type nodeDialer struct {
    41  	svc            kiwi.TSvc
    42  	nodeId         int64
    43  	ver            string
    44  	head           util.M
    45  	dialer         kiwi.IDialer
    46  	currReconnect  int
    47  	onConnected    OnNetDialerConnected
    48  	onDisconnected OnNetDialerDisconnected
    49  	ctx            context.Context
    50  	cancel         context.CancelFunc
    51  }
    52  
    53  func (d *nodeDialer) heartbeat() {
    54  	go func() {
    55  		ticker := time.NewTicker(time.Second * 10)
    56  		for {
    57  			select {
    58  			case <-d.ctx.Done():
    59  				ticker.Stop()
    60  				return
    61  			case <-ticker.C:
    62  				d.Send(Heartbeat, nil)
    63  			}
    64  		}
    65  	}()
    66  }
    67  
    68  func (d *nodeDialer) onConn(_ kiwi.IAgent) {
    69  	d.onConnected(d)
    70  	if kiwi.GetNodeMeta().Mode == kiwi.ModeDebug {
    71  		return
    72  	}
    73  	d.heartbeat()
    74  }
    75  
    76  func (d *nodeDialer) onDisConn(_ kiwi.IAgent, err *util.Err) {
    77  	d.onDisconnected(d, err)
    78  	d.cancel()
    79  }
    80  
    81  func (d *nodeDialer) Svc() kiwi.TSvc {
    82  	return d.svc
    83  }
    84  
    85  func (d *nodeDialer) NodeId() int64 {
    86  	return d.nodeId
    87  }
    88  
    89  func (d *nodeDialer) Dialer() kiwi.IDialer {
    90  	return d.dialer
    91  }
    92  
    93  func (d *nodeDialer) Head() util.M {
    94  	return d.head
    95  }
    96  
    97  func (d *nodeDialer) connect() {
    98  	err := d.dialer.Connect(util.Ctx())
    99  	if err == nil {
   100  		d.currReconnect = 0
   101  		return
   102  	}
   103  	err.AddParams(util.M{
   104  		"service":   d.svc,
   105  		"node id":   d.nodeId,
   106  		"reconnect": d.currReconnect,
   107  	})
   108  	kiwi.Error(err)
   109  	d.reconnect()
   110  }
   111  
   112  func (d *nodeDialer) reconnect() {
   113  	d.currReconnect++
   114  	if d.currReconnect >= MaxReconnect {
   115  		kiwi.Error2(util.EcConnectErr, util.M{
   116  			"error":   "connect failed",
   117  			"service": d.svc,
   118  			"node id": d.nodeId,
   119  		})
   120  		return
   121  	}
   122  	time.Sleep(_NetReconnectDur)
   123  	_ = d.dialer.Agent().Enable().IfEnable(d.connect)
   124  }
   125  
   126  func (d *nodeDialer) Send(bytes []byte, fnErr util.FnErr) {
   127  	d.sendWithCount(bytes, fnErr, 0)
   128  }
   129  
   130  func (d *nodeDialer) sendWithCount(bytes []byte, fnErr util.FnErr, count uint8) {
   131  	err := d.dialer.Agent().Send(bytes)
   132  	if err == nil {
   133  		fnErr.Invoke(nil)
   134  		return
   135  	}
   136  	if err.Code() != util.EcClosed {
   137  		kiwi.Error(err)
   138  		fnErr.Invoke(err)
   139  		return
   140  	}
   141  	if count >= MaxSendRetry {
   142  		fnErr.Invoke(err)
   143  		return
   144  	}
   145  	time.AfterFunc(SendRetryDur, func() {
   146  		d.sendWithCount(bytes, fnErr, count+1)
   147  	})
   148  }