Skip to content

Instantly share code, notes, and snippets.

@feliwir
Created September 17, 2025 11:35
Show Gist options
  • Select an option

  • Save feliwir/daf46d26ff5bd942ecc198e8211b51f9 to your computer and use it in GitHub Desktop.

Select an option

Save feliwir/daf46d26ff5bd942ecc198e8211b51f9 to your computer and use it in GitHub Desktop.
error[E0373]: closure may outlive the current function, but it borrows `store`, which is owned by the current function
--> src/api/v1/send/routes.rs:90:15
|
49 | store: web::Data<Arc<DynObjectStore>>,
| ----- lifetime `'1` appears in the type of `store`
...
90 | .then(|location| {
| ^^^^^^^^^^ may outlive borrowed value `store`
91 | let store_clone: web::Data<Arc<DynObjectStore>> = store.clone();
| ----- `store` is borrowed here
|
note: function requires argument type to outlive `'1`
--> src/api/v1/send/routes.rs:130:5
|
130 | / client
131 | | .store_instances()
132 | | .with_instances(data_stream)
| |____________________________________^
help: to force the closure to take ownership of `store` (and any other referenced variables), use the `move` keyword
|
90 | .then(move |location| {
| ++++
error[E0373]: closure may outlive the current function, but it borrows `response.remaining_sub_operations`, which is owned by the current function
--> src/api/v1/send/routes.rs:118:21
|
49 | store: web::Data<Arc<DynObjectStore>>,
| ----- lifetime `'1` appears in the type of `store`
...
118 | .filter_map(|res| async move {
| ^^^^^ may outlive borrowed value `response.remaining_sub_operations`
...
123 | response.remaining_sub_operations -= 1;
| --------------------------------- `response.remaining_sub_operations` is borrowed here
|
note: function requires argument type to outlive `'1`
--> src/api/v1/send/routes.rs:130:5
|
130 | / client
131 | | .store_instances()
132 | | .with_instances(data_stream)
| |____________________________________^
help: to force the closure to take ownership of `response.remaining_sub_operations` (and any other referenced variables), use the `move` keyword
|
118 | .filter_map(move |res| async move {
| ++++
error[E0505]: cannot move out of `response` because it is borrowed
--> src/api/v1/send/routes.rs:140:71
|
49 | store: web::Data<Arc<DynObjectStore>>,
| ----- lifetime `'1` appears in the type of `store`
...
118 | .filter_map(|res| async move {
| ----- borrow of `response.remaining_sub_operations` occurs here
...
123 | response.remaining_sub_operations -= 1;
| --------------------------------- borrow occurs due to use in closure
...
130 | / client
131 | | .store_instances()
132 | | .with_instances(data_stream)
| |____________________________________- argument requires that `response.remaining_sub_operations` is borrowed for `'1`
...
140 | Ok(HttpResponse::Ok().json(DicomJson::from(InMemDicomObject::from(response))))
| ^^^^^^^^ move out of `response` occurs here
#[post("/studies/{study_uid}/series/forward-requests/{transaction_uid}")]
pub async fn forward_series_in_study(
pool: web::Data<DbPool>,
store: web::Data<Arc<DynObjectStore>>,
path_params: web::Path<(String, String)>,
query_params: web::Query<SendQueryParams>,
) -> Result<impl Responder> {
let (study_uid, transaction_uid) = path_params.into_inner();
if query_params.search.is_some() {
return Err(ErrorNotImplemented("Search parameter is not implemented"));
}
let mut conn = pool.get().await.map_err(|e| {
tracing::error!("Failed to get database connection: {}", e);
ErrorInternalServerError("Failed to get database connection")
})?;
// Get all instances in the study
let instances_list = db::dicom::instance_table::list_in_study(
&mut conn, &study_uid, 0, 100000, // Arbitrary large limit
)
.await
.map_err(|e| {
tracing::error!("Failed to list instances in study: {}", e);
ErrorInternalServerError("Failed to list instances in study")
})?;
// Initialize the response
let mut response = SendResponse::default();
response.remaining_sub_operations = instances_list.len() as u32;
let atomic_failures = AtomicU32::new(0);
let instances_locations = instances_list
.iter()
.map(|(series, instance)| {
format!(
"{}/{}/{}",
series.study_instance_uid, series.series_instance_uid, instance.sop_instance_uid
)
})
.collect::<Vec<String>>();
let instances_locations_stream = futures_util::stream::iter(instances_locations);
let data_stream = instances_locations_stream
.then(|location| {
let store_clone: web::Data<Arc<DynObjectStore>> = store.clone();
async move {
// Load the instance from the object store
let get_result = store_clone.get(&Path::from(location.clone())).await;
let data = match get_result {
Ok(data) => data,
Err(e) => {
tracing::error!("Failed to get instance from object store: {}", e);
// response.failed_sub_operations += 1;
// response.remaining_sub_operations -= 1;
// response.failed_sop_instances.push(location);
return Err("Failed to get instance from object store");
}
};
let bytes = data.bytes().await.map_err(|e| {
tracing::error!("Failed to read instance data: {}", e);
"Failed to read instance data"
})?;
let cursor = Cursor::new(bytes);
let dicom_object = FileDicomObject::from_reader(cursor).map_err(|e| {
tracing::error!("Failed to parse DICOM object: {}", e);
"Failed to parse DICOM object"
})?;
Ok(dicom_object)
}
})
.filter_map(|res| async move {
match res {
Ok(data) => Some(data),
Err(_) => {
response.failed_sub_operations += 1;
response.remaining_sub_operations -= 1;
None
}
}
});
// Setup the dicomweb client
let client = dicom_web::DicomWebClient::with_single_url(&query_params.destination);
client
.store_instances()
.with_instances(data_stream)
.run()
.await
.map_err(|e| {
tracing::error!("Failed to send instances via DICOMweb: {}", e);
ErrorInternalServerError("Failed to send instances via DICOMweb")
})?;
Ok(HttpResponse::Ok().json(DicomJson::from(InMemDicomObject::from(response))))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment