**已关闭。**此问题需要debugging details。目前不接受回答。
编辑问题以包括desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将帮助其他人回答问题。
12天前关门了。
Improve this question的
我正在使用Axum和HTMX创建一个ChatGpt克隆网站。我真的很难理解如何在Axum后端实现共享可变状态。我一直在引用this example,但当我最终崩溃并克隆示例时,它甚至没有编译。。所以我担心我引用的是过时的信息。我目前的main()函数是这样的:
pub type SharedState = Arc<RwLock<AppState>>;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AppState {
chats: Vec<Chat>,
current_chat_idx: u8,
}
#[tokio::main]
async fn main() {
let state = SharedState::default();
let router: Router<()> = Router::new()
.route("/", get(home))
.route("/chat/:current_agent", get(chat))
.route("/snippets/chat_list", get(chat_list))
.route("/snippets/chat_buttons", get(chat_buttons))
.route("/snippets/chat_history", get(chat_history))
.layer(Extension(state))
.with_state(AppState::default());
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(router.into_make_service())
.await
.unwrap();
}
字符串
上面的代码编译并运行,但我很困惑。如果.layer()让我访问SharedState结构,为什么我需要用.with_state()方法传递另一个AppState示例?这不是浪费内存吗?完全没有意义,无视这是让它编译的唯一方法?
我使用state: Extension<SharedState>
作为参数编写了这些端点:
pub async fn chat_history(state: Extension<SharedState>) -> Html<String> {
let mut shared_state = state.write().unwrap();
let agent = shared_state.current_agent();
let messages: Vec<MessageRender> = agent
.memory
.cache()
.as_ref()
.into_iter()
.map(|m| MessageRender::from(m))
.collect();
let template = fs::read_to_string("src/html/snippets/chat_history.html").unwrap();
let r = render!(&template, messages => messages);
Html(r)
}
pub async fn chat_list(state: Extension<SharedState>) -> Html<String> {
let shared_state = state.read().unwrap();
let current_chat_name = &shared_state.current_chat().name;
println!(
"Chat list current name, idx: {}, {}",
current_chat_name,
state.read().unwrap().current_chat_idx
);
let template = fs::read_to_string("src/html/snippets/chat_list.html").unwrap();
let r = render!(&template,chats => shared_state.chats, current_chat_name => current_chat_name );
Html(r)
}
型
它们都编译得很好,并且在网页上表现得像预期的那样。但是当我尝试编译这个端点时:
pub async fn post_prompt(
state: Extension<super::SharedState>,
Form(prompt): Form<PromptForm>,
) -> Html<String> {
let mut shared_state = state.write().unwrap();
let agent = shared_state.current_agent();
let res = agent.prompt(prompt.user_input).await;
if let Ok(response) = res {
println!("{}", response);
}
Html(String::new())
}
型
我得到这个错误:
error[E0277]: the trait bound `fn(axum::Extension<Arc<std::sync::RwLock<AppState>>>, Form<PromptForm>) -> impl Future<Output = axum::response::Html<std::string::String>> {api::post_prompt}: Handler<_, _, _>` is not satisfied
--> src/main.rs:83:58
|
83 | .route("/chat/:current_agent/prompt_agent", post(post_prompt))
| ---- ^^^^^^^^^^^ the trait `Handler<_, _, _>` is not implemented for fn item `fn(axum::Extension<Arc<std::sync::RwLock<AppState>>>, Form<PromptForm>) -> impl Future<Output = axum::response::Html<std::string::String>> {api::post_prompt}`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `Handler<T, S, B>`:
<Layered<L, H, T, S, B, B2> as Handler<T, S, B2>>
<MethodRouter<S, B> as Handler<(), S, B>>
型
我试着删除Form参数,尝试只使用Extension参数进行编译,但我还是遇到了同样的错误。
1条答案
按热度按时间xzv2uavs1#
post_prompt
端点未编译的原因是它正在等待std::sync::RWLock
,将RWLock更改为tokio::sync::RWLock
修复了该问题,处理程序代码现在可以编译