Created
September 17, 2025 11:35
-
-
Save feliwir/daf46d26ff5bd942ecc198e8211b51f9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #[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