@@ -6,18 +6,17 @@ import (
6
6
"errors"
7
7
"fmt"
8
8
"github.com/ethereum/go-ethereum/ethclient"
9
+ "github.com/ethereum/go-ethereum/log"
10
+ "github.com/sirupsen/logrus"
9
11
"os"
10
12
"path/filepath"
11
- "razor/logger"
12
13
"razor/path"
13
14
"sort"
14
15
"strings"
15
16
"sync"
16
17
"time"
17
18
)
18
19
19
- var log = logger .NewLogger ()
20
-
21
20
func (m * RPCManager ) calculateMetrics (endpoint * RPCEndpoint ) error {
22
21
ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Second )
23
22
defer cancel ()
@@ -39,7 +38,7 @@ func (m *RPCManager) calculateMetrics(endpoint *RPCEndpoint) error {
39
38
40
39
endpoint .BlockNumber = blockNumber
41
40
endpoint .Latency = latency
42
- endpoint .Client = client // Store the client for future use
41
+ endpoint .Client = client
43
42
44
43
return nil
45
44
}
@@ -51,14 +50,14 @@ func (m *RPCManager) updateAndSortEndpoints() error {
51
50
}
52
51
53
52
var wg sync.WaitGroup
54
- log .Debug ("Starting concurrent metrics calculation for all endpoints..." )
53
+ logrus .Debug ("Starting concurrent metrics calculation for all endpoints..." )
55
54
56
55
for _ , endpoint := range m .Endpoints {
57
56
wg .Add (1 )
58
57
go func (ep * RPCEndpoint ) {
59
58
defer wg .Done ()
60
59
if err := m .calculateMetrics (ep ); err != nil {
61
- log . Printf ("Error calculating metrics for endpoint %s: %v" , ep .URL , err )
60
+ logrus . Errorf ("Error calculating metrics for endpoint %s: %v" , ep .URL , err )
62
61
}
63
62
}(endpoint )
64
63
}
@@ -76,8 +75,12 @@ func (m *RPCManager) updateAndSortEndpoints() error {
76
75
return m .Endpoints [i ].BlockNumber > m .Endpoints [j ].BlockNumber
77
76
})
78
77
79
- // Update the best RPC client after sorting
78
+ // Update the best RPC client and endpoint after sorting
80
79
m .BestRPCClient = m .Endpoints [0 ].Client
80
+ m .BestEndpoint = m .Endpoints [0 ]
81
+
82
+ logrus .Infof ("Best RPC endpoint updated: %s (BlockNumber: %d, Latency: %.2f)" ,
83
+ m .BestEndpoint .URL , m .BestEndpoint .BlockNumber , m .BestEndpoint .Latency )
81
84
82
85
return nil
83
86
}
@@ -87,7 +90,7 @@ func (m *RPCManager) RefreshEndpoints() error {
87
90
if err := m .updateAndSortEndpoints (); err != nil {
88
91
return fmt .Errorf ("failed to refresh endpoints: %w" , err )
89
92
}
90
- log .Infof ("Endpoints refreshed successfully" )
93
+ logrus .Infof ("Endpoints refreshed successfully" )
91
94
return nil
92
95
}
93
96
@@ -122,7 +125,7 @@ func InitializeRPCManager(provider string) (*RPCManager, error) {
122
125
123
126
// If the provider is not found, add it to the list
124
127
if ! providerFound && provider != "" {
125
- log .Infof ("Adding user-provided endpoint: %s" , provider )
128
+ logrus .Infof ("Adding user-provided endpoint: %s" , provider )
126
129
rpcEndpointsList = append (rpcEndpointsList , provider )
127
130
}
128
131
@@ -154,14 +157,27 @@ func (m *RPCManager) GetBestRPCClient() (*ethclient.Client, error) {
154
157
return m .BestRPCClient , nil
155
158
}
156
159
160
+ // GetBestEndpointURL returns the URL of the best endpoint
161
+ func (m * RPCManager ) GetBestEndpointURL () (string , error ) {
162
+ m .mutex .RLock ()
163
+ defer m .mutex .RUnlock ()
164
+
165
+ if m .BestEndpoint == nil {
166
+ return "" , fmt .Errorf ("no best endpoint available" )
167
+ }
168
+ return m .BestEndpoint .URL , nil
169
+ }
170
+
157
171
// SwitchToNextBestRPCClient switches to the next best available client after the current best client.
172
+ // If no valid next best client is found, it retains the current best client.
158
173
func (m * RPCManager ) SwitchToNextBestRPCClient () error {
159
174
m .mutex .Lock ()
160
175
defer m .mutex .Unlock ()
161
176
162
177
// If there are fewer than 2 endpoints, there are no alternate clients to switch to.
163
178
if len (m .Endpoints ) < 2 {
164
- return fmt .Errorf ("no other RPC clients to switch to" )
179
+ logrus .Warn ("No alternate RPC clients available. Retaining the current best client." )
180
+ return nil
165
181
}
166
182
167
183
// Find the index of the current best client
@@ -173,16 +189,36 @@ func (m *RPCManager) SwitchToNextBestRPCClient() error {
173
189
}
174
190
}
175
191
176
- // If current client is not found (which is rare), return an error
192
+ // If the current client is not found (which is rare), return an error
177
193
if currentIndex == - 1 {
178
194
return fmt .Errorf ("current best client not found in the list of endpoints" )
179
195
}
180
196
181
- // Calculate the next index by wrapping around if necessary
182
- nextIndex := (currentIndex + 1 ) % len (m .Endpoints )
197
+ // Iterate through the remaining endpoints to find a valid next best client
198
+ for i := 1 ; i < len (m .Endpoints ); i ++ {
199
+ nextIndex := (currentIndex + i ) % len (m .Endpoints )
200
+ nextEndpoint := m .Endpoints [nextIndex ]
201
+
202
+ // Check if we can connect to the next endpoint
203
+ ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Second )
204
+ defer cancel ()
205
+
206
+ client , err := ethclient .DialContext (ctx , nextEndpoint .URL )
207
+ if err != nil {
208
+ logrus .Errorf ("Failed to connect to RPC endpoint %s: %v" , nextEndpoint .URL , err )
209
+ continue
210
+ }
211
+
212
+ // Successfully connected, update the best client and endpoint
213
+ m .BestRPCClient = client
214
+ m .BestEndpoint = nextEndpoint
215
+
216
+ logrus .Infof ("Switched to the next best RPC endpoint: %s (BlockNumber: %d, Latency: %.2f)" ,
217
+ m .BestEndpoint .URL , m .BestEndpoint .BlockNumber , m .BestEndpoint .Latency )
218
+ return nil
219
+ }
183
220
184
- // Switch to the next client in the list
185
- m .BestRPCClient = m .Endpoints [nextIndex ].Client
186
- log .Infof ("Switched to the next best RPC client: %s" , m .Endpoints [nextIndex ].URL )
221
+ // If no valid endpoint is found, retain the current best client
222
+ logrus .Warn ("No valid next-best RPC client found. Retaining the current best client." )
187
223
return nil
188
224
}
0 commit comments