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