Преглед изворни кода

Update to anansi 0.14.2 (#8051)

* Update to anansi 0.14.2

* fixed update test for anansi

* fixed other update test for anansi

---------

Co-authored-by: sarutora <example.com>
saru-tora пре 2 година
родитељ
комит
6080b20570

+ 1 - 1
frameworks/Rust/anansi/Cargo.toml

@@ -12,7 +12,7 @@ edition = "2021"
 raw = []
 
 [dependencies]
-anansi = { git = "https://github.com/saru-tora/anansi", rev = "87830d6", features = ["postgres", "minimal", "redis"] }
+anansi = { git = "https://github.com/saru-tora/anansi", rev = "b59c7d0", features = ["postgres", "minimal", "redis"] }
 async-trait = "0.1.57"
 rand = "0.8.4"
 serde = "1"

+ 2 - 2
frameworks/Rust/anansi/benchmark_config.json

@@ -22,7 +22,7 @@
         "webserver": "hyper",
         "os": "Linux",
         "database_os": "Linux",
-        "display_name": "Anansi",
+        "display_name": "Anansi [minimal]",
         "notes": "",
         "versus": "None"
       },
@@ -44,7 +44,7 @@
         "webserver": "hyper",
         "os": "Linux",
         "database_os": "Linux",
-        "display_name": "Anansi [raw]",
+        "display_name": "Anansi [minimal, raw]",
         "notes": "",
         "versus": "None"
       }

+ 47 - 7
frameworks/Rust/anansi/src/hello/middleware.rs

@@ -1,6 +1,6 @@
-use std::fmt;
+use std::fmt::{self, Write};
 use std::sync::Arc;
-use anansi::db::postgres::{PgDbRow, PgDbRowVec, PgStatement};
+use anansi::db::postgres::{PgDbPool, PgDbRow, PgDbRowVec, PgStatement};
 
 #[macro_export]
 macro_rules! impl_pg {
@@ -9,16 +9,45 @@ macro_rules! impl_pg {
         impl crate::hello::middleware::Pg for HttpRequest {
             async fn get_world(&self) -> anansi::web::Result<anansi::db::postgres::PgDbRow> {
                 use anansi::web::BaseRequest;
-                self.mid.stmt.0.world.fetch_one(&[&Self::random_num()], self.raw().pool()).await
+                self.raw().app_state().stmt.0.world.fetch_one(&[&Self::random_num()], self.raw().pool()).await
+            }
+            async fn update_worlds(&self, n: usize, params: &[&(dyn tokio_postgres::types::ToSql + Sync)]) -> anansi::web::Result<()> {
+                use anansi::web::BaseRequest;
+                self.raw().app_state().stmt.0.updates[n].execute(params, self.raw().pool()).await
             }
             async fn get_fortunes(&self) -> anansi::web::Result<anansi::db::postgres::PgDbRowVec> {
                 use anansi::web::BaseRequest;
-                self.mid.stmt.0.fortune.fetch_all(&[], self.raw().pool()).await
+                self.raw().app_state().stmt.0.fortune.fetch_all(&[], self.raw().pool()).await
+            }
+        }
+        impl crate::hello::middleware::AsStmt for AppData {
+            fn as_stmt(&self) -> &crate::hello::middleware::Stmt {
+                &self.stmt
             }
         }
     }
 }
 
+fn update_statement(num: u16) -> String {
+    let mut pl = 1;
+    let mut q = "UPDATE world SET randomnumber = CASE id ".to_string();
+    for _ in 1..=num {
+        let _ = write!(q, "WHEN ${} THEN ${} ", pl, pl + 1);
+        pl += 2;
+    }
+
+    q.push_str("ELSE randomnumber END WHERE id IN (");
+
+    for _ in 1..=num {
+        let _ = write!(q, "${},", pl);
+        pl += 1;
+    }
+
+    q.pop();
+    q.push(')');
+    q
+}
+
 #[derive(Clone)]
 pub struct Stmt(pub Arc<State>);
 
