github.com/status-im/status-go@v1.1.0/protocol/datasync/transport.go (about)

     1  package datasync
     2  
     3  import (
     4  	"errors"
     5  	"math"
     6  	"math/rand"
     7  	"time"
     8  
     9  	"github.com/status-im/mvds/protobuf"
    10  	"github.com/status-im/mvds/state"
    11  	"github.com/status-im/mvds/transport"
    12  	"go.uber.org/zap"
    13  )
    14  
    15  const backoffInterval = 30
    16  
    17  var errNotInitialized = errors.New("datasync transport not initialized")
    18  var DatasyncTicker = 300 * time.Millisecond
    19  
    20  // It's easier to calculate nextEpoch if we consider seconds as a unit rather than
    21  // 300 ms, so we multiply the result by the ratio
    22  var offsetToSecond = uint64(time.Second / DatasyncTicker)
    23  
    24  type NodeTransport struct {
    25  	packets  chan transport.Packet
    26  	logger   *zap.Logger
    27  	dispatch func(state.PeerID, *protobuf.Payload) error
    28  }
    29  
    30  func NewNodeTransport() *NodeTransport {
    31  	return &NodeTransport{
    32  		packets: make(chan transport.Packet),
    33  	}
    34  }
    35  
    36  func (t *NodeTransport) Init(dispatch func(state.PeerID, *protobuf.Payload) error, logger *zap.Logger) {
    37  	t.dispatch = dispatch
    38  	t.logger = logger
    39  }
    40  
    41  func (t *NodeTransport) AddPacket(p transport.Packet) {
    42  	t.packets <- p
    43  }
    44  
    45  func (t *NodeTransport) Watch() transport.Packet {
    46  	return <-t.packets
    47  }
    48  
    49  func (t *NodeTransport) Send(_ state.PeerID, peer state.PeerID, payload *protobuf.Payload) error {
    50  	if t.dispatch == nil {
    51  		return errNotInitialized
    52  	}
    53  
    54  	// We don't return an error otherwise datasync will keep
    55  	// re-trying sending at each epoch
    56  	err := t.dispatch(peer, payload)
    57  	if err != nil {
    58  		t.logger.Error("failed to send message", zap.Error(err))
    59  		return nil
    60  	}
    61  
    62  	return nil
    63  }
    64  
    65  // CalculateSendTime calculates the next epoch
    66  // at which a message should be sent.
    67  // We randomize it a bit so that not all messages are sent on the same epoch
    68  func CalculateSendTime(count uint64, time int64) int64 {
    69  	return time + int64(uint64(math.Exp2(float64(count-1)))*backoffInterval*offsetToSecond) + int64(rand.Intn(30)) // nolint: gosec
    70  }