#Hey guys, i need some help with a lifetime problem thats requires borrow for static

7 messages · Page 1 of 1 (latest)

rapid silo
#
use std::sync::Arc;
use futures::{ future::BoxFuture, stream::{ BoxStream, SelectAll }, StreamExt };
use solana_client::nonblocking::pubsub_client::PubsubClient;
use chrono::prelude::*;

#[tokio::main]
async fn main() {
    // use to combine several streams into one and dynamically add new streams with push()
    let mut all_streams = SelectAll::new();

    // we should only have one websocket client for the application
    let ws_client = Arc::new(PubsubClient::new("wss://api.mainnet-beta.solana.com").await.unwrap());

    // make a slot subscription as an example and append the stream to all_streams
    let (stream, _unsubscribe) = subscribe_slot(&ws_client).await;
    all_streams.push(stream);

    // spawn a tokio task to handle all received updates
    tokio::spawn(async move {
        while let Some(update) = all_streams.next().await {
            println!("{:#?}", update);
        }
    });

    // let the application run until user exits with ctrl + c
    tokio::signal::ctrl_c().await.unwrap();
}

// copied from solana_client::nonblocking::pubsub_client::PubsubClient
type UnsubscribeFn = Box<dyn (FnOnce() -> BoxFuture<'static, ()>) + Send>;

// usage of the lifetime parameter 'a seems necessary to avoid lifetime problems within this function
async fn subscribe_slot<'a>(
    ws_client: &'a Arc<PubsubClient>
) -> (BoxStream<'a, Update>, UnsubscribeFn) {
    let (stream, unsubscribe) = ws_client.slot_subscribe().await.unwrap();

    // map the stream to our required format
    let stream = stream
        .map(move |slot_info| {
            let timestamp = Utc::now().timestamp();

            Update::Slot(SlotUpdate {
                timestamp,
                slot: slot_info.slot,
            })
        })
        .boxed();

    (stream, unsubscribe)
}

#[derive(Debug)]
pub enum Update {
    Slot(SlotUpdate),
    // ... other update types
}

#[derive(Debug)]
pub struct SlotUpdate {
    pub timestamp: i64,
    pub slot: u64,
}

#

the problem is, it's not possible for me to move everything in the tokio spawn block because later i need to encapsulate the subscriptions inside sth like a SubscriptionManager (which might hold the ws_client if necessary) and i need to be able to access that object from different parts of my application, for example to add new subscriptions, remove old ones etc.

// here we get the following error:
// ws_client does not live long enough
// borrowed value does not live long enoughrustcClick for full compiler diagnostic
// websocket.rs(27, 1): ws_client dropped here while still borrowed
// websocket.rs(12, 9): binding ws_client declared here
// websocket.rs(15, 34): argument requires that ws_client is borrowed for 'static
// and at the end of the main function: ws_client dropped here while still borrowed
error[E0597]: `ws_client` does not live long enough
  --> examples/websocket.rs:15:49
   |
12 |     let ws_client = Arc::new(PubsubClient::new("wss://api.mainnet-beta.solana.com").await.unwrap());
   |         --------- binding `ws_client` declared here
...
15 |     let (stream, _unsubscribe) = subscribe_slot(&ws_client).await;
   |                                  ---------------^^^^^^^^^^-
   |                                  |              |
   |                                  |              borrowed value does not live long enough
   |                                  argument requires that `ws_client` is borrowed for `'static`
...
27 | }
   | - `ws_client` dropped here while still borrowed
uneven relic
#

-code

vivid perchBOT
#

Please post your code examples and compiler output with code fences (```) around them. Example:

```rust
let (x, y) = (0, 42);
println!("Position at {}, {}", x, y);
```
let (x, y) = (0, 42);
println!("Position at {}, {}", x, y);

If the snippet is long or you want to demonstrate something, consider sharing it through the playground: https://play.rust-lang.org/ or https://www.rustexplorer.com/ or https://paste.rs/web.

Please avoid sharing screenshots of your code, as they're not very accessible. Using code fences or a shared snippet makes the code more readable and allows those helping you to copy-paste the code to help explain things.

uneven relic
#

also

#

-errors

vivid perchBOT
#

Run cargo check in a terminal

Note: If using rust analyzer you can click the "click for full compiler diagnostic" link in your editor.

Please post the full output of the above command, including the error title and any help or notes. An example of how this looks is:

error[E0308]: mismatched types
 --> src/main.rs:3:17
  |
3 | let foo: &i32 = bar;
  |          ----   ^^^ expected `&i32`, found integer
  |          |
  |          expected due to this
  |
help: consider borrowing here
  |
3 | let foo: &i32 = &bar;
  |                 +

When posting the error put it in a code block so it has nice formatting:
```rust
// error from cargo check here
```

Please do not post a screenshot. If the output is to long then use a paste tool like https://paste.rs/web