【问题标题】:How to run Diesel migration with Rocket in production?如何在生产中使用 Rocket 运行 Diesel 迁移?
【发布时间】:2020-07-17 17:11:58
【问题描述】:

我需要在生产环境中为基于 Rocket 的应用程序运行 Diesel 数据库迁移。通常有几种方法可以为数据库执行迁移:

  1. 在应用程序启动时。
  2. 独立于应用程序启动。

我更喜欢使用应用程序二进制文件的--migrate 标志调用的第二个选项,但由于目标应用程序相当简单,第一种方法就可以了。

有一个 thread in the Diesel issue tracker 关于在生产中运行迁移并建议如何进行:

  1. diesel_migrations 添加到您的依赖项中
  2. 在您的箱子中添加一个extern crate diesel_migrations,并确保用#[macro_use] 装饰它
  3. 在代码的开头添加embed_migrations!()
  4. 要运行迁移,请使用 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 (&amp;db_conn);?
  • 我不知道您为什么要在柴油问题跟踪器中挖掘不完整的信息,而不是使用 corresponding 文档。除此之外,您将需要一个实现Connection 的实例,所以要么按照火箭文档(我在那里看到他们的神奇宏的东西)建议做任何事情,要么只是在应用程序开始运行迁移时建立一个新的PgConnection

标签: database rust database-migration rust-diesel rust-rocket


【解决方案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
    }
    

    【讨论】:

      猜你喜欢
      • 2021-04-27
      • 1970-01-01
      • 2020-10-16
      • 2022-12-01
      • 2022-09-23
      • 1970-01-01
      • 2014-05-07
      • 1970-01-01
      • 2018-04-10
      相关资源
      最近更新 更多