-
Notifications
You must be signed in to change notification settings - Fork 78
feat(providers/api): multi-solana-client [BLO-1067] #308
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #308 +/- ##
=======================================
Coverage 62.46% 62.46%
=======================================
Files 220 222 +2
Lines 9734 9798 +64
=======================================
+ Hits 6080 6120 +40
- Misses 3102 3122 +20
- Partials 552 556 +4 ☔ View full report in Codecov by Sentry. |
369e64c
to
6f60353
Compare
eab5cba
to
3407a12
Compare
5739225
to
f279e4c
Compare
76d4f58
to
ff34ce4
Compare
cmd/slinky-config/main.go
Outdated
nodes := strings.Split(solanaNodeURLs, ",") | ||
|
||
for _, node := range nodes { | ||
cfg.Endpoints = append(cfg.Endpoints, config.Endpoint{ | ||
URL: node, | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The solanaNodeURLs flag should just be a StringSliceVarP. It eliminates all of this code.
// Create a channel to receive the responses from the underlying clients | ||
responsesCh := make(chan *rpc.GetMultipleAccountsResult, len(c.clients)) | ||
|
||
// spawn a goroutine for each client to fetch the accounts | ||
var wg sync.WaitGroup | ||
wg.Add(len(c.clients)) | ||
|
||
for i := range c.clients { | ||
go func(client SolanaJSONRPCClient) { | ||
defer wg.Done() | ||
resp, err := client.GetMultipleAccountsWithOpts(ctx, accounts, opts) | ||
if err != nil { | ||
c.logger.Error("failed to fetch accounts", zap.Error(err)) | ||
return | ||
} | ||
responsesCh <- resp | ||
}(c.clients[i]) | ||
} | ||
|
||
// close the channel once all responses are received, or the context is cancelled | ||
go func() { | ||
select { | ||
case <-ctx.Done(): | ||
c.logger.Error("context cancelled") | ||
case <-channelForWaitGroup(&wg): | ||
} | ||
close(responsesCh) | ||
}() | ||
|
||
responses := make([]*rpc.GetMultipleAccountsResult, 0, len(c.clients)) | ||
for resp := range responsesCh { | ||
responses = append(responses, resp) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Create a channel to receive the responses from the underlying clients | |
responsesCh := make(chan *rpc.GetMultipleAccountsResult, len(c.clients)) | |
// spawn a goroutine for each client to fetch the accounts | |
var wg sync.WaitGroup | |
wg.Add(len(c.clients)) | |
for i := range c.clients { | |
go func(client SolanaJSONRPCClient) { | |
defer wg.Done() | |
resp, err := client.GetMultipleAccountsWithOpts(ctx, accounts, opts) | |
if err != nil { | |
c.logger.Error("failed to fetch accounts", zap.Error(err)) | |
return | |
} | |
responsesCh <- resp | |
}(c.clients[i]) | |
} | |
// close the channel once all responses are received, or the context is cancelled | |
go func() { | |
select { | |
case <-ctx.Done(): | |
c.logger.Error("context cancelled") | |
case <-channelForWaitGroup(&wg): | |
} | |
close(responsesCh) | |
}() | |
responses := make([]*rpc.GetMultipleAccountsResult, 0, len(c.clients)) | |
for resp := range responsesCh { | |
responses = append(responses, resp) | |
} | |
responses := make([]*rpc.GetMultipleAccountsResult, 0, len(c.clients)) | |
// spawn a goroutine for each client to fetch the accounts | |
var wg sync.WaitGroup | |
wg.Add(len(c.clients)) | |
for i := range c.clients { | |
go func(client SolanaJSONRPCClient) { | |
defer wg.Done() | |
resp, err := client.GetMultipleAccountsWithOpts(ctx, accounts, opts) | |
if err != nil { | |
c.logger.Error("failed to fetch accounts", zap.Error(err)) | |
return | |
} | |
responses[i] = resp | |
}(c.clients[i]) | |
} | |
wg.Wait() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm struggling to see why we need anything more than parallelized fetches here. Anything that errors out will properly have no results, and we block on all the responses returning no matter what.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic defers to context closure over all clients finishing their outbound requests. Agreed that the behavior is the same if the underlying client defers to context closure
In This PR
Endpoints
field to the config, where we can place node-urls / authentication, etcMultiClient
to raydium to permit querying across multiple separated node-providers + aggregating repsonses from among them