I'm quite a newbie to Rust, and especially async programming in Rust. Please help inform me if I'm missing something here.
So I'm trying to make requests with a concurrency limit in the following code.
let provider = Arc::new(Provider::<Http>::connect("").await);
let start_block = 5800000;
let end_block = 5900000;
let iterations = (end_block - start_block) / 1000;
let logs: Vec<_> = futures::stream::iter(0..iterations)
.map(|i| {
let begin = start_block + i * 1000;
let end = begin + 1000;
let filter = Filter::new()
.from_block(begin)
.to_block(end)
.event(TRANSFER_EVENT);
provider.get_logs(&filter)
})
.buffered(5)
.collect()
.await;
The compiler then complains:
error[E0515]: cannot return value referencing local variable `filter`
--> src\ether_utils.rs:169:17
|
169 | provider.get_logs(filter.as_ref())
| ^^^^^^^^^^^^^^^^^^---------------^
| | |
| | `filter` is borrowed here
| returns a value referencing data owned by the current function
I think I understand the error to some extent, and have come up with a workaround by rewriting the code:
let provider = Arc::new(Provider::<Http>::connect("").await);
let start_block = 5800000;
let end_block = 5900000;
let iterations = (end_block - start_block) / 1000;
let filters: Vec<Filter> = (0..iterations)
.map(|i| {
let begin = start_block + i * 1000;
let end = begin + 1000;
// let provider = provider.clone();
Filter::new()
// .at_block_hash(tx.block_hash.unwrap())
.from_block(begin)
.to_block(end)
.event(TRANSFER_EVENT)
})
.collect();
let logs: Vec<_> = futures::stream::iter(0..iterations)
.map(|i| provider.get_logs(&filters[i]))
.buffered(5)
.collect()
.await;
Now I feel the code looks a little off to me, as I'm forced to move the filter
variables out of the stream.map()
function to satisfy the lifetime check. Is there anyway to make it look more straight-forward, like converting the provider.get_logs(&filters[i])
to contain a "owned" filter
instead of reference?