You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用good_lp与sea-orm时遇Send trait未实现错误求助

问题描述

我用good_lp crate求解线性规划问题,之后用异步框架sea-orm把结果存到数据库里,代码如下:

#[debug_handler]
pub async fn compute(
    Extension(database): Extension<DatabaseConnection>,
) -> Html<String> {
    // some computations

    for outcome_name in outcome_names.iter() {
        // set up problem

        let result = p.solve();
        if let Ok(solution) = result {
            for (intervention_name, var) in problem.var_map.iter() {
                let updated_value = solution.value(var.clone()) as i32;
                let updated_size = value_to_size.get(&updated_value).unwrap().to_string();
                update_intervention_outcome(
                    &database,
                    intervention_name.clone(),
                    outcome_name.clone(),
                    updated_size.clone(),
                ).await;
            }
        };
    };
    // return html
}

现在遇到的问题是求解结果CoinCbcSolution没实现Send trait,不清楚为什么solution的销毁会引发问题,也不知道怎么修复。错误信息如下:

error: future cannot be sent between threads safely
   --> src/routes/computations.rs:76:1
    |
76  | #[debug_handler]
    | ^^^^^^^^^^^^^^^^ future returned by `compute` is not `Send`
    |
 = help: within `impl futures::Future<Output = axum::response::Html<std::string::String>>`, the trait `std::marker::Send` is not implemented for `*mut coin_cbc_sys::Cbc_Model`
note: future is not `Send` as this value is used across an await
   --> src/routes/computations.rs:341:126
    |
336 |         if let Ok(solution) = result {
    |                   -------- has type `CoinCbcSolution` which is not `Send`
...
341 |                 update_intervention_outcome(
                          &database,
                          intervention_name.clone(),
                          outcome_name.clone(),
                          updated_size.clone(),
                      ).await;
    |                                                                                                                              ^^^^^^ await occurs here, with `solution` maybe used later
342 |             }
343 |         };
    |         - `solution` is later dropped here
解决方案

问题根源

CoinCbcSolution内部持有未实现Send的原始指针(*mut coin_cbc_sys::Cbc_Model),而Axum的handler要求返回的Future必须是Send的——因为异步运行时会在不同线程间调度Future。你的代码里solution在await之后才被销毁,导致Future持有了非Send的solution,违反了约束。

修复方法

把从solution中提取数据的操作和异步数据库操作分开:先一次性把所有需要的数据从solution里取出来,存到一个实现了Send的结构里(比如包含String的元组Vec),等solution被销毁后,再执行异步的数据库更新。

修改后的代码示例:

#[debug_handler]
pub async fn compute(
    Extension(database): Extension<DatabaseConnection>,
) -> Html<String> {
    // some computations

    for outcome_name in outcome_names.iter() {
        // set up problem

        let result = p.solve();
        if let Ok(solution) = result {
            // 先收集所有需要更新的数据,此时solution还在作用域内
            let updates: Vec<_> = problem.var_map.iter()
                .map(|(intervention_name, var)| {
                    let updated_value = solution.value(var.clone()) as i32;
                    let updated_size = value_to_size.get(&updated_value).unwrap().to_string();
                    (
                        intervention_name.clone(),
                        outcome_name.clone(),
                        updated_size,
                    )
                })
                .collect();
            
            // 这里solution已经被销毁,接下来的异步操作不会持有非Send的对象
            for (intervention_name, outcome_name, updated_size) in updates {
                update_intervention_outcome(
                    &database,
                    intervention_name,
                    outcome_name,
                    updated_size,
                ).await;
            }
        };
    };
    // return html
}

原理说明

通过先收集所有需要的数据,solution会在collect()之后、进入异步循环之前被销毁,这样后续的异步Future就不会持有任何非Send的对象,满足Axum对Future的Send要求。

内容的提问来源于stack exchange,提问作者bard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 21:45:29