@@ -30,19 +59,29 @@ impl fmt::Debug for Stmt {
 }
 
 impl Stmt {
-    pub async fn new(raw: &mut anansi::web::RawRequest<anansi::db::postgres::PgDbPool>) -> anansi::web::Result<Self> {
+    pub async fn new(pool: &PgDbPool) -> anansi::web::Result<Self> {
+        let mut updates = vec![];
+        for n in 1..=500 {
+            updates.push(PgStatement::new(&update_statement(n), pool).await?);
+        }
         Ok(Self(Arc::new(State {
-            world: PgStatement::new("SELECT * FROM world WHERE id = $1", raw.pool()).await?,
-            fortune: PgStatement::new("SELECT * FROM fortune", raw.pool()).await?,
+            world: PgStatement::new("SELECT * FROM world WHERE id = $1", pool).await?,
+            updates,
+            fortune: PgStatement::new("SELECT * FROM fortune", pool).await?,
         })))
     }
 }
 
 pub struct State {
     pub world: PgStatement,
+    pub updates: Vec<PgStatement>,
     pub fortune: PgStatement,
 }
 
+pub trait AsStmt {
+    fn as_stmt(&self) -> &Stmt;
+}
+
 #[async_trait::async_trait]
 pub trait Pg {
     fn random_num() -> i32 {
@@ -50,5 +89,6 @@ pub trait Pg {
         rand::thread_rng().gen_range(1..=10_000)
     }
     async fn get_world(&self) -> anansi::web::Result<PgDbRow>;
+    async fn update_worlds(&self, n: usize, params: &[&(dyn tokio_postgres::types::ToSql + Sync)]) -> anansi::web::Result<()>;
     async fn get_fortunes(&self) -> anansi::web::Result<PgDbRowVec>;
 }

+ 19 - 41
frameworks/Rust/anansi/src/hello/world/raw.rs

@@ -1,33 +1,11 @@
 use crate::prelude::*;
+use crate::hello::middleware::Pg;
 use serde::Serialize;
-use anansi::{check, prep};
+use anansi::check;
 use super::util::get_query;
-use std::borrow::Cow;
-use anansi::db::DbRow;
 use rand::Rng;
-use std::fmt::Write;
 use tokio_postgres::types::ToSql;
 
-fn update_statement(num: u16) -> String {
-    let mut pl = 1;
-    let mut q = "UPDATE world SET randomnumber = CASE id ".to_string();
-    for _ in 1..=num {
-        let _ = write!(q, "WHEN ${} THEN ${} ", pl, pl + 1);
-        pl += 2;
-    }
-
-    q.push_str("ELSE randomnumber END WHERE id IN (");
-
-    for _ in 1..=num {
-        let _ = write!(q, "${},", pl);
-        pl += 1;
-    }
-
-    q.pop();
-    q.push(')');
-    q
-}
-
 fn random_num() -> i32 {
     rand::thread_rng().gen_range(1..=10_000)
 }
@@ -39,36 +17,36 @@ pub struct World {
 }
 
 #[derive(Serialize, Debug)]
-pub struct Fortune {
+pub struct Fortune<'a> {
     id: i32,
-    message: Cow<'static, str>,
+    message: &'a str,
 }
 
 #[base_view]
 fn base<R: Request>(_req: &mut R) -> Result<Response> {}
 
 #[viewer]
-impl<R: Request> WorldView<R> {
+impl<R: Request + Pg> WorldView<R> {
+    async fn one_world(req: &R) -> Result<World> {
+        let row = req.get_world().await?;
+        let world = World {
+            id: row.get_i32(0),
+            randomnumber: row.get_i32(1),
+        };
+        Ok(world)
+    }
     async fn get_worlds(req: &R) -> Result<Vec<World>> {
         let q = get_query(req.params());
         let mut worlds = Vec::with_capacity(q as usize);
         for _ in 0..q {
-            let row = req.get_world().await?;
-            let world = World {
-                id: row.try_i32("id")?,
-                randomnumber: row.try_i32("randomnumber")?,
-            };
+            let world = Self::one_world(req).await?;
             worlds.push(world);
         }
         Ok(worlds)
     }
     #[check(Site::is_visitor)]
     pub async fn db(req: &mut R) -> Result<Response> {
-        let row = req.get_world().await?;
-        let world = World {
-            id: row.get_i32(0),
-            randomnumber: row.get_i32(1),
-        };
+        let world = Self::one_world(req).await?;
         Response::json(&world)
     }
     #[check(Site::is_visitor)]
@@ -83,11 +61,11 @@ impl<R: Request> WorldView<R> {
         let mut fortunes = Vec::with_capacity(rows.len() + 1);
         fortunes.push(Fortune {
             id: 0,
-            message: Cow::Borrowed("Additional fortune added at request time.")
+            message: "Additional fortune added at request time.",
         });
         fortunes.extend(rows.iter().map(|row| Fortune {
             id: row.get(0),
-            message: Cow::Owned(row.get(1)),
+            message: row.get(1),
         }));
         fortunes.sort_by(|it, next| it.message.cmp(&next.message));
     }
@@ -99,7 +77,7 @@ impl<R: Request> WorldView<R> {
         for _ in 0..q {
             let row = req.get_world().await?;
             let world = World {
-                id: row.try_i32("id")?,
+                id: row.get_i32(0),
                 randomnumber: random_num(),
             };
             worlds.push(world);
@@ -111,7 +89,7 @@ impl<R: Request> WorldView<R> {
         for world in &worlds {
             params.push(&world.id);
         }
-        prep!(req, format!("update{}", q), update_statement(q as u16), params.as_slice(), execute)?;
+        req.update_worlds(q - 1, params.as_slice()).await?;
         Response::json(&worlds)
     }
     #[check(Site::is_visitor)]

+ 4 - 6
frameworks/Rust/anansi/src/hello/world/templates/.parsed/raw_fortunes.in

@@ -1,6 +1,4 @@
-{_args._content = {let mut _c = String::new();_c.push_str("    <table>
-    <tr><th>id</th><th>message</th></tr>
-    ");for fortune in fortunes {_c.push_str("
-        <tr><td>");_c.push_str(&anansi::web::html_escape(&format!("{}", fortune.id)));_c.push_str("</td><td>");_c.push_str(&anansi::web::html_escape(&format!("{}", fortune.message)));_c.push_str("</td></tr>
-    ");}_c.push_str("
-    </table>"); _c};_args._title = {let mut _c = String::new();_c.push_str("");_c.push_str(&anansi::web::html_escape(&format!("{}", title)));_c.push_str(""); _c};_args}
+{_args._content = {let mut _c = String::new();_c.push_str("<table><tr><th>id</th><th>message</th></tr>");
+for fortune in fortunes {_c.push_str("<tr><td>");_c.push_str(&anansi::web::html_escape(&format!("{}", fortune.id)));_c.push_str("</td><td>");
+_c.push_str(&anansi::web::html_escape(&format!("{}", fortune.message)));_c.push_str("</td></tr>");}_c.push_str("</table>"); _c};
+_args._title = {let mut _c = String::new();_c.push_str(&anansi::web::html_escape(&format!("{}", title))); _c};_args}

+ 1 - 1
frameworks/Rust/anansi/src/hello/world/views.rs

@@ -65,7 +65,7 @@ impl<R: Request> WorldView<R> {
         for world in &mut worlds {
             world.randomNumber = random_int();
         }
-        transact!(req, raw_bulk_update!(req, World, &worlds, randomNumber).await)?;
+        raw_bulk_update!(req, World, &worlds, randomNumber).await?;
         Response::json(&worlds)
     }
     #[check(Site::is_visitor)]

+ 2 - 1
frameworks/Rust/anansi/src/main.rs

@@ -15,7 +15,8 @@ min_main!(server, {
     use anansi::cache::prelude::*;
     use hello::records::World;
     use anansi::records::Record;
-    let worlds = World::get_all().raw_query(&server.pool).await.expect("problem fetching worlds");
+    use anansi::db::AsDb;
+    let worlds = World::get_all().raw_query(server.app_data.as_db()).await.expect("problem fetching worlds");
     let mut items = vec![];
     for world in worlds {
         let id = world.pk().to_string();

+ 37 - 2
frameworks/Rust/anansi/src/project.rs

@@ -1,7 +1,8 @@
 use anansi::project::prelude::*;
+use crate::app_migrations;
 
 #[cfg(feature = "raw")]
-use super::hello::middleware::{Pg, Stmt};
+use super::hello::middleware::Stmt;
 
 #[cfg(feature = "raw")]
 use crate::impl_pg;
@@ -18,10 +19,44 @@ database!(postgres);
 raw_middleware!();
 
 #[cfg(feature = "raw")]
-anansi::setup!(stmt, Stmt, Pg);
+anansi::setup!();
 
 #[cfg(feature = "raw")]
 impl_pg!();
 
 #[cfg(not(feature = "raw"))]
 middleware!();
+
+#[derive(Clone, Debug)]
+pub struct AppData {
+    pub pool: Pool,
+    #[cfg(feature = "raw")]
+    pub stmt: Stmt,
+}
+
+#[cfg(feature = "raw")]
+impl AppData {
+    pub async fn new() -> Self {
+        let pool = anansi::server::get_db::<AppData>(app_migrations).await;
+        let stmt = Stmt::new(&pool).await.unwrap();
+        Self {pool, stmt}
+    }
+}
+
+#[cfg(not(feature = "raw"))]
+impl AppData {
+    pub async fn new() -> Self {
+        let pool = anansi::server::get_db::<AppData>(app_migrations).await;
+        Self {pool}
+    }
+}
+
+impl anansi::db::AsDb for AppData {
+    type SqlDb = Pool;
+    fn as_db(&self) -> &Pool {
+        &self.pool
+    }
+    fn as_db_mut(&mut self) -> &mut Pool {
+        &mut self.pool
+    }
+}

+ 4 - 1
frameworks/Rust/anansi/src/urls.rs

@@ -19,7 +19,10 @@ pub fn routes<R: Request>() -> Router<R> {
 use crate::hello::world::raw::WorldView;
 
 #[cfg(feature = "raw")]
-pub fn routes<R: Request>() -> Router<R> {
+use crate::hello::middleware::Pg;
+
+#[cfg(feature = "raw")]
+pub fn routes<R: Request + Pg>() -> Router<R> {
     Router::new()
         .route("/db", WorldView::db)
         .route("/queries", WorldView::queries)