diff --git a/frameworks/Rust/anansi/Cargo.toml b/frameworks/Rust/anansi/Cargo.toml new file mode 100644 index 00000000000..08b92229014 --- /dev/null +++ b/frameworks/Rust/anansi/Cargo.toml @@ -0,0 +1,19 @@ +[workspace] +members = [ + ".", +] + +[package] +name = "tfb-anansi" +version = "0.1.0" +edition = "2021" + +[features] +raw = [] + +[dependencies] +anansi = { git = "https://github.com/saru-tora/anansi", rev = "2567157", features = ["postgres", "minimal", "redis"] } +async-trait = "0.1.57" +rand = "0.8.4" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" diff --git a/frameworks/Rust/anansi/README.md b/frameworks/Rust/anansi/README.md new file mode 100755 index 00000000000..ebddef843ca --- /dev/null +++ b/frameworks/Rust/anansi/README.md @@ -0,0 +1,36 @@ +# [Anansi](https://saru-tora.github.io/anansi/) Benchmarking Test + +Anansi is a simple full-stack web framework for Rust. + +### Test Type Implementation Source Code + +All tests can be found in: src/hello/world/ + +## Test URLs +### JSON + +http://localhost:8080/json + +### PLAINTEXT + +http://localhost:8080/plaintext + +### DB + +http://localhost:8080/db + +### QUERY + +http://localhost:8080/query?queries= + +### CACHED QUERY + +http://localhost:8080/cached_query?queries= + +### UPDATE + +http://localhost:8080/update?queries= + +### FORTUNES + +http://localhost:8080/fortunes diff --git a/frameworks/Rust/anansi/anansi-raw.dockerfile b/frameworks/Rust/anansi/anansi-raw.dockerfile new file mode 100644 index 00000000000..96c284a8b7a --- /dev/null +++ b/frameworks/Rust/anansi/anansi-raw.dockerfile @@ -0,0 +1,11 @@ +FROM rust:1.64 + +ADD ./ /anansi +WORKDIR /anansi + +RUN cargo clean +RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --features raw + +EXPOSE 8080 + +CMD RUST_LOG=off ./target/release/tfb-anansi 0.0.0.0:8080 diff --git a/frameworks/Rust/anansi/anansi.dockerfile b/frameworks/Rust/anansi/anansi.dockerfile new file mode 100644 index 00000000000..bf6f7596193 --- /dev/null +++ b/frameworks/Rust/anansi/anansi.dockerfile @@ -0,0 +1,14 @@ +FROM rust:1.64 + +RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends redis-server + +ADD ./ /anansi +WORKDIR /anansi + +RUN cargo clean +RUN RUSTFLAGS="-C target-cpu=native" cargo build --release + +EXPOSE 8080 + +ENV RUST_LOG=off +CMD service redis-server start && ./target/release/tfb-anansi 0.0.0.0:8080 diff --git a/frameworks/Rust/anansi/benchmark_config.json b/frameworks/Rust/anansi/benchmark_config.json new file mode 100755 index 00000000000..621fafdbdba --- /dev/null +++ b/frameworks/Rust/anansi/benchmark_config.json @@ -0,0 +1,52 @@ +{ + "framework": "anansi", + "tests": [ + { + "default": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "db_url": "/db", + "fortune_url": "/fortunes", + "query_url": "/queries?q=", + "update_url": "/updates?q=", + "cached_query_url": "/cached-queries?q=", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "postgres", + "framework": "Anansi", + "language": "Rust", + "flavor": "None", + "orm": "Full", + "platform": "None", + "webserver": "hyper", + "os": "Linux", + "database_os": "Linux", + "display_name": "Anansi", + "notes": "", + "versus": "None" + }, + "raw": { + "db_url": "/db", + "fortune_url": "/fortunes", + "query_url": "/queries?q=", + "update_url": "/updates?q=", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "postgres", + "framework": "Anansi", + "language": "Rust", + "flavor": "None", + "orm": "Raw", + "platform": "None", + "webserver": "hyper", + "os": "Linux", + "database_os": "Linux", + "display_name": "Anansi [raw]", + "notes": "", + "versus": "None" + } + } + ] +} diff --git a/frameworks/Rust/anansi/settings.toml b/frameworks/Rust/anansi/settings.toml new file mode 100644 index 00000000000..ea5f708b543 --- /dev/null +++ b/frameworks/Rust/anansi/settings.toml @@ -0,0 +1,19 @@ +secret_key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +login_url = "/login" +smtp_relay = "" +smtp_username = "" +smtp_password = "" + +[caches] + +[caches.default] +location = "redis://127.0.0.1/" + +[databases] + +[databases.default] +name = "hello_world" +user = "benchmarkdbuser" +password = "benchmarkdbpass" +address = "tfb-database" +max_conn = 512 diff --git a/frameworks/Rust/anansi/src/hello/migrations/mod.rs b/frameworks/Rust/anansi/src/hello/migrations/mod.rs new file mode 100644 index 00000000000..72ca3a1f046 --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/migrations/mod.rs @@ -0,0 +1,3 @@ +use anansi::migrations::prelude::*; + +local_migrations! {} \ No newline at end of file diff --git a/frameworks/Rust/anansi/src/hello/mod.rs b/frameworks/Rust/anansi/src/hello/mod.rs new file mode 100644 index 00000000000..2266878c520 --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/mod.rs @@ -0,0 +1,7 @@ +pub mod urls; +#[cfg(not(feature = "raw"))] +pub mod records; +pub mod migrations; + +pub const APP_NAME: &'static str = "hello"; +pub mod world; diff --git a/frameworks/Rust/anansi/src/hello/records.rs b/frameworks/Rust/anansi/src/hello/records.rs new file mode 100644 index 00000000000..9df45db2f02 --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/records.rs @@ -0,0 +1,47 @@ +#![allow(non_snake_case)] +use async_trait::async_trait; +use anansi::web::{Result, BaseRequest}; +use anansi::record; +use anansi::records::{Relate, Int, Text, random_int}; +use serde::Serialize; + +#[record(table_name = "World")] +#[derive(Serialize)] +pub struct World { + #[field(primary_key = "true", default_fn = "random_int")] + pub id: Int, + pub randomNumber: Int, +} + +#[async_trait] +impl Relate for World { + async fn on_save(&self, _req: &R) -> Result<()> { + unimplemented!(); + } + async fn on_delete(&self, _req: &R) -> Result<()> { + unimplemented!(); + } +} + +#[record(table_name = "Fortune")] +pub struct Fortune { + #[field(primary_key = "true", default_fn = "random_int")] + pub id: Int, + pub message: Text, +} + +impl Fortune { + pub fn additional() -> Self { + Self {id: Int::new(0), message: Text::from("Additional fortune added at request time.".to_string())} + } +} + +#[async_trait] +impl Relate for Fortune { + async fn on_save(&self, _req: &R) -> Result<()> { + unimplemented!(); + } + async fn on_delete(&self, _req: &R) -> Result<()> { + unimplemented!(); + } +} diff --git a/frameworks/Rust/anansi/src/hello/urls.rs b/frameworks/Rust/anansi/src/hello/urls.rs new file mode 100644 index 00000000000..8eaf0efb443 --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/urls.rs @@ -0,0 +1,3 @@ +use anansi::web::prelude::*; + +routes! {} diff --git a/frameworks/Rust/anansi/src/hello/world/mod.rs b/frameworks/Rust/anansi/src/hello/world/mod.rs new file mode 100644 index 00000000000..2d3508e5707 --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/world/mod.rs @@ -0,0 +1,5 @@ +#[cfg(not(feature = "raw"))] +pub mod views; +#[cfg(feature = "raw")] +pub mod raw; +pub mod util; diff --git a/frameworks/Rust/anansi/src/hello/world/raw.rs b/frameworks/Rust/anansi/src/hello/world/raw.rs new file mode 100644 index 00000000000..24baf746bc4 --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/world/raw.rs @@ -0,0 +1,133 @@ +use crate::prelude::*; +use serde::Serialize; +use anansi::check; +use anansi::db::postgres::{PgDbRow, PgQuery}; +use super::util::get_query; +use std::borrow::Cow; +use anansi::db::DbRow; +use rand::Rng; +use std::fmt::Write; + +thread_local!(static UPDATES: Vec> = { + let mut updates = vec![Cow::from("")]; + for num in 1..=500u16 { + 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(')'); + + updates.push(Cow::from(q)); + } + updates +}); + +fn random_num() -> i32 { + rand::thread_rng().gen_range(1..=10_000) +} + +#[derive(Copy, Clone, Serialize, Debug)] +pub struct World { + id: i32, + randomnumber: i32, +} + +#[derive(Serialize, Debug)] +pub struct Fortune { + id: i32, + message: Cow<'static, str>, +} + +#[base_view] +fn base(_req: &mut R) -> Result {} + +#[viewer] +impl WorldView { + async fn get_world(req: &R) -> Result { + PgQuery::new("SELECT * FROM world WHERE id = $1") + .bind(random_num()) + .fetch_one(req) + .await + } + async fn get_worlds(req: &R) -> Result> { + let q = get_query(req.params()); + let mut worlds = Vec::with_capacity(q as usize); + for _ in 0..q { + let row = Self::get_world(req).await?; + let world = World { + id: row.try_i32("id")?, + randomnumber: row.try_i32("randomnumber")?, + }; + worlds.push(world); + } + Ok(worlds) + } + #[check(Site::is_visitor)] + pub async fn db(req: &mut R) -> Result { + let row = Self::get_world(req).await?; + let world = World { + id: row.try_i32("id")?, + randomnumber: row.try_i32("randomnumber")?, + }; + Response::json(&world) + } + #[check(Site::is_visitor)] + pub async fn queries(req: &mut R) -> Result { + let worlds = Self::get_worlds(req).await?; + Response::json(&worlds) + } + #[view(Site::is_visitor)] + pub async fn raw_fortunes(req: &mut R) -> Result { + let title = "Fortunes"; + let rows = PgQuery::new("SELECT * FROM fortune") + .fetch_all(req) + .await?; + let mut fortunes = vec![Fortune { + id: 0, + message: Cow::Borrowed("Additional fortune added at request time.") + }]; + for row in rows { + fortunes.push(Fortune { + id: row.try_i32("id")?, + message: Cow::Owned(row.try_string("message")?), + }) + } + fortunes.sort_by(|it, next| it.message.cmp(&next.message)); + } + #[check(Site::is_visitor)] + pub async fn updates(req: &mut R) -> Result { + let q = get_query(req.params()) as usize; + let mut worlds = Vec::with_capacity(q); + let mut update = Cow::from(""); + UPDATES.with(|u| { + update = u[q].clone(); + }); + let mut updates = PgQuery::new(&update); + for _ in 0..q { + let row = Self::get_world(req).await?; + let world = World { + id: row.try_i32("id")?, + randomnumber: random_num(), + }; + updates = updates.bind(world.id) + .bind(world.randomnumber); + worlds.push(world); + } + for world in &worlds { + updates = updates.bind(world.id); + } + updates.execute(req).await?; + Response::json(&worlds) + } +} diff --git a/frameworks/Rust/anansi/src/hello/world/templates/.parsed/base.in b/frameworks/Rust/anansi/src/hello/world/templates/.parsed/base.in new file mode 100644 index 00000000000..c93a1f8edc3 --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/world/templates/.parsed/base.in @@ -0,0 +1,9 @@ +{let mut _c = String::new();_c.push_str(" + + + ");_c.push_str(&_base_args._title);_c.push_str(" + + + ");_c.push_str(&_base_args._content);_c.push_str(" + +");Ok(anansi::web::Response::new(200, _c.into_bytes()))} \ No newline at end of file diff --git a/frameworks/Rust/anansi/src/hello/world/templates/.parsed/base_args.in b/frameworks/Rust/anansi/src/hello/world/templates/.parsed/base_args.in new file mode 100644 index 00000000000..9ad5b91f42b --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/world/templates/.parsed/base_args.in @@ -0,0 +1 @@ +pub struct Args {pub _title: String,pub _content: String,}impl anansi::cache::Cacheable for Args {fn to_bytes(&self) -> Vec {let mut v = vec![];v.append(&mut self._title.len().to_ne_bytes().to_vec());v.append(&mut self._title.as_bytes().to_vec());v.append(&mut self._content.len().to_ne_bytes().to_vec());v.append(&mut self._content.as_bytes().to_vec());v} fn from_bytes(mut __b: Vec) -> anansi::web::Result {let mut buf = __b.split_off(8); let l = usize::from_ne_bytes(__b.try_into().unwrap()); let mut __b = buf.split_off(l); let _title = String::from_utf8(buf)?;let mut buf = __b.split_off(8); let l = usize::from_ne_bytes(__b.try_into().unwrap()); let mut __b = buf.split_off(l); let _content = String::from_utf8(buf)?;Ok(Self {_title, _content, })}} impl Args {pub fn new() -> Self {Self {_title: String::new(), _content: String::new(), }}} \ No newline at end of file diff --git a/frameworks/Rust/anansi/src/hello/world/templates/.parsed/fortunes.in b/frameworks/Rust/anansi/src/hello/world/templates/.parsed/fortunes.in new file mode 100644 index 00000000000..7cf8984f743 --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/world/templates/.parsed/fortunes.in @@ -0,0 +1,6 @@ +{_args._title = {let mut _c = String::new();_c.push_str("");_c.push_str(&anansi::web::html_escape(&format!("{}", title)));_c.push_str(""); _c};_args._content = {let mut _c = String::new();_c.push_str(" + + ");for fortune in fortunes {_c.push_str(" + + ");}_c.push_str(" +
idmessage
");_c.push_str(&anansi::web::html_escape(&format!("{}", fortune.pk())));_c.push_str("");_c.push_str(&anansi::web::html_escape(&format!("{}", fortune.message)));_c.push_str("
"); _c};_args} \ No newline at end of file diff --git a/frameworks/Rust/anansi/src/hello/world/templates/.parsed/index.in b/frameworks/Rust/anansi/src/hello/world/templates/.parsed/index.in new file mode 100644 index 00000000000..17b9c49d56b --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/world/templates/.parsed/index.in @@ -0,0 +1 @@ +{_args._title = {let mut _c = String::new();_c.push_str("");_c.push_str(&anansi::web::html_escape(&format!("{}", title)));_c.push_str(""); _c};_args._content = {let mut _c = String::new();_c.push_str("

