github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/gossip/comm/ack.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package comm 8 9 import ( 10 "github.com/hechain20/hechain/gossip/common" 11 "github.com/hechain20/hechain/gossip/protoext" 12 "github.com/hechain20/hechain/gossip/util" 13 ) 14 15 type ( 16 sendFunc func(peer *RemotePeer, msg *protoext.SignedGossipMessage) 17 waitFunc func(*RemotePeer) error 18 ) 19 20 type ackSendOperation struct { 21 snd sendFunc 22 waitForAck waitFunc 23 } 24 25 func newAckSendOperation(snd sendFunc, waitForAck waitFunc) *ackSendOperation { 26 return &ackSendOperation{ 27 snd: snd, 28 waitForAck: waitForAck, 29 } 30 } 31 32 func (aso *ackSendOperation) send(msg *protoext.SignedGossipMessage, minAckNum int, peers ...*RemotePeer) []SendResult { 33 successAcks := 0 34 results := []SendResult{} 35 36 acks := make(chan SendResult, len(peers)) 37 // Send to all peers the message 38 for _, p := range peers { 39 go func(p *RemotePeer) { 40 // Send the message to 'p' 41 aso.snd(p, msg) 42 // Wait for an ack from 'p', or get an error if timed out 43 err := aso.waitForAck(p) 44 acks <- SendResult{ 45 RemotePeer: *p, 46 error: err, 47 } 48 }(p) 49 } 50 for { 51 ack := <-acks 52 results = append(results, SendResult{ 53 error: ack.error, 54 RemotePeer: ack.RemotePeer, 55 }) 56 if ack.error == nil { 57 successAcks++ 58 } 59 if successAcks == minAckNum || len(results) == len(peers) { 60 break 61 } 62 } 63 return results 64 } 65 66 func interceptAcks(nextHandler handler, remotePeerID common.PKIidType, pubSub *util.PubSub) func(*protoext.SignedGossipMessage) { 67 return func(m *protoext.SignedGossipMessage) { 68 if protoext.IsAck(m.GossipMessage) { 69 topic := topicForAck(m.Nonce, remotePeerID) 70 pubSub.Publish(topic, m.GetAck()) 71 return 72 } 73 nextHandler(m) 74 } 75 }