Как создать обработчик никеля, который использует соединение с базой данных?

Я пытаюсь сделать простое расширение для примера комментариев, создав 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");
}
Другие вопросы по тегам