服务层的代码结构会影响Axum处理程序对trait的实现情况
我在用Rust和 Axum框架开发一个相当简单的CRUD REST API。它具有处理程序和服务的分层——处理程序通过 Arc 调用服务。
在开发 generate_unique_slug 函数时,我遇到了如下编译错误。
错误是:
error[E0277]: the trait bound `fn(State<Arc<AppState>>, ..., ..., ...) -> ... {create}: Handler<_, _>` is not satisfied
--> src/mgmt/server.rs:48:18
|
48 | post(branch::create).get(branch::list),
| ---- ^^^^^^^^^^^^^^ the trait `axum::handler::Handler<_, _>` is not implemented for fn item `fn(State<Arc<AppState>>, UserId, Path<...>, ...) -> ... {create}`
| |
| required by a bound introduced by this call
|
= note: Consider using `#[axum::debug_handler]` to improve the error message
= help: the following other types implement trait `axum::handler::Handler<T, S>`:
`MethodRouter<S>` implements `axum::handler::Handler<(), S>`
`axum::handler::Layered<L, H, T, S>` implements `axum::handler::Handler<T, S>`
note: required by a bound in `post`
--> /Users/mateuszwozniak/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/axum-0.8.8/src/routing/method_routing.rs:445:1
|
445 | top_level_handler_fn!(post, POST);
| ^^^^^^^^^^^^^^^^^^^^^^----^^^^^^^
| | |
| | required by a bound in this function
| required by this bound in `post`
= note: the full name for the type has been written to '/Users/mateuszwozniak/repos/neond/target/debug/deps/neond-1ab29fe44f789f04.long-type-14284547332887205018.txt'
= note: consider using `--verbose` to print the full type name to the console
= note: this error originates in the macro `top_level_handler_fn` (in Nightly builds, run with -Z macro-backtrace for more info)
导致此错误的代码位于 struct BranchService 的 async fn generate_unique_slug 里:
async fn generate_unique_slug(&self) -> Result<String> {
let mut generator = Generator::default();
for _ in 0..10 {
let slug = generator
.next()
.unwrap_or_else(|| format!("branch-{}", Uuid::new_v4()));
if self.branch_repo.find_by_slug(&slug).await?.is_none() {
return Ok(slug);
}
}
Ok(format!("branch-{}", Uuid::new_v4()))
}
然而,稍作修改——将 names::Generator::default() 移出循环后,代码就可以编译通过:
async fn generate_unique_slug(&self) -> Result<String> {
for _ in 0..10 {
let slug = Generator::default()
.next()
.unwrap_or_else(|| format!("branch-{}", Uuid::new_v4()));
if self.branch_repo.find_by_slug(&slug).await?.is_none() {
return Ok(slug);
}
}
Ok(format!("branch-{}", Uuid::new_v4()))
}
有人能解释这是为什么吗?为什么这个小改动能修复编译错误?
使用的crate: https://crates.io/crates/names
解决方案
如同kmdreko提到的,这很可能是因为 Generator 不是 Send,意味着它不能被发送到不同的线程。你可以按照错误信息中的建议进行检查:
= note: Consider using `#[axum::debug_handler]` to improve the error message
如果你的应用运行在多线程运行时(Tokio的默认设置),那么在 .await 期间它可能会被重新调度到另一条线程。这意味着你在 .await 时所持有的所有变量都需要能够移动到不同的线程上。
你第二个示例之所以能工作,是因为你在每次循环中创建了一个新的 Generator,因此当前的那个在 .await 之前被丢弃,所以它不需要与函数一起发送。
没有简单的修复方法。可能的解决方案有:
- 在发生任何
.await之前生成所有名称 - 切换到一个不同的生成器,它是
Send - 不使用多线程运行时
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。