");_c.push_str(&anansi::web::html_escape(&format!("{}", title)));_c.push_str("

"); _c};_args} \ No newline at end of file diff --git a/frameworks/Rust/anansi/src/hello/world/templates/.parsed/raw_fortunes.in b/frameworks/Rust/anansi/src/hello/world/templates/.parsed/raw_fortunes.in new file mode 100644 index 00000000000..3f510b939d2 --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/world/templates/.parsed/raw_fortunes.in @@ -0,0 +1,5 @@ +{_args._title = {let mut _c = String::new();_c.push_str(&anansi::web::html_escape(&format!("{}", title))); _c}; +_args._content = {let mut _c = String::new();_c.push_str(""); +for fortune in fortunes {_c.push_str(""); +} _c.push_str("
idmessage
"); _c.push_str(&anansi::web::html_escape(&format!("{}", fortune.id))); +_c.push_str(""); _c.push_str(&anansi::web::html_escape(&format!("{}", fortune.message))); _c.push_str("
"); _c};_args} diff --git a/frameworks/Rust/anansi/src/hello/world/templates/base.rs.html b/frameworks/Rust/anansi/src/hello/world/templates/base.rs.html new file mode 100644 index 00000000000..440d37a95eb --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/world/templates/base.rs.html @@ -0,0 +1,9 @@ + + + + @block title + + + @block content + + diff --git a/frameworks/Rust/anansi/src/hello/world/templates/fortunes.rs.html b/frameworks/Rust/anansi/src/hello/world/templates/fortunes.rs.html new file mode 100644 index 00000000000..0d4e369792a --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/world/templates/fortunes.rs.html @@ -0,0 +1,10 @@ +@block title {@title} + +@block content { + + + @for fortune in fortunes { + + } +
idmessage
@fortune.pk()@fortune.message
+} diff --git a/frameworks/Rust/anansi/src/hello/world/templates/raw_fortunes.rs.html b/frameworks/Rust/anansi/src/hello/world/templates/raw_fortunes.rs.html new file mode 100644 index 00000000000..1ad9bd10a1f --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/world/templates/raw_fortunes.rs.html @@ -0,0 +1,10 @@ +@block title {@title} + +@block content { + + + @for fortune in fortunes { + + } +
idmessage
@fortune.id@fortune.message
+} diff --git a/frameworks/Rust/anansi/src/hello/world/util.rs b/frameworks/Rust/anansi/src/hello/world/util.rs new file mode 100644 index 00000000000..8e8998f2b1f --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/world/util.rs @@ -0,0 +1,16 @@ +use anansi::web::Parameters; + +pub fn get_query(params: &Parameters) -> i16 { + if let Ok(q) = params.get("q") { + if let Ok(q) = q.parse() { + if q > 1 { + return if q <= 500 { + q + } else { + 500 + }; + } + } + } + 1 +} diff --git a/frameworks/Rust/anansi/src/hello/world/views.rs b/frameworks/Rust/anansi/src/hello/world/views.rs new file mode 100644 index 00000000000..5ee366c73b6 --- /dev/null +++ b/frameworks/Rust/anansi/src/hello/world/views.rs @@ -0,0 +1,90 @@ +use crate::prelude::*; +use anansi::cache::prelude::*; +use anansi::records::Int; +use super::super::records::{World, Fortune}; +use super::util::get_query; +use serde::Serialize; +use anansi::{check, raw_bulk_update}; +use rand::Rng; + +fn random_i32() -> i32 { + rand::thread_rng().gen_range(1..=10_000) +} + +fn random_int() -> Int { + Int::new(random_i32()) +} + +#[derive(Serialize)] +struct Message { + message: &'static str, +} + +#[base_view] +fn base(_req: &mut R) -> Result {} + +#[viewer] +impl WorldView { + #[check(Site::is_visitor)] + pub async fn json(req: &mut R) -> Result { + let message = Message {message: "Hello, World!"}; + Response::json(&message) + } + async fn get_world(req: &R) -> Result { + World::find(random_int()).get(req).await + } + async fn get_worlds(req: &R) -> Result> { + let q = get_query(req.params()); + let mut worlds = Vec::with_capacity(q as usize); + for _ in 0..q { + let world = Self::get_world(req).await?; + worlds.push(world); + } + Ok(worlds) + } + #[check(Site::is_visitor)] + pub async fn db(req: &mut R) -> Result { + let world = Self::get_world(req).await?; + Response::json(&world) + } + #[check(Site::is_visitor)] + pub async fn queries(req: &mut R) -> Result { + let worlds = Self::get_worlds(req).await?; + Response::json(&worlds) + } + #[view(Site::is_visitor)] + pub async fn fortunes(req: &mut R) -> Result { + let title = "Fortunes"; + let mut fortunes = Fortune::get_all().query(req).await?; + fortunes.push(Fortune::additional()); + fortunes.sort_by(|it, next| it.message.cmp(&next.message)); + } + #[check(Site::is_visitor)] + pub async fn updates(req: &mut R) -> Result { + let mut worlds = Self::get_worlds(req).await?; + for world in &mut worlds { + world.randomNumber = random_int(); + } + transact!(req, raw_bulk_update!(req, World, &worlds, randomNumber).await)?; + Response::json(&worlds) + } + #[check(Site::is_visitor)] + pub async fn plaintext(req: &mut R) -> Result { + Ok(Response::text("Hello, World!".to_string())) + } + #[check(Site::is_visitor)] + pub async fn cached_queries(req: &mut R) -> Result { + let q = get_query(req.params()); + let mut ids = vec![]; + for _ in 0..q { + ids.push(random_i32().to_string()); + } + let mut worlds = vec!['[' as u8]; + for mut world in req.cache().get_many(ids).await? { + worlds.append(&mut world); + } + worlds.pop(); + worlds.push(']' as u8); + Response::json_bytes(worlds) + } +} diff --git a/frameworks/Rust/anansi/src/http_errors/500.html b/frameworks/Rust/anansi/src/http_errors/500.html new file mode 100644 index 00000000000..1c14f7cd7f3 --- /dev/null +++ b/frameworks/Rust/anansi/src/http_errors/500.html @@ -0,0 +1,11 @@ + + + + + 500 Internal Server Error + + +

Internal Server Error

+

Sorry, something went wrong.

+ + diff --git a/frameworks/Rust/anansi/src/http_errors/mod.rs b/frameworks/Rust/anansi/src/http_errors/mod.rs new file mode 100644 index 00000000000..38b44033152 --- /dev/null +++ b/frameworks/Rust/anansi/src/http_errors/mod.rs @@ -0,0 +1 @@ +pub mod views; diff --git a/frameworks/Rust/anansi/src/http_errors/templates/.parsed/not_found.in b/frameworks/Rust/anansi/src/http_errors/templates/.parsed/not_found.in new file mode 100644 index 00000000000..79a388a74b5 --- /dev/null +++ b/frameworks/Rust/anansi/src/http_errors/templates/.parsed/not_found.in @@ -0,0 +1,11 @@ +{let mut _c = String::new();_c.push_str(" + + + + Not Found + + +

404

+

Page not found.

+ +");Ok(anansi::web::Response::new(200, _c.into_bytes()))} \ No newline at end of file diff --git a/frameworks/Rust/anansi/src/http_errors/templates/not_found.rs.html b/frameworks/Rust/anansi/src/http_errors/templates/not_found.rs.html new file mode 100644 index 00000000000..eaf9a979ee7 --- /dev/null +++ b/frameworks/Rust/anansi/src/http_errors/templates/not_found.rs.html @@ -0,0 +1,11 @@ + + + + + Not Found + + +

404

+

Page not found.

+ + diff --git a/frameworks/Rust/anansi/src/http_errors/views.rs b/frameworks/Rust/anansi/src/http_errors/views.rs new file mode 100644 index 00000000000..04872858818 --- /dev/null +++ b/frameworks/Rust/anansi/src/http_errors/views.rs @@ -0,0 +1,12 @@ +use anansi::{check, viewer, render}; +use anansi::web::{Result, Response}; +use anansi::site::Site; +use crate::project::Request; + +#[viewer] +impl ErrorView { + #[check(Site::is_visitor)] + pub async fn not_found(_req: &mut R) -> Result { + render!("not_found") + } +} diff --git a/frameworks/Rust/anansi/src/main.rs b/frameworks/Rust/anansi/src/main.rs new file mode 100644 index 00000000000..54ea7cfc5d6 --- /dev/null +++ b/frameworks/Rust/anansi/src/main.rs @@ -0,0 +1,33 @@ +use anansi::*; + +mod urls; +mod project; +mod http_errors; +mod hello; + +apps! { + hello, +} + +app_statics! {} + +#[cfg(feature = "raw")] +min_main!(); + +#[cfg(not(feature = "raw"))] +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"); + let mut items = vec![]; + for world in worlds { + let id = world.pk().to_string(); + let mut bytes = serde_json::to_vec(&world).expect("problem serializing world"); + bytes.push(',' as u8); + items.push((id, bytes)); + } + server.cache.set_many(&items).await.expect("problem caching world"); + } +}); diff --git a/frameworks/Rust/anansi/src/project.rs b/frameworks/Rust/anansi/src/project.rs new file mode 100644 index 00000000000..08b6f41e15b --- /dev/null +++ b/frameworks/Rust/anansi/src/project.rs @@ -0,0 +1,11 @@ +use anansi::project::prelude::*; + +#[cfg(feature = "raw")] +app_cache!(local); + +#[cfg(not(feature = "raw"))] +app_cache!(redis); + +database!(postgres); + +middleware!(); diff --git a/frameworks/Rust/anansi/src/urls.rs b/frameworks/Rust/anansi/src/urls.rs new file mode 100644 index 00000000000..beefcc8825b --- /dev/null +++ b/frameworks/Rust/anansi/src/urls.rs @@ -0,0 +1,25 @@ +use anansi::web::prelude::*; +#[cfg(not(feature = "raw"))] +use crate::hello::world::views::WorldView; + +#[cfg(not(feature = "raw"))] +routes! { + path!("/json", WorldView::json), + path!("/db", WorldView::db), + path!("/queries", WorldView::queries), + path!("/fortunes", WorldView::fortunes), + path!("/updates", WorldView::updates), + path!("/plaintext", WorldView::plaintext), + path!("/cached-queries", WorldView::cached_queries), +} + +#[cfg(feature = "raw")] +use crate::hello::world::raw::WorldView; + +#[cfg(feature = "raw")] +routes! { + path!("/db", WorldView::db), + path!("/queries", WorldView::queries), + path!("/fortunes", WorldView::raw_fortunes), + path!("/updates", WorldView::updates), +}