From 2624f475968858caaaaeab7c2c54c2b96070336e Mon Sep 17 00:00:00 2001 From: Joe Date: Sat, 29 Jul 2023 19:47:55 -0400 Subject: [PATCH 1/4] :building_construction: Add examples directory To get this to work, we also need to move the code from src/ to its own package in memcache. This is because we're adding a complex example with axum, which includes its own Cargo.toml. This has other effects: it means that you can't add single file examples anymore. It must be a crate. This is the same decision used in the Axum repo, and is just a current limitation of cargo. --- Cargo.toml | 30 +++----- examples/axum/Cargo.toml | 11 +++ examples/axum/src/main.rs | 72 +++++++++++++++++++ examples/pooled/Cargo.toml | 8 +++ examples/pooled/src/main.rs | 27 +++++++ examples/simple/Cargo.toml | 8 +++ examples/simple/src/main.rs | 28 ++++++++ memcache/Cargo.toml | 22 ++++++ {src => memcache/src}/client.rs | 0 {src => memcache/src}/connection.rs | 0 {src => memcache/src}/error.rs | 0 {src => memcache/src}/lib.rs | 0 {src => memcache/src}/protocol/ascii.rs | 0 {src => memcache/src}/protocol/binary.rs | 0 .../src}/protocol/binary_packet.rs | 0 {src => memcache/src}/protocol/mod.rs | 0 {src => memcache/src}/stream/mod.rs | 0 {src => memcache/src}/stream/udp_stream.rs | 0 {src => memcache/src}/value.rs | 0 19 files changed, 184 insertions(+), 22 deletions(-) create mode 100644 examples/axum/Cargo.toml create mode 100644 examples/axum/src/main.rs create mode 100644 examples/pooled/Cargo.toml create mode 100644 examples/pooled/src/main.rs create mode 100644 examples/simple/Cargo.toml create mode 100644 examples/simple/src/main.rs create mode 100644 memcache/Cargo.toml rename {src => memcache/src}/client.rs (100%) rename {src => memcache/src}/connection.rs (100%) rename {src => memcache/src}/error.rs (100%) rename {src => memcache/src}/lib.rs (100%) rename {src => memcache/src}/protocol/ascii.rs (100%) rename {src => memcache/src}/protocol/binary.rs (100%) rename {src => memcache/src}/protocol/binary_packet.rs (100%) rename {src => memcache/src}/protocol/mod.rs (100%) rename {src => memcache/src}/stream/mod.rs (100%) rename {src => memcache/src}/stream/udp_stream.rs (100%) rename {src => memcache/src}/value.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index bd7d8a4..b0114fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,22 +1,8 @@ -[package] -name = "memcache" -version = "0.17.0" -authors = ["An Long "] -repository = "https://github.com/aisk/rust-memcache" -readme = "README.md" -license = "MIT" -description = "memcached client for rust" -keywords = ["memcache", "memcached", "driver", "cache", "database"] -edition = "2018" - -[features] -default = ["tls"] -tls = ["openssl"] - -[dependencies] -byteorder = "1" -url = "2.1.1" -rand = "0.8" -enum_dispatch = "0.3" -openssl = { version = "^0.10", optional = true } -r2d2 = "0.8.8" +[workspace] +members = [ + "examples/*", + "memcache" +] +default-members = [ + "memcache" +] diff --git a/examples/axum/Cargo.toml b/examples/axum/Cargo.toml new file mode 100644 index 0000000..3cde5ed --- /dev/null +++ b/examples/axum/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "example-axum" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +axum = { version = "0.6.19", features = ["headers"] } +memcache = { path = "../../memcache" } +tokio = { version = "1.15.0", features = ["full"] } +r2d2 = "0.8.10" diff --git a/examples/axum/src/main.rs b/examples/axum/src/main.rs new file mode 100644 index 0000000..d730562 --- /dev/null +++ b/examples/axum/src/main.rs @@ -0,0 +1,72 @@ +//! An example of how to setup Axum with memcached, using a shared +//! connection pool that is accessible to all requests through Axum's +//! state. +//! Run the example with: +//! +//! ```not_rust +//! cargo run -p example-axum +//! ``` + + +use std::sync::Arc; + +use memcache::{self, Url, Pool}; +use axum::{Router, routing::get, extract::{State, Path}, Server}; + +#[derive(Clone)] +struct AppState { + memcache: Arc, +} + +async fn get_root( + State(app_state): State, + Path(key): Path, +) -> String { + let memcache = app_state.memcache.clone(); + + match memcache.get(&key) { + Ok(Some(value)) => value, + Ok(None) => "Not found".to_string(), + Err(err) => format!("ERROR: {}", err), + } +} + +async fn post_root( + State(app_state): State, + Path(key): Path, + body: String +) -> String { + let memcache = app_state.memcache.clone(); + + match memcache.set(&key, body, 300) { + Ok(_) => "OK".to_string(), + Err(e) => format!("ERROR: {}", e), + } +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + println!("This example requires a memcached server running on 127.0.0.1:11211"); + + let memcached_url = "memcache://127.0.0.1:11211"; + let memcached_url = Url::parse(memcached_url)?; + + let pool = Pool::builder().max_size(10).build(memcache::ConnectionManager::new(memcached_url))?; + let client = memcache::Client::with_pool(pool)?; + + let app = Router::new() + .route("/kv/:key", get(get_root).post(post_root)) + .with_state(AppState { + memcache: Arc::new(client) + }); + + println!("Starting server on http://0.0.0.0:3000"); + println!("Set keys using [POST] http://0.0.0.0:3000/kv/ with a body for the value"); + println!("Get keys using [GET] http://0.0.0.0:3000/kv/"); + + Server::bind(&"0.0.0.0:3000".parse().unwrap()) + .serve(app.into_make_service()) + .await + .unwrap(); + Ok(()) +} diff --git a/examples/pooled/Cargo.toml b/examples/pooled/Cargo.toml new file mode 100644 index 0000000..f07fd63 --- /dev/null +++ b/examples/pooled/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "example-pooled" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +memcache = { path = "../../memcache" } diff --git a/examples/pooled/src/main.rs b/examples/pooled/src/main.rs new file mode 100644 index 0000000..76eb52f --- /dev/null +++ b/examples/pooled/src/main.rs @@ -0,0 +1,27 @@ +//! An example of how to setup a connection pool for memcached +//! connections. +//! Run the example with: +//! +//! ```not_rust +//! cargo run -p example-pooled +//! ``` + +use memcache::{Client, Pool, ConnectionManager, Url}; + +fn main() -> Result<(), Box> { + let localhost = Url::parse("memcache://localhost:11211")?; + let pool = Pool::builder().max_size(10).build(ConnectionManager::new(localhost))?; + let client = Client::with_pool(pool)?; + + // sets a key to a value, with a 10 second expiration time + client.set("test", "value", 10)?; + + // gets the value of a key + if let Some(value) = client.get::("test")? { + println!("test: {}", value); + } + + // deletes a key + client.delete("test")?; + Ok(()) +} diff --git a/examples/simple/Cargo.toml b/examples/simple/Cargo.toml new file mode 100644 index 0000000..8663f59 --- /dev/null +++ b/examples/simple/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "example-simple" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +memcache = { path = "../../memcache" } diff --git a/examples/simple/src/main.rs b/examples/simple/src/main.rs new file mode 100644 index 0000000..84edc18 --- /dev/null +++ b/examples/simple/src/main.rs @@ -0,0 +1,28 @@ +//! A simple example of using the memcache crate, which +//! connects to a memcached server and sets, gets, and +//! deletes a key. +//! Run the example with: +//! +//! ```not_rust +//! cargo run -p example-simple +//! ``` + +use memcache::connect; + +pub fn main() -> Result<(), Box> { + let localhost = "memcache://localhost:11211"; + let client = connect(localhost).expect("Couldn't connect to memcached"); + + // sets a key to a value, with a 10 second expiration time + client.set("test", "value", 10)?; + + // gets the value of a key + if let Some(value) = client.get::("test")? { + println!("test: {}", value); + } + + // deletes a key + client.delete("test")?; + + Ok(()) +} diff --git a/memcache/Cargo.toml b/memcache/Cargo.toml new file mode 100644 index 0000000..f1a8707 --- /dev/null +++ b/memcache/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "memcache" +version = "0.17.0" +authors = ["An Long "] +repository = "https://github.com/aisk/rust-memcache" +readme = "README.md" +license = "MIT" +description = "memcached client for rust" +keywords = ["memcache", "memcached", "driver", "cache", "database"] +edition = "2021" + +[features] +default = ["tls"] +tls = ["openssl"] + +[dependencies] +byteorder = "1" +url = "2.1.1" +rand = "0.8" +enum_dispatch = "0.3" +openssl = { version = "^0.10", optional = true } +r2d2 = "0.8.8" diff --git a/src/client.rs b/memcache/src/client.rs similarity index 100% rename from src/client.rs rename to memcache/src/client.rs diff --git a/src/connection.rs b/memcache/src/connection.rs similarity index 100% rename from src/connection.rs rename to memcache/src/connection.rs diff --git a/src/error.rs b/memcache/src/error.rs similarity index 100% rename from src/error.rs rename to memcache/src/error.rs diff --git a/src/lib.rs b/memcache/src/lib.rs similarity index 100% rename from src/lib.rs rename to memcache/src/lib.rs diff --git a/src/protocol/ascii.rs b/memcache/src/protocol/ascii.rs similarity index 100% rename from src/protocol/ascii.rs rename to memcache/src/protocol/ascii.rs diff --git a/src/protocol/binary.rs b/memcache/src/protocol/binary.rs similarity index 100% rename from src/protocol/binary.rs rename to memcache/src/protocol/binary.rs diff --git a/src/protocol/binary_packet.rs b/memcache/src/protocol/binary_packet.rs similarity index 100% rename from src/protocol/binary_packet.rs rename to memcache/src/protocol/binary_packet.rs diff --git a/src/protocol/mod.rs b/memcache/src/protocol/mod.rs similarity index 100% rename from src/protocol/mod.rs rename to memcache/src/protocol/mod.rs diff --git a/src/stream/mod.rs b/memcache/src/stream/mod.rs similarity index 100% rename from src/stream/mod.rs rename to memcache/src/stream/mod.rs diff --git a/src/stream/udp_stream.rs b/memcache/src/stream/udp_stream.rs similarity index 100% rename from src/stream/udp_stream.rs rename to memcache/src/stream/udp_stream.rs diff --git a/src/value.rs b/memcache/src/value.rs similarity index 100% rename from src/value.rs rename to memcache/src/value.rs From 5cdaf78515c8b9041a85c58d4999e5b1e3bb19db Mon Sep 17 00:00:00 2001 From: Joe Date: Sat, 29 Jul 2023 19:55:29 -0400 Subject: [PATCH 2/4] :art: Run cargo fmt --- examples/axum/src/main.rs | 26 ++++++++++++-------------- examples/pooled/src/main.rs | 4 ++-- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/examples/axum/src/main.rs b/examples/axum/src/main.rs index d730562..6faf058 100644 --- a/examples/axum/src/main.rs +++ b/examples/axum/src/main.rs @@ -7,21 +7,21 @@ //! cargo run -p example-axum //! ``` - use std::sync::Arc; -use memcache::{self, Url, Pool}; -use axum::{Router, routing::get, extract::{State, Path}, Server}; +use axum::{ + extract::{Path, State}, + routing::get, + Router, Server, +}; +use memcache::{self, Pool, Url}; #[derive(Clone)] struct AppState { memcache: Arc, } -async fn get_root( - State(app_state): State, - Path(key): Path, -) -> String { +async fn get_root(State(app_state): State, Path(key): Path) -> String { let memcache = app_state.memcache.clone(); match memcache.get(&key) { @@ -31,11 +31,7 @@ async fn get_root( } } -async fn post_root( - State(app_state): State, - Path(key): Path, - body: String -) -> String { +async fn post_root(State(app_state): State, Path(key): Path, body: String) -> String { let memcache = app_state.memcache.clone(); match memcache.set(&key, body, 300) { @@ -51,13 +47,15 @@ async fn main() -> Result<(), Box> { let memcached_url = "memcache://127.0.0.1:11211"; let memcached_url = Url::parse(memcached_url)?; - let pool = Pool::builder().max_size(10).build(memcache::ConnectionManager::new(memcached_url))?; + let pool = Pool::builder() + .max_size(10) + .build(memcache::ConnectionManager::new(memcached_url))?; let client = memcache::Client::with_pool(pool)?; let app = Router::new() .route("/kv/:key", get(get_root).post(post_root)) .with_state(AppState { - memcache: Arc::new(client) + memcache: Arc::new(client), }); println!("Starting server on http://0.0.0.0:3000"); diff --git a/examples/pooled/src/main.rs b/examples/pooled/src/main.rs index 76eb52f..89ce9a1 100644 --- a/examples/pooled/src/main.rs +++ b/examples/pooled/src/main.rs @@ -6,7 +6,7 @@ //! cargo run -p example-pooled //! ``` -use memcache::{Client, Pool, ConnectionManager, Url}; +use memcache::{Client, ConnectionManager, Pool, Url}; fn main() -> Result<(), Box> { let localhost = Url::parse("memcache://localhost:11211")?; @@ -23,5 +23,5 @@ fn main() -> Result<(), Box> { // deletes a key client.delete("test")?; - Ok(()) + Ok(()) } From da98080b452e32fbb746b7f29737078d5265df58 Mon Sep 17 00:00:00 2001 From: Joe Date: Sat, 29 Jul 2023 19:59:00 -0400 Subject: [PATCH 3/4] :recycle: Remove un-needed clones --- examples/axum/src/main.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/examples/axum/src/main.rs b/examples/axum/src/main.rs index 6faf058..d16d873 100644 --- a/examples/axum/src/main.rs +++ b/examples/axum/src/main.rs @@ -22,9 +22,7 @@ struct AppState { } async fn get_root(State(app_state): State, Path(key): Path) -> String { - let memcache = app_state.memcache.clone(); - - match memcache.get(&key) { + match app_state.memcache.get(&key) { Ok(Some(value)) => value, Ok(None) => "Not found".to_string(), Err(err) => format!("ERROR: {}", err), @@ -32,9 +30,7 @@ async fn get_root(State(app_state): State, Path(key): Path) -> } async fn post_root(State(app_state): State, Path(key): Path, body: String) -> String { - let memcache = app_state.memcache.clone(); - - match memcache.set(&key, body, 300) { + match app_state.memcache.set(&key, body, 300) { Ok(_) => "OK".to_string(), Err(e) => format!("ERROR: {}", e), } From 82492233db4abd11bc1ad05719ca8ac4f2a4679a Mon Sep 17 00:00:00 2001 From: Joe Date: Sun, 30 Jul 2023 13:01:24 -0400 Subject: [PATCH 4/4] :recycle: Remove unused dependency --- examples/axum/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/axum/Cargo.toml b/examples/axum/Cargo.toml index 3cde5ed..fa3efab 100644 --- a/examples/axum/Cargo.toml +++ b/examples/axum/Cargo.toml @@ -8,4 +8,3 @@ publish = false axum = { version = "0.6.19", features = ["headers"] } memcache = { path = "../../memcache" } tokio = { version = "1.15.0", features = ["full"] } -r2d2 = "0.8.10"