Как создать обработчик никеля, который использует соединение с базой данных?
Я пытаюсь сделать простое расширение для примера комментариев, создав REST API и зафиксировав сообщение в базе данных. Я создаю соединение вне рамок самого обработчика, который, как я предполагаю, лежит в основе моей проблемы. Я просто не уверен, как это исправить.
Это код для обработчика сообщений:
server.get("/comments", middleware! {
let mut stmt = conn.prepare("SELECT * FROM comment").unwrap();
let mut iter = stmt.query_map(&[], |row| {
Comment { id: row.get(0), author: row.get(1), text: row.get(2) }
}).unwrap();
let mut out: Vec<Comment> = Vec::new();
for comment in iter {
out.push(comment.unwrap());
}
json::encode(&out).unwrap()
});
Это ошибка, которую я получаю:
<nickel macros>:22:50: 22:66 error: the trait `core::marker::Sync` is not implemented for the type `core::cell::UnsafeCell<rusqlite::InnerConnection>` [E0277]
Я предполагаю, что ошибка в том, что я создал экземпляр, а затем попытался использовать его в замыкании, и эта переменная, вероятно, будет уничтожена после завершения моей основной функции.
1 ответ
Вот MCVE, который воспроизводит проблему (вы должны предоставить их при задании вопросов):
extern crate rusqlite;
#[macro_use]
extern crate nickel;
use nickel::{Nickel, HttpRouter};
use rusqlite::Connection;
fn main() {
let mut server = Nickel::new();
let conn = Connection::open_in_memory().unwrap();
server.get("/comments", middleware! {
let _stmt = conn.prepare("SELECT * FROM comment").unwrap();
""
});
server.listen("127.0.0.1:6767");
}
Sync
Черта говорит:
Типы, которые не
Sync
это те, которые имеют "внутреннюю изменчивость" не-потокобезопасным способом, таким какCell
а такжеRefCell
Что соответствует сообщению об ошибке, которое вы получаете. Что-то внутри Connection
имеет внутреннюю изменчивость, что означает, что компилятор не может автоматически гарантировать безопасность совместного использования его между потоками. У меня был недавний вопрос, который может быть полезен для разработчика Connection
, если они могут гарантировать, что безопасно делиться (возможно, сам SQLite дает гарантии).
Самое простое, что вы можете сделать, это убедиться, что только один поток имеет доступ к объекту базы данных одновременно:
use std::sync::Mutex;
fn main() {
let mut server = Nickel::new();
let conn = Mutex::new(Connection::open_in_memory().unwrap());
server.get("/comments", middleware! {
let conn = conn.lock().unwrap();
let _stmt = conn.prepare("SELECT * FROM comment").unwrap();
""
});
server.listen("127.0.0.1:6767");
}