Passing a variable between multiple Rust files

I have an ID that I declare in a function in my controller.rs. But I need this ID in my service.rs. Is there a proper way to pass this variable between multiple Rust files? - Would the use of a struct be a good solution, or would there be a better way?

The general strategy is to pass it as an argument or return value when code in one of your files calls a function defined in the other. Without more detail about how you've organized things and what you're trying to do, it's hard to give any more specific advice.

2 Likes

You are asking the wrong question. Your code is compiled as a single binary, which means that you don't "pass" variables between files.

What you need to do instead is to think about code dependencies like function calls and dependency injection.

3 Likes

Maybe this helps

/*
controller.rs
I pass the id here
*/
#[get("/blacklight/{id}/{url}")]
pub async fn blacklight(path: web::Path<(String, String)>) -> impl Responder {
    let (id, url): (String, String) = path.into_inner();
}
/*
This is my service.rs
*/
// This function is called when a MQTT message comes from a specific topic
fn handle_blacklight() {
// I need the id here without passing it as a parameter
}

I'm not familiar with the framework/libraries you're using¹, but the general approach here would be to store the id inside the message that the controller enqueues, and then have handle_blacklight read it back out of the message that it's processing.


¹ What are they, btw?

2 Likes

I'm using actix-web and paho_mqtt

#[derive(Default)]
pub struct DataStore {
      pub data: String,
}

#[get("/blacklight/{id}/{url}")]
pub async fn blacklight(path: web::Path<(String, String)>) -> impl Responder {
    let (id, url): (String, String) = path.into_inner();

    DataStore { data: id };
}
fn handle_blacklight() {
    let data_store: DataStore = DataStore::default();

    let id = data_store.data;
}

Could this work?

How would you handle multiple simultaneous blacklight() requests? I assume each has a different ID and there's also multiple handle_blacklight() messages coming in.

The signature for handle_blacklight() bothers me; it implies global state, which is problematic for Actix's multi-threaded and multi-async-task environment.

Ok, what do I have to change?

You need to carefully plan out:

  • Relationship between events
  • Your data model. There's no single solution here.
  • How you'll manage thread and task synchronization with the data model
2 Likes

For this process the way is to call the Actix endpoint, publish the parameter to a external service and the external service publish the data back to my webserver where the handle_blacklight() set the relationship between the external sent data and the ID.

If you have a nodejs background, think of how you'd do it there. After you have that, it will be easier for us to explain how to adjust it to the Rust environment.

1 Like

No, I have no nodejs background. I have experience with Java's Spring

I'm not familiar with it. Does it use Java's new async/await support?

This constructs a new empty object; it doesn't grab existing data.

As far as I know it don't use it.

And how can access the id in handle_blacklight()?

Which id from which blacklight() call? Since it's Actix, there could be tens of thousands of simultaneous blacklight() calls, plus countless more in the past.

This isn't really helpful. I just want to pass the id to another function and don't want to discuss about the negative sides of Actix.

Option 1 (you already said it can't work): pass it as an argument

Option 2: ??? You appear to assume a single-threaded non-async system which can only handle 1 request at a time. Actix handles a collosal amount of simultaneous requests.

You need to give the ID to the external service, so that it can hand it back to you after it's finished its work.

2 Likes

Ok, thank you. I hoped to prevent this but ok