55 "errors"
66 "log/slog"
77 "net/http"
8- "os"
98 "time"
109
1110 "github.com/flashbots/go-utils/jsonrpc"
@@ -19,20 +18,19 @@ var (
1918 ShareWorkerQueueSize = 10000
2019 requestTimeout = time .Second * 10
2120
22- errUnknownRequestType = errors .New ("unknwon request type for sharing" )
21+ errUnknownRequestType = errors .New ("unknown request type for sharing" )
2322)
2423
2524const (
2625 bigRequestSize = 50_000
2726)
2827
2928type ShareQueue struct {
30- name string
31- log * slog.Logger
32- queue chan * ParsedRequest
33- updatePeers chan []ConfighubBuilder
34- localBuilderEndpoint string
35- signer * signature.Signer
29+ name string
30+ log * slog.Logger
31+ queue chan * ParsedRequest
32+ updatePeers chan []ConfighubBuilder
33+ signer * signature.Signer
3634 // if > 0 share queue will spawn multiple senders per peer
3735 workersPerPeer int
3836}
@@ -73,23 +71,7 @@ func (sq *ShareQueue) Run() {
7371 if sq .workersPerPeer > 0 {
7472 workersPerPeer = sq .workersPerPeer
7573 }
76- var (
77- localBuilder * shareQueuePeer
78- peers []shareQueuePeer
79- )
80- if len (sq .localBuilderEndpoint ) > 0 {
81- client , err := NewFastHTTPClient (nil , workersPerPeer )
82- if err != nil {
83- sq .log .Error ("Failed to intitialize local builder enpoint" )
84- os .Exit (1 )
85- }
86- builderPeer := newShareQueuePeer ("local-builder" , client , ConfighubBuilder {}, sq .localBuilderEndpoint )
87- localBuilder = & builderPeer
88- for worker := range workersPerPeer {
89- go sq .proxyRequests (localBuilder , worker )
90- }
91- defer localBuilder .Close ()
92- }
74+ var peers []shareQueuePeer
9375 for {
9476 select {
9577 case req , more := <- sq .queue :
@@ -98,9 +80,6 @@ func (sq *ShareQueue) Run() {
9880 sq .log .Info ("Share queue closing, queue channel closed" )
9981 return
10082 }
101- if localBuilder != nil {
102- localBuilder .SendRequest (sq .log , req )
103- }
10483 if ! req .systemEndpoint {
10584 for _ , peer := range peers {
10685 peer .SendRequest (sq .log , req )
@@ -166,6 +145,83 @@ func (sq *ShareQueue) Run() {
166145 }
167146}
168147
148+ type LocalBuilderSender struct {
149+ logger * slog.Logger
150+ client * fasthttp.Client
151+ endpoint string
152+ }
153+
154+ func NewLocalBuilderSender (logger * slog.Logger , endpoint string , maxOpenConnections int ) (LocalBuilderSender , error ) {
155+ logger = logger .With (slog .String ("peer" , "local-builder" ))
156+
157+ client , err := NewFastHTTPClient (nil , maxOpenConnections )
158+ if err != nil {
159+ return LocalBuilderSender {}, err
160+ }
161+
162+ return LocalBuilderSender {
163+ logger , client , endpoint ,
164+ }, nil
165+ }
166+
167+ func (s * LocalBuilderSender ) SendRequest (req * ParsedRequest ) error {
168+ request := fasthttp .AcquireRequest ()
169+ request .SetRequestURI (s .endpoint )
170+ request .Header .SetMethod (http .MethodPost )
171+ request .Header .SetContentTypeBytes ([]byte ("application/json" ))
172+ defer fasthttp .ReleaseRequest (request )
173+
174+ return sendShareRequest (s .logger , req , request , s .client , "local-builder" )
175+ }
176+
177+ func sendShareRequest (logger * slog.Logger , req * ParsedRequest , request * fasthttp.Request , client * fasthttp.Client , peerName string ) error {
178+ if req .serializedJSONRPCRequest == nil {
179+ logger .Debug ("Skip sharing request that is not serialized properly" )
180+ return nil
181+ }
182+
183+ timeInQueue := time .Since (req .receivedAt )
184+
185+ request .Header .Set (signature .HTTPHeader , req .signatureHeader )
186+ request .SetBodyRaw (req .serializedJSONRPCRequest )
187+
188+ resp := fasthttp .AcquireResponse ()
189+ start := time .Now ()
190+ err := client .DoTimeout (request , resp , requestTimeout )
191+ requestDuration := time .Since (start )
192+ timeE2E := timeInQueue + requestDuration
193+
194+ // in background update metrics and handle response
195+ go func () {
196+ isBig := req .size >= bigRequestSize
197+ timeShareQueuePeerQueueDuration (peerName , timeInQueue , req .method , req .systemEndpoint , isBig )
198+ timeShareQueuePeerRPCDuration (peerName , requestDuration .Milliseconds (), isBig )
199+ timeShareQueuePeerE2EDuration (peerName , timeE2E , req .method , req .systemEndpoint , isBig )
200+
201+ logSendErrorLevel := slog .LevelDebug
202+ if peerName == "local-builder" {
203+ logSendErrorLevel = slog .LevelWarn
204+ }
205+ if err != nil {
206+ logger .Log (context .Background (), logSendErrorLevel , "Error while proxying request" , slog .Any ("error" , err ))
207+ incShareQueuePeerRPCErrors (peerName )
208+ } else {
209+ var parsedResp jsonrpc.JSONRPCResponse
210+ err = json .Unmarshal (resp .Body (), & parsedResp )
211+ if err != nil {
212+ logger .Log (context .Background (), logSendErrorLevel , "Error parsing response while proxying" , slog .Any ("error" , err ))
213+ incShareQueuePeerRPCErrors (peerName )
214+ } else if parsedResp .Error != nil {
215+ logger .Log (context .Background (), logSendErrorLevel , "Error returned from target while proxying" , slog .Any ("error" , parsedResp .Error ))
216+ incShareQueuePeerRPCErrors (peerName )
217+ }
218+ }
219+ fasthttp .ReleaseResponse (resp )
220+ }()
221+
222+ return nil
223+ }
224+
169225func (sq * ShareQueue ) proxyRequests (peer * shareQueuePeer , worker int ) {
170226 proxiedRequestCount := 0
171227 logger := sq .log .With (slog .String ("peer" , peer .name ), slog .String ("name" , sq .name ), slog .Int ("worker" , worker ))
@@ -191,44 +247,10 @@ func (sq *ShareQueue) proxyRequests(peer *shareQueuePeer, worker int) {
191247 continue
192248 }
193249
194- timeInQueue := time .Since (req .receivedAt )
195-
196- request .Header .Set (signature .HTTPHeader , req .signatureHeader )
197- request .SetBodyRaw (req .serializedJSONRPCRequest )
198-
199- resp := fasthttp .AcquireResponse ()
200- start := time .Now ()
201- err := peer .client .DoTimeout (request , resp , requestTimeout )
202- requestDuration := time .Since (start )
203- timeE2E := timeInQueue + requestDuration
204-
205- // in background update metrics and handle response
206- go func () {
207- isBig := req .size >= bigRequestSize
208- timeShareQueuePeerQueueDuration (peer .name , timeInQueue , req .method , req .systemEndpoint , isBig )
209- timeShareQueuePeerRPCDuration (peer .name , requestDuration .Milliseconds (), isBig )
210- timeShareQueuePeerE2EDuration (peer .name , timeE2E , req .method , req .systemEndpoint , isBig )
211-
212- logSendErrorLevel := slog .LevelDebug
213- if peer .name == "local-builder" {
214- logSendErrorLevel = slog .LevelWarn
215- }
216- if err != nil {
217- logger .Log (context .Background (), logSendErrorLevel , "Error while proxying request" , slog .Any ("error" , err ))
218- incShareQueuePeerRPCErrors (peer .name )
219- } else {
220- var parsedResp jsonrpc.JSONRPCResponse
221- err = json .Unmarshal (resp .Body (), & parsedResp )
222- if err != nil {
223- logger .Log (context .Background (), logSendErrorLevel , "Error parsing response while proxying" , slog .Any ("error" , err ))
224- incShareQueuePeerRPCErrors (peer .name )
225- } else if parsedResp .Error != nil {
226- logger .Log (context .Background (), logSendErrorLevel , "Error returned from target while proxying" , slog .Any ("error" , parsedResp .Error ))
227- incShareQueuePeerRPCErrors (peer .name )
228- }
229- }
230- fasthttp .ReleaseResponse (resp )
231- }()
250+ err := sendShareRequest (logger , req , request , peer .client , peer .name )
251+ if err != nil {
252+ logger .Debug ("Failed to proxy a request" , slog .Any ("error" , err ))
253+ }
232254
233255 proxiedRequestCount += 1
234256 logger .Debug ("Message proxied" )
0 commit comments