mirror of
https://github.com/actix/examples
synced 2025-06-28 18:00:37 +02:00
actix examples in actix release version
This commit is contained in:
1
diesel/.env
Normal file
1
diesel/.env
Normal file
@ -0,0 +1 @@
|
||||
DATABASE_URL=file:test.db
|
19
diesel/Cargo.toml
Normal file
19
diesel/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "diesel-example"
|
||||
version = "0.1.0"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
env_logger = "0.5"
|
||||
actix = "0.5"
|
||||
actix-web = "^0.5"
|
||||
|
||||
futures = "0.1"
|
||||
uuid = { version = "0.5", features = ["serde", "v4"] }
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
serde_derive = "1.0"
|
||||
|
||||
diesel = { version = "^1.1.0", features = ["sqlite", "r2d2"] }
|
||||
r2d2 = "0.8"
|
||||
dotenv = "0.10"
|
43
diesel/README.md
Normal file
43
diesel/README.md
Normal file
@ -0,0 +1,43 @@
|
||||
# diesel
|
||||
|
||||
Diesel's `Getting Started` guide using SQLite for Actix web
|
||||
|
||||
## Usage
|
||||
|
||||
### init database sqlite
|
||||
|
||||
```bash
|
||||
cargo install diesel_cli --no-default-features --features sqlite
|
||||
cd actix-web/examples/diesel
|
||||
echo "DATABASE_URL=file:test.db" > .env
|
||||
diesel migration run
|
||||
```
|
||||
|
||||
### server
|
||||
|
||||
```bash
|
||||
# if ubuntu : sudo apt-get install libsqlite3-dev
|
||||
# if fedora : sudo dnf install libsqlite3x-devel
|
||||
cd actix-web/examples/diesel
|
||||
cargo run (or ``cargo watch -x run``)
|
||||
# Started http server: 127.0.0.1:8080
|
||||
```
|
||||
|
||||
### web client
|
||||
|
||||
[http://127.0.0.1:8080/NAME](http://127.0.0.1:8080/NAME)
|
||||
|
||||
### sqlite client
|
||||
|
||||
```bash
|
||||
# if ubuntu : sudo apt-get install sqlite3
|
||||
# if fedora : sudo dnf install sqlite3x
|
||||
sqlite3 test.db
|
||||
sqlite> .tables
|
||||
sqlite> select * from users;
|
||||
```
|
||||
|
||||
|
||||
## Postgresql
|
||||
|
||||
You will also find another complete example of diesel+postgresql on [https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/frameworks/Rust/actix](https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/frameworks/Rust/actix)
|
1
diesel/migrations/20170124012402_create_users/down.sql
Normal file
1
diesel/migrations/20170124012402_create_users/down.sql
Normal file
@ -0,0 +1 @@
|
||||
DROP TABLE users
|
4
diesel/migrations/20170124012402_create_users/up.sql
Normal file
4
diesel/migrations/20170124012402_create_users/up.sql
Normal file
@ -0,0 +1,4 @@
|
||||
CREATE TABLE users (
|
||||
id VARCHAR NOT NULL PRIMARY KEY,
|
||||
name VARCHAR NOT NULL
|
||||
)
|
55
diesel/src/db.rs
Normal file
55
diesel/src/db.rs
Normal file
@ -0,0 +1,55 @@
|
||||
//! Db executor actor
|
||||
use uuid;
|
||||
use diesel;
|
||||
use actix_web::*;
|
||||
use actix::prelude::*;
|
||||
use diesel::prelude::*;
|
||||
use diesel::r2d2::{Pool, ConnectionManager};
|
||||
|
||||
use models;
|
||||
use schema;
|
||||
|
||||
/// This is db executor actor. We are going to run 3 of them in parallel.
|
||||
pub struct DbExecutor(pub Pool<ConnectionManager<SqliteConnection>>);
|
||||
|
||||
/// This is only message that this actor can handle, but it is easy to extend number of
|
||||
/// messages.
|
||||
pub struct CreateUser {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl Message for CreateUser {
|
||||
type Result = Result<models::User, Error>;
|
||||
}
|
||||
|
||||
impl Actor for DbExecutor {
|
||||
type Context = SyncContext<Self>;
|
||||
}
|
||||
|
||||
impl Handler<CreateUser> for DbExecutor {
|
||||
type Result = Result<models::User, Error>;
|
||||
|
||||
fn handle(&mut self, msg: CreateUser, _: &mut Self::Context) -> Self::Result {
|
||||
use self::schema::users::dsl::*;
|
||||
|
||||
let uuid = format!("{}", uuid::Uuid::new_v4());
|
||||
let new_user = models::NewUser {
|
||||
id: &uuid,
|
||||
name: &msg.name,
|
||||
};
|
||||
|
||||
let conn: &SqliteConnection = &self.0.get().unwrap();
|
||||
|
||||
diesel::insert_into(users)
|
||||
.values(&new_user)
|
||||
.execute(conn)
|
||||
.expect("Error inserting person");
|
||||
|
||||
let mut items = users
|
||||
.filter(id.eq(&uuid))
|
||||
.load::<models::User>(conn)
|
||||
.expect("Error loading person");
|
||||
|
||||
Ok(items.pop().unwrap())
|
||||
}
|
||||
}
|
78
diesel/src/main.rs
Normal file
78
diesel/src/main.rs
Normal file
@ -0,0 +1,78 @@
|
||||
//! Actix web diesel example
|
||||
//!
|
||||
//! Diesel does not support tokio, so we have to run it in separate threads.
|
||||
//! Actix supports sync actors by default, so we going to create sync actor that use diesel.
|
||||
//! Technically sync actors are worker style actors, multiple of them
|
||||
//! can run in parallel and process messages from same queue.
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
#[macro_use]
|
||||
extern crate diesel;
|
||||
extern crate r2d2;
|
||||
extern crate uuid;
|
||||
extern crate futures;
|
||||
extern crate actix;
|
||||
extern crate actix_web;
|
||||
extern crate env_logger;
|
||||
|
||||
use actix::prelude::*;
|
||||
use actix_web::{http, server, middleware,
|
||||
App, Path, State, HttpResponse, AsyncResponder, FutureResponse};
|
||||
|
||||
use diesel::prelude::*;
|
||||
use diesel::r2d2::{ Pool, ConnectionManager };
|
||||
use futures::future::Future;
|
||||
|
||||
mod db;
|
||||
mod models;
|
||||
mod schema;
|
||||
|
||||
use db::{CreateUser, DbExecutor};
|
||||
|
||||
|
||||
/// State with DbExecutor address
|
||||
struct AppState {
|
||||
db: Addr<Syn, DbExecutor>,
|
||||
}
|
||||
|
||||
/// Async request handler
|
||||
fn index(name: Path<String>, state: State<AppState>) -> FutureResponse<HttpResponse> {
|
||||
// send async `CreateUser` message to a `DbExecutor`
|
||||
state.db.send(CreateUser{name: name.into_inner()})
|
||||
.from_err()
|
||||
.and_then(|res| {
|
||||
match res {
|
||||
Ok(user) => Ok(HttpResponse::Ok().json(user)),
|
||||
Err(_) => Ok(HttpResponse::InternalServerError().into())
|
||||
}
|
||||
})
|
||||
.responder()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
::std::env::set_var("RUST_LOG", "actix_web=info");
|
||||
env_logger::init();
|
||||
let sys = actix::System::new("diesel-example");
|
||||
|
||||
// Start 3 db executor actors
|
||||
let manager = ConnectionManager::<SqliteConnection>::new("test.db");
|
||||
let pool = r2d2::Pool::builder().build(manager).expect("Failed to create pool.");
|
||||
|
||||
let addr = SyncArbiter::start(3, move || {
|
||||
DbExecutor(pool.clone())
|
||||
});
|
||||
|
||||
// Start http server
|
||||
server::new(move || {
|
||||
App::with_state(AppState{db: addr.clone()})
|
||||
// enable logger
|
||||
.middleware(middleware::Logger::default())
|
||||
.resource("/{name}", |r| r.method(http::Method::GET).with2(index))})
|
||||
.bind("127.0.0.1:8080").unwrap()
|
||||
.start();
|
||||
|
||||
println!("Started http server: 127.0.0.1:8080");
|
||||
let _ = sys.run();
|
||||
}
|
14
diesel/src/models.rs
Normal file
14
diesel/src/models.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use super::schema::users;
|
||||
|
||||
#[derive(Serialize, Queryable)]
|
||||
pub struct User {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "users"]
|
||||
pub struct NewUser<'a> {
|
||||
pub id: &'a str,
|
||||
pub name: &'a str,
|
||||
}
|
6
diesel/src/schema.rs
Normal file
6
diesel/src/schema.rs
Normal file
@ -0,0 +1,6 @@
|
||||
table! {
|
||||
users (id) {
|
||||
id -> Text,
|
||||
name -> Text,
|
||||
}
|
||||
}
|
BIN
diesel/test.db
Normal file
BIN
diesel/test.db
Normal file
Binary file not shown.
Reference in New Issue
Block a user