如何创建使用数据库连接的Nickel处理程序



我试图通过创建一个RESTneneneba 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]

我认为错误是因为我创建了实例,然后试图在闭包中使用它,一旦我的主函数完成,该变量可能会被销毁。

这里有一个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的类型是那些以非线程安全的方式具有"内部可变性"的类型,如CellRefCell

与您收到的错误消息相匹配。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");
}

最新更新