Petite recette pour réaliser un micro-service codé en Rust de zéro au déploiement. Afin de découvrir Rust au travers de son écosysteme, ainsi que l'intégration dans une "infrastructure micro-services".
Car un langage n'est pas qu'une syntaxe et un compilateur, mais aussi ce qu'il y a autour: outils, documentation, communauté, ...
struct V2 {
x: f64,
y: f64,
}
pub struct V2 {
pub x: f64,
pub y: f64,
}
fn main(){
let v = V2{x: 10.0, y: 11_f64};
println!("display v: {}", v);
}
impl V2 {
fn to_string(&self) -> String {
format!("V2 {{ x: {}, y: {} }}", self.x, self.y)
}
}
//...
println!("display v: {}", v.to_string());
error[E0277]: `V2` doesn't implement `std::fmt::Display`
--> src/main.rs:8:31
|
8 | println!("display v: {}", v);
| ^ `V2` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
|
= help: the trait `std::fmt::Display` is not implemented for `V2`
= note: required by `std::fmt::Display::fmt`
use std::fmt;
impl fmt::Display for V2 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "V2 {{ x: {}, y: {} }}", self.x, self.y)
}
}
//...
println!("display v {}", v);
#[derive(Debug, Clone)]
pub struct V2 {
pub x: f64,
pub y: f64,
}
println!("display v {}", v);
println!("debug v {:?}", v);
println!("debug pretty v {:#?}", v);
display v V2 { x: 10, y: 11 }
debug v V2 { x: 10.0, y: 11.0 }
debug pretty v V2 {
x: 10.0,
y: 11.0
}
fn twice(x: T) -> U
where
T: Add<Output=U>,
T: Copy,
{
x + x
}
fn main() {
let one = V2 { x: 1, y: 1 };
println!("{:?}", twice(one));
}
pub trait ToString {
fn to_string(&self) -> String;
}
pub trait Add {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
pub trait To42 {
fn to_42(&self) -> i32 {
42
}
}
impl To42 for V2{}
println!("v.to_42 {}", v.to_42());
impl Add for V2 {
type Output = V2;
fn add(self, rhs: V2) -> V2 {
V2 {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
}
impl AddAssign for V2 {
fn add_assign(&mut self, rhs: V2) {
self.x += rhs.x;
self.y += rhs.y;
}
}
enum Colors {
Blue,
Yellow,
Green,
}
enum Command {
Help,
Kill(i32),
Run {
path: String,
options: Vec<String>,
}
}
macro_rules! print_twice {
( $x:expr ) => {
{
println!("{:?}", twice($x));
}
};
}
print_twice!(V2 { x: 1, y: 1 });
fn main() {
let one = V2 { x: 1, y: 1 };
let twice = |x| x + x;
println!("{:?}", twice(one));
}
fn f(x: V2) {...}
fn f(x: &V2) {...}
fn f(x: &mut V2) {...}
curl https://sh.rustup.rs -sSf | sh
rustup default stable
rustup show
rustup update
rustup component add rustfmt-preview
rustup component add rls-preview rust-src rust-analysis
rustup doc
rustc --version
rustc --help
rustfmt --help
rustdoc --help
cargo --help
https://doc.rust-lang.org/cargo/reference/manifest.html
[package]
name = "hello"
version = "0.1.0"
authors = ["name <my@email.com>"]
[dependencies]
# Generated by Cargo
# will have compiled files and executables
/target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
https://github.com/github/gitignore/blob/master/Rust.gitignore
.
├── Cargo.lock
├── Cargo.toml
├── build.rs
├── benches
│ └── large-input.rs
├── examples
│ └── simple.rs
├── src
│ ├── bin
│ │ └── another_executable.rs
│ ├── lib.rs
│ └── main.rs
└── tests
└── some-integration-tests.rs
cargo doc
open target/doc/hello/index.html
/// This comment documents the `foo` function.
///
/// You can use the `rustdoc` tool via `cargo doc` to generate
/// HTML documentation from these comments!
fn foo() {
// ...
}
~/.cargo/bin
cargo install ripgrep https
cargo install cargo-watch cargo-make mdbook
cargo install --list
A collection of lints to catch common mistakes and improve your Rust code.
rustup install nightly
cargo +nightly install --force clippy
cargo +nightly clippy
via GDB / LLDB
Debugging Rust programs with lldb on MacOS | Bryce Fisher-Fleig
cargo +nightly bench
cargo bench
Running target/release/deps/bench1-0a8dde0ccacc35ee
fib 20 time: [25.800 us 26.114 us 26.453 us]
Found 3 outliers among 100 measurements (3.00%)
1 (1.00%) high mild
2 (2.00%) high severe
Running target/release/deps/bench1-0a8dde0ccacc35ee
fib 20 time: [25.662 us 25.993 us 26.302 us]
change: [-5.4472% -3.3608% -1.1502%] (p = 0.00 < 0.05)
Performance has improved.
Found 5 outliers among 100 measurements (5.00%)
5 (5.00%) high mild
git clone https://github.com/davidB/labs_cooking_microservices_with_rust rust-cook
cd rust-cook/reviews
# .travis.yml
language: rust
rust:
- stable
- beta
- nightly
matrix:
allow_failures:
- rust: nightly
fast_finish: true
include:
- rust: stable
env: RUSTFMT
install:
- rustup component add rustfmt-preview
script:
- cargo fmt -- --write-mode=diff
cache: cargo
see https://github.com/michiel/docker-rust-microservice
rustup target add x86_64-unknown-linux-musl
cargo build --target x86_64-unknown-linux-musl --release
# from https://blog.sedrik.se/posts/my-docker-setup-for-rust/
FROM ekidd/rust-musl-builder as builder
WORKDIR /home/rust/
# Avoid having to install/build all dependencies by copying
# the Cargo files and making a dummy src/main.rs
COPY Cargo.toml .
COPY Cargo.lock .
RUN echo "fn main() {}" > src/bin.rs
RUN echo "" > src/lib.rs
# RUN cargo test
RUN cargo build --release
# We need to touch our real main.rs file or else docker will use
# the cached one.
COPY . .
RUN sudo touch src/bin.rs src/lib.rs
RUN sudo chown -R rust /home/rust
# RUN cargo test
RUN cargo build --release
# Size optimization & rename to main
RUN strip target/x86_64-unknown-linux-musl/release/reviews -o target/x86_64-unknown-linux-musl/release/main
# Start building the final image
FROM scratch
WORKDIR /home/rust/
COPY --from=builder /home/rust/target/x86_64-unknown-linux-musl/release/main .
ENTRYPOINT ["./main"]
target
Dockerfile
.dockerignore
.git
.gitignore
README*
docker build -t reviews:v10 .
docker run -p 9080:9080 -e "RUST_LOG=info" --rm --name reviews reviews:v10
docker stop reviews
curl localhost:9080/ratings/0
{
"id" : 0,
"ratings" : {
"Reviewer2" : 4,
"Reviewer1" : 5
}
}
curl localhost:9080/reviews/0
{
"id" : 0,
"reviews" : [
{
"text" : "An extremely entertaining play by Shakespeare.",
"rating" : { "color" : "blue", "stars" : 5 },
"reviewer" : "Reviewer1"
},
...
]
}
cargo install diesel_cli
DATABASE_URL=test.sqlite diesel setup
diesel migration generate reviews
DATABASE_URL=test.sqlite diesel migration run
DATABASE_URL=test.sqlite diesel print-schema > src/schema.rs
curl http://127.0.0.1:9080/graphql -d '{"query":"{products{id,reviews{text,rating{stars}}}}"}'
{
"data" : {
"products" : [
{
"reviews" : [
{
"text" : "An extremely entertaining play by Shakespeare.",
"rating" : { "stars" : 5 }
},
...
]
}
]
}
}
#DevoxxFR