如何在生产中使用 Rocket 运行 Diesel 迁移?
Posted
技术标签:
【中文标题】如何在生产中使用 Rocket 运行 Diesel 迁移?【英文标题】:How to run Diesel migration with Rocket in production? 【发布时间】:2020-07-17 17:11:58 【问题描述】:我需要在生产环境中为基于 Rocket 的应用程序运行 Diesel 数据库迁移。通常有几种方法可以为数据库执行迁移:
-
在应用程序启动时。
独立于应用程序启动。
我更喜欢使用应用程序二进制文件的--migrate
标志调用的第二个选项,但由于目标应用程序相当简单,第一种方法就可以了。
有一个 thread in the Diesel issue tracker 关于在生产中运行迁移并建议如何进行:
将
diesel_migrations
添加到您的依赖项中 在您的箱子中添加一个extern crate diesel_migrations
,并确保用#[macro_use]
装饰它 在代码的开头添加embed_migrations!()
要运行迁移,请使用embedded_migrations::run(&db_conn)
在main.rs
我做了:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_migrations;
#[macro_use]
extern crate rocket;
#[macro_use]
extern crate rocket_contrib;
#[database("my_db_name")]
pub struct DbConn(diesel::PgConnection);
fn main()
// Update database
embed_migrations!();
embedded_migrations::run(&DbConn);
// Launch the app
...
这会导致错误:
error[E0277]: the trait bound `fn(diesel::r2d2::PooledConnection<<diesel::PgConnection as rocket_contrib::databases::Poolable>::Manager>) -> DbConn DbConn: diesel::Connection` is not satisfied
--> src/main.rs:30:30
|
29 | embed_migrations!();
| --------------------
| |
| required by this bound in `main::embedded_migrations::run`
30 | embedded_migrations::run(&DbConn);
| ^^^^^^^ the trait `diesel::Connection` is not implemented for `fn(diesel::r2d2::PooledConnection<<diesel::PgConnection as rocket_contrib::databases::Poolable>::Manager>) -> DbConn DbConn`
|
= note: required because of the requirements on the impl of `diesel_migrations::MigrationConnection` for `fn(diesel::r2d2::PooledConnection<<diesel::PgConnection as rocket_contrib::databases::Poolable>::Manager>) -> DbConn DbConn`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
如何解决?
【问题讨论】:
你不应该用连接实例而不是连接类型来调用run
吗?即:let db_conn = whatever; embedded_migrations::run (&db_conn);
?
我不知道您为什么要在柴油问题跟踪器中挖掘不完整的信息,而不是使用 corresponding 文档。除此之外,您将需要一个实现Connection
的实例,所以要么按照火箭文档(我在那里看到他们的神奇宏的东西)建议做任何事情,要么只是在应用程序开始运行迁移时建立一个新的PgConnection
。
【参考方案1】:
谷歌了一些,找到了工作示例here。
键码
use rocket::Rocket;
use rocket::fairing::AdHoc;
// This macro from `diesel_migrations` defines an `embedded_migrations` module
// containing a function named `run`. This allows the example to be run and
// tested without any outside setup of the database.
embed_migrations!();
#[database("sqlite_database")]
pub struct DbConn(SqliteConnection);
fn run_db_migrations(rocket: Rocket) -> Result<Rocket, Rocket>
let conn = DbConn::get_one(&rocket).expect("database connection");
match embedded_migrations::run(&*conn)
Ok(()) => Ok(rocket),
Err(e) =>
error!("Failed to run database migrations: :?", e);
Err(rocket)
fn rocket() -> Rocket
rocket::ignite()
.attach(DbConn::fairing())
.attach(AdHoc::on_attach("Database Migrations", run_db_migrations))
.mount("/", StaticFiles::from("static/"))
.mount("/", routes![index])
.mount("/todo", routes![new, toggle, delete])
.attach(Template::fairing())
【讨论】:
【参考方案2】:以 SS_Rebelious 的回答为基础,这就是我必须为 Rocket 0.5 做的事情
#[macro_use]
extern crate rocket;
#[macro_use]
extern crate diesel_migrations;
use capt_server::api::routes;
use diesel_migrations::embed_migrations;
use envy;
use rocket::fairing::AdHoc;
use rocket::Build, Rocket;
use rocket_sync_db_pools::database;
#[database("sqlite_db")]
pub struct Db(diesel::SqliteConnection);
// This macro from `diesel_migrations` defines an `embedded_migrations` module
// containing a function named `run`. This allows the example to be run and
// tested without any outside setup of the database.
embed_migrations!();
#[launch]
fn rocket() -> _
rocket::build()
.attach(Db::fairing())
.attach(AdHoc::try_on_ignite("Database Migrations", migrate))
.mount("/", routes())
async fn migrate(rocket: Rocket<Build>) -> Result<Rocket<Build>, Rocket<Build>>
let db = Db::get_one(&rocket).await.expect("database connection");
db.run(|conn| match embedded_migrations::run(&*conn)
Ok(()) => Ok(rocket),
Err(e) =>
error!("Failed to run database migrations: :?", e);
Err(rocket)
)
.await
【讨论】:
以上是关于如何在生产中使用 Rocket 运行 Diesel 迁移?的主要内容,如果未能解决你的问题,请参考以下文章
diesel.rs 和rocket.rs:不明白为啥它需要一个数据库表
带有 Rocket 和 Diesel 的多租户 Web 应用程序