mirror of
https://github.com/logos-messaging/go-libp2p-pubsub.git
synced 2026-01-02 21:03:07 +00:00
to support batch publishing messages Replaces #602. Batch publishing lets the system know there are multiple related messages to be published so it can prioritize sending different messages before sending copies of messages. For example, with the default API, when you publish two messages A and B, under the hood A gets sent to D=8 peers first, before B gets sent out. With this MessageBatch api we can now send one copy of A _and then_ one copy of B before sending multiple copies. When a node has bandwidth constraints relative to the messages it is publishing this improves dissemination time. For more context see this post: https://ethresear.ch/t/improving-das-performance-with-gossipsub-batch-publishing/21713
63 lines
1.4 KiB
Go
63 lines
1.4 KiB
Go
package pubsub
|
|
|
|
import (
|
|
"iter"
|
|
|
|
"github.com/libp2p/go-libp2p/core/peer"
|
|
)
|
|
|
|
// MessageBatch allows a user to batch related messages and then publish them at
|
|
// once. This allows the Scheduler to define an order for outgoing RPCs.
|
|
// This helps bandwidth constrained peers.
|
|
type MessageBatch struct {
|
|
messages []*Message
|
|
}
|
|
|
|
type messageBatchAndPublishOptions struct {
|
|
messages []*Message
|
|
opts *BatchPublishOptions
|
|
}
|
|
|
|
// RPCScheduler schedules outgoing RPCs.
|
|
type RPCScheduler interface {
|
|
// AddRPC adds an RPC to the scheduler.
|
|
AddRPC(peer peer.ID, msgID string, rpc *RPC)
|
|
// All returns an ordered iterator of RPCs.
|
|
All() iter.Seq2[peer.ID, *RPC]
|
|
}
|
|
|
|
type pendingRPC struct {
|
|
peer peer.ID
|
|
rpc *RPC
|
|
}
|
|
|
|
// RoundRobinMessageIDScheduler schedules outgoing RPCs in round-robin order of message IDs.
|
|
type RoundRobinMessageIDScheduler struct {
|
|
rpcs map[string][]pendingRPC
|
|
}
|
|
|
|
func (s *RoundRobinMessageIDScheduler) AddRPC(peer peer.ID, msgID string, rpc *RPC) {
|
|
if s.rpcs == nil {
|
|
s.rpcs = make(map[string][]pendingRPC)
|
|
}
|
|
s.rpcs[msgID] = append(s.rpcs[msgID], pendingRPC{peer: peer, rpc: rpc})
|
|
}
|
|
|
|
func (s *RoundRobinMessageIDScheduler) All() iter.Seq2[peer.ID, *RPC] {
|
|
return func(yield func(peer.ID, *RPC) bool) {
|
|
for len(s.rpcs) > 0 {
|
|
for msgID, rpcs := range s.rpcs {
|
|
if len(rpcs) == 0 {
|
|
delete(s.rpcs, msgID)
|
|
continue
|
|
}
|
|
if !yield(rpcs[0].peer, rpcs[0].rpc) {
|
|
return
|
|
}
|
|
|
|
s.rpcs[msgID] = rpcs[1:]
|
|
}
|
|
}
|
|
}
|
|
}
|