<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maxime David</title>
    <description>The latest articles on DEV Community by Maxime David (@maxday).</description>
    <link>https://dev.to/maxday</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F976571%2Fb6a30eed-0453-4c82-82e3-ea7de3a2fdd5.jpeg</url>
      <title>DEV Community: Maxime David</title>
      <link>https://dev.to/maxday</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maxday"/>
    <language>en</language>
    <item>
      <title>Rust on AWS App Runner - Part2</title>
      <dc:creator>Maxime David</dc:creator>
      <pubDate>Tue, 05 Sep 2023 14:01:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/rust-on-aws-app-runner-part2-17d2</link>
      <guid>https://dev.to/aws-builders/rust-on-aws-app-runner-part2-17d2</guid>
      <description>&lt;p&gt;Hey hey hey 🍕!&lt;/p&gt;

&lt;p&gt;This is the second part of this series, make sure you've already read &lt;a href="https://dev.to/aws-builders/rust-on-aws-app-runner-part1-4hpp"&gt;the first part&lt;/a&gt; :)&lt;/p&gt;

&lt;p&gt;In the first part, we saw how to create a basic Rust API with a &lt;code&gt;GET /pizza&lt;/code&gt; endpoint to retrieve the list of pizza.&lt;/p&gt;

&lt;p&gt;In this part, let's see how to containerize our app!&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's create our container
&lt;/h2&gt;

&lt;p&gt;Since AWS App Runner is a fully managed container application service, we definitely need a container!&lt;/p&gt;

&lt;p&gt;In this section, we will see how to build that container thanks to &lt;code&gt;Docker&lt;/code&gt; using a &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;Dockerfile&lt;/code&gt; is a text file that contains all the commands needed to build our container, it's often compared to a recipe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rust as the base image
&lt;/h2&gt;

&lt;p&gt;Let's start with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; rust:slim-bullseye&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./ /app&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;cargo build &lt;span class="nt"&gt;--release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line describes the base image that we want to use, here the official &lt;code&gt;rust&lt;/code&gt; one. &lt;/p&gt;

&lt;p&gt;This is really convenient since we don't have to install &lt;code&gt;rust&lt;/code&gt; or &lt;code&gt;cargo&lt;/code&gt;: both are already installed in this base image.&lt;/p&gt;

&lt;p&gt;Then we define the current working directory, here &lt;code&gt;/app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then we copy our sources (&lt;code&gt;src&lt;/code&gt; + &lt;code&gt;Cargo.toml&lt;/code&gt; + &lt;code&gt;Cargo.lock&lt;/code&gt;) into the container.&lt;/p&gt;

&lt;p&gt;Finally we build our API directly inside the container, in release mode, to be sure to have a production-ready binary.&lt;/p&gt;

&lt;p&gt;Great, we now have our binary ready in our image!&lt;/p&gt;

&lt;p&gt;But wait, we also have &lt;code&gt;rust&lt;/code&gt;, &lt;code&gt;cargo&lt;/code&gt; and a bunch of useless tools at runtime. &lt;/p&gt;

&lt;p&gt;It was convenient to use the official &lt;code&gt;rust&lt;/code&gt; image &lt;strong&gt;to build&lt;/strong&gt;, but we don't need it anymore for the &lt;strong&gt;runtime&lt;/strong&gt;. Fortunately, Docker supports &lt;strong&gt;multi stage builds&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-stage builds
&lt;/h2&gt;

&lt;p&gt;We can specify a base image to build and another one to run! That's exactly what we want!&lt;/p&gt;

&lt;p&gt;The idea here is to have the smallest possible image so the cold start would be extremely fast. That's why we are going to use a &lt;code&gt;distroless&lt;/code&gt; base image.&lt;/p&gt;

&lt;p&gt;Those images are built by Google and contain almost nothing: no &lt;code&gt;bash&lt;/code&gt;, no &lt;code&gt;ssh&lt;/code&gt;, no utility tools which makes the image extremely small.&lt;/p&gt;

&lt;p&gt;Let's modify our Dockerfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;rust:slim-bullseye&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;BUILD&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./ /app&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;cargo build &lt;span class="nt"&gt;--release&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; gcr.io/distroless/cc-debian10&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=BUILD /app/target/release/app-runner-rust / &lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["./app-runner-rust"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we name our first image &lt;code&gt;BUILD&lt;/code&gt; so we can reference that later. Then from the distroless image, we copy our binary from the &lt;code&gt;BUILD&lt;/code&gt; image! Super convenient! I love Docker :D&lt;/p&gt;

&lt;p&gt;Our runtime image is just the &lt;code&gt;distroless base image&lt;/code&gt; + &lt;code&gt;rust binary&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let's finally build it with &lt;code&gt;docker build . -t maxday/app-runner&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let's check for our image size: &lt;code&gt;docker images | grep maxday/app-runner&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images | &lt;span class="nb"&gt;grep &lt;/span&gt;maxday/app-runner
maxday/app-runner                                          latest          e278afc78403   3 minutes ago    20.1MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;20.1MB!!! 🤯 Extremely small!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Woot woot! We now have a ready to deploy container!&lt;/p&gt;

&lt;h2&gt;
  
  
  Local test
&lt;/h2&gt;

&lt;p&gt;Before deploying, let's make sure everything looks fine by running it locally and calling our &lt;code&gt;GET /pizza&lt;/code&gt; endpoint.&lt;/p&gt;

&lt;p&gt;You can run your newly built docker image with:&lt;br&gt;&lt;br&gt;
&lt;code&gt;docker run -d -p 8080:8080 maxday/app-runner&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-d&lt;/code&gt; means &lt;code&gt;detached&lt;/code&gt; so the container runs in the background&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-p 8080:8080&lt;/code&gt; means that you're bridging the host port 8080 to the container port 8080.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can check that your container is up and running with:&lt;br&gt;&lt;br&gt;
&lt;code&gt;docker ps&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps
CONTAINER ID   IMAGE               COMMAND               CREATED          STATUS          PORTS                    NAMES
e5d8978ee6ee   maxday/app-runner   &lt;span class="s2"&gt;"./app-runner-rust"&lt;/span&gt;   53 seconds ago   Up 53 seconds   0.0.0.0:8080-&amp;gt;8080/tcp   pedantic_kare
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can curl the endpoint:&lt;br&gt;&lt;br&gt;
&lt;code&gt;curl http://localhost:8080/pizza&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl localhost:8080/pizza
&lt;span class="o"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;:&lt;span class="s2"&gt;"Margherita"&lt;/span&gt;,&lt;span class="s2"&gt;"toppings"&lt;/span&gt;:[&lt;span class="s2"&gt;"tomato"&lt;/span&gt;,&lt;span class="s2"&gt;"fior di latte"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,&lt;span class="s2"&gt;"price"&lt;/span&gt;:10&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;:&lt;span class="s2"&gt;"Veggie"&lt;/span&gt;,&lt;span class="s2"&gt;"toppings"&lt;/span&gt;:[&lt;span class="s2"&gt;"green peppers"&lt;/span&gt;,&lt;span class="s2"&gt;"onion"&lt;/span&gt;,&lt;span class="s2"&gt;"mushrooms"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,&lt;span class="s2"&gt;"price"&lt;/span&gt;:12&lt;span class="o"&gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Awesome! 🎉&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our container is now ready to be used by AWS App Runner.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;See you next week for the final episode of this series to deploy it!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Like this content? Consider following me for more!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A question? Feel free to use the comment section ⬇️&lt;/p&gt;

&lt;p&gt;You can find me on &lt;a href="https://www.linkedin.com/in/maxday/"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://www.youtube.com/@maxday_coding"&gt;YouTube&lt;/a&gt; and &lt;a href="https://twitter.com/_maxday"&gt;Twitter&lt;/a&gt;!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Rust on AWS App Runner - Part1</title>
      <dc:creator>Maxime David</dc:creator>
      <pubDate>Mon, 21 Aug 2023 14:36:51 +0000</pubDate>
      <link>https://dev.to/aws-builders/rust-on-aws-app-runner-part1-4hpp</link>
      <guid>https://dev.to/aws-builders/rust-on-aws-app-runner-part1-4hpp</guid>
      <description>&lt;p&gt;Hey hey hey 🍕!&lt;/p&gt;

&lt;p&gt;Over the past few months, I've been advocating for Rust on AWS Lambda a lot!&lt;/p&gt;

&lt;p&gt;Here is a quick recap in case you missed it!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=Idys2BAmqIU"&gt;Live coding&lt;/a&gt;  a AWS Lambda in Rust with TDD&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/maxday/lambda-perf"&gt;Lambda-Perf tool&lt;/a&gt; where Rust is killing the cold start game&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the way, we're almost at 256 ⭐️ which is 🤯 for a side project! I'm sure we can do it!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/live/5ptACic_FJQ?feature=share&amp;amp;t=255"&gt;Rust Linz Meetup&lt;/a&gt; where I gave a talk about Serverless + Rust&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But as you may know, serverless is NOT only about AWS Lambda. If you need compute, &lt;strong&gt;AWS App Runner&lt;/strong&gt; might be a great fit!&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS App Runner
&lt;/h2&gt;

&lt;p&gt;If you see Lambda as &lt;code&gt;functions as a service&lt;/code&gt; you can see &lt;br&gt;
App Runner as &lt;code&gt;containers as a service&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It means that you can focus on &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;building your app&lt;/li&gt;
&lt;li&gt;containerized it (ie: Docker image)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and AWS will scale it for you, including to zero.&lt;/p&gt;

&lt;p&gt;It also means that you will experience a cold start when no containers are up or when you need to handle more traffic.&lt;/p&gt;

&lt;p&gt;Similarly to AWS Lambda, Rust would be a great candidate for AWS App Runner if we manage to build a tiny container which starts extremely fast! &lt;/p&gt;

&lt;p&gt;Annnnnnd that's what we are going to try to do in the series of blog post! &lt;/p&gt;
&lt;h2&gt;
  
  
  Ready? Let's gooooooo! 🎉
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Part1 - Create a simple Rust API - this blog post&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Part2 - Containerize it! (and make it small)&lt;/li&gt;
&lt;li&gt;Part3 - Deploy it to AWS App Runner&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Part 1 - Create a simple Rust API
&lt;/h2&gt;

&lt;p&gt;In this part, we will focus on building a simple Rust service.&lt;/p&gt;

&lt;p&gt;Let's bootstrap the project using &lt;code&gt;cargo&lt;/code&gt; &lt;br&gt;
and run &lt;code&gt;cargo new pizza-rust --bin&lt;/code&gt; &lt;br&gt;
(oh yeah we're going to talk about 🍕)&lt;/p&gt;

&lt;p&gt;You should now have this file structure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AMbpPlqn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/43q551m441gvqrunlczx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AMbpPlqn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/43q551m441gvqrunlczx.png" alt="file structure" width="129" height="97"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Dependency
&lt;/h2&gt;

&lt;p&gt;There are multiple web framework crates in Rust but one the most commonly used is &lt;code&gt;actix_web&lt;/code&gt; so let's use this one!&lt;/p&gt;

&lt;p&gt;We're also going to need &lt;code&gt;serde&lt;/code&gt; to serialize and deserialize our pizzas.&lt;/p&gt;

&lt;p&gt;Finally, for testing purpose, we're going to use both &lt;code&gt;actix-rt&lt;/code&gt; abd &lt;code&gt;actix-test&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  main.rs
&lt;/h2&gt;

&lt;p&gt;Our main function will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[actix_web::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;HttpServer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;App&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pizza_service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;.bind&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;"0.0.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
    &lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;.await&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we've defined a very minimal web server, listening on 8080 and using the not-yet-defined &lt;code&gt;pizza_service&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Test first!
&lt;/h2&gt;

&lt;p&gt;Before going too far in the actual code, let's write our unit test first.&lt;br&gt;
When we hit /pizza, we want to receive a JSON array of pizza.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[cfg(test)]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;pizza_service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Pizza&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nd"&gt;#[actix_rt::test]&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// define a test pizza&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pizzas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="nn"&gt;Pizza&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pizzaTest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"topping0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"topping1"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;1234&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="c1"&gt;// define our in-memory db&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;app_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pizzas&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// define our test server&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;srv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;actix_test&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; 
            &lt;span class="nn"&gt;App&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.app_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app_data&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="nf"&gt;.service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pizza_service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// perform the request&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;srv&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/pizza"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="nf"&gt;.status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.is_success&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result_pizza&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="py"&gt;.json&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Pizza&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// assert the result&lt;/span&gt;
        &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result_pizza&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="py"&gt;.name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"pizzaTest"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result_pizza&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="py"&gt;.toppings&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"topping0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"topping1"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result_pizza&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="py"&gt;.price&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1234&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Back to main.rs
&lt;/h2&gt;

&lt;p&gt;Finally, let's modify our code to satisfy our test&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// let's create our pizza structure, making sure we can serialize and deserialize it!&lt;/span&gt;
&lt;span class="nd"&gt;#[derive(Serialize,&lt;/span&gt; &lt;span class="nd"&gt;Deserialize)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Pizza&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// simple Pizza constructor&lt;/span&gt;
&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Pizza&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Pizza&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Pizza&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;toppings&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// define our GET endpoint&lt;/span&gt;
&lt;span class="nd"&gt;#[get(&lt;/span&gt;&lt;span class="s"&gt;"/pizza"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;pizza_service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Pizza&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Responder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//just returning the JSON representation of our pizzas&lt;/span&gt;
    &lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// our fresh pizzas&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pizzas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nn"&gt;Pizza&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Margherita"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"tomato"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"fior di latte"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nn"&gt;Pizza&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Veggie"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"green peppers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"onion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"mushrooms"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// in-memory db&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;app_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pizzas&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nn"&gt;HttpServer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;App&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.app_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app_data&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pizza_service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;.bind&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;"0.0.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
    &lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;.await&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it!&lt;br&gt;
Our test is now passing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;test
   &lt;/span&gt;Compiling app-runner-rust v1.0.0 &lt;span class="o"&gt;(&lt;/span&gt;/rust&lt;span class="o"&gt;)&lt;/span&gt;
    Finished &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;unoptimized + debuginfo] target&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;1.27s
     Running unittests src/main.rs &lt;span class="o"&gt;(&lt;/span&gt;target/debug/deps/app_runner_rust-46a4a4cb852eb0c3&lt;span class="o"&gt;)&lt;/span&gt;

running 1 &lt;span class="nb"&gt;test
test &lt;/span&gt;tests::test ... ok

&lt;span class="nb"&gt;test &lt;/span&gt;result: ok. 1 passed&lt;span class="p"&gt;;&lt;/span&gt; 0 failed&lt;span class="p"&gt;;&lt;/span&gt; 0 ignored&lt;span class="p"&gt;;&lt;/span&gt; 0 measured&lt;span class="p"&gt;;&lt;/span&gt; 0 filtered out&lt;span class="p"&gt;;&lt;/span&gt; finished &lt;span class="k"&gt;in &lt;/span&gt;0.01s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final check
&lt;/h2&gt;

&lt;p&gt;Let's run our API with &lt;code&gt;cargo run&lt;/code&gt; &lt;br&gt;
and hit our endpoint &lt;code&gt;curl -i http://localhost:8080/pizza&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; http://localhost:8080/pizza
HTTP/1.1 200 OK
content-length: 150
content-type: application/json
&lt;span class="nb"&gt;date&lt;/span&gt;: Sun, 20 Aug 2023 00:26:27 GMT

&lt;span class="o"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;:&lt;span class="s2"&gt;"Margherita"&lt;/span&gt;,&lt;span class="s2"&gt;"toppings"&lt;/span&gt;:[&lt;span class="s2"&gt;"tomato"&lt;/span&gt;,&lt;span class="s2"&gt;"fior di latte"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,&lt;span class="s2"&gt;"price"&lt;/span&gt;:10&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;:&lt;span class="s2"&gt;"Veggie"&lt;/span&gt;,&lt;span class="s2"&gt;"toppings"&lt;/span&gt;:[&lt;span class="s2"&gt;"green peppers"&lt;/span&gt;,&lt;span class="s2"&gt;"onion"&lt;/span&gt;,&lt;span class="s2"&gt;"mushrooms"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,&lt;span class="s2"&gt;"price"&lt;/span&gt;:12&lt;span class="o"&gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voila! 🍕&lt;/p&gt;

&lt;p&gt;Our API is now ready to be containerized and that's the topic of the next blog post in this series! &lt;/p&gt;

&lt;p&gt;👋 Stay tunned for part 2 next week!&lt;/p&gt;

&lt;p&gt;You can find me on &lt;a href="https://www.linkedin.com/in/maxday/"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://www.youtube.com/@maxday_coding"&gt;YouTube&lt;/a&gt; and &lt;a href="https://twitter.com/_maxday"&gt;Twitter&lt;/a&gt;!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How I Discovered That the AWS Lambda Runtime Might Be Written in Go</title>
      <dc:creator>Maxime David</dc:creator>
      <pubDate>Wed, 02 Aug 2023 18:28:23 +0000</pubDate>
      <link>https://dev.to/aws-builders/how-i-discovered-that-the-aws-lambda-runtime-might-be-written-in-go-3i9l</link>
      <guid>https://dev.to/aws-builders/how-i-discovered-that-the-aws-lambda-runtime-might-be-written-in-go-3i9l</guid>
      <description>&lt;p&gt;Have you ever wondered how your Lambda function code is triggered?&lt;/p&gt;

&lt;p&gt;Each runtime has to conform to the &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html" rel="noopener noreferrer"&gt;AWS Lambda runtime API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In managed runtimes, you don't need to take care of that; that's the whole point of using a managed runtime! AWS takes care of that for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But how?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's hard to say because it's not clearly documented. However, while I was conducting some unrelated experiments, I made a very cool discovery! &lt;br&gt;
I think you'll find it interesting too!&lt;/p&gt;

&lt;p&gt;If you're working with Go and care about performance, you might want to look at some important metrics, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the number of allocations &lt;/li&gt;
&lt;li&gt;the time taken for each init() functions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To do so, you need to setup a environment variable:&lt;br&gt;&lt;br&gt;
&lt;code&gt;GODEBUG&lt;/code&gt; to &lt;code&gt;inittrace=1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And tada 🎉!&lt;/p&gt;

&lt;p&gt;In addition to information about the binary I wanted to test, I'm now able to see traces from another binary, which seems to be the one from AWS that conforms to the runtime API.&lt;/p&gt;

&lt;p&gt;Here is an example of the output 👀👀👀&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;init internal/bytealg @0.008 ms, 0 ms clock, 0 bytes, 0 allocs
...
init go.amzn.com/lambda/fatalerror @3.7 ms, 0.031 ms clock, 336 bytes, 2 allocs
...
init go.amzn.com/lambda/interop @6.5 ms, 0.023 ms clock, 1128 bytes, 32 allocs
init go.amzn.com/lambda/telemetry @6.5 ms, 0.067 ms clock, 16 bytes, 1 allocs
init go.amzn.com/lambda/core @6.6 ms, 0.007 ms clock, 224 bytes, 12 allocs
init go.amzn.com/lambda/rapi/rendering @6.7 ms, 0.086 ms clock, 16 bytes, 1 allocs
init go.amzn.com/lambda/rapi/handler @6.8 ms, 0 ms clock, 256 bytes, 2 allocs
init go.amzn.com/lambda/rapid @6.8 ms, 0.099 ms clock, 16 bytes, 1 allocs
...
INIT_START Runtime Version: nodejs:18.v9 Runtime Version ARN: arn:aws:lambda:us-east-1::runtime:7d5f06b69c951da8a48b926ce280a9daf2e8bb1a74fc4a2672580c787d608206
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we can clearly see some explicit package names coming from AWS. &lt;/p&gt;

&lt;p&gt;Another important thing to note is that those logs are output BEFORE the &lt;code&gt;INIT_START&lt;/code&gt; log line, which provides further evidence that it might be how AWS Lambda is managing your code!&lt;/p&gt;

&lt;p&gt;Voila! 🎉&lt;br&gt;
What do you think?&lt;/p&gt;

&lt;p&gt;You can find me on &lt;a href="https://www.linkedin.com/in/maxday/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; and &lt;a href="https://twitter.com/_maxday" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>performance</category>
    </item>
    <item>
      <title>Benchmarking Rust for Serverless</title>
      <dc:creator>Maxime David</dc:creator>
      <pubDate>Fri, 14 Apr 2023 14:35:19 +0000</pubDate>
      <link>https://dev.to/aws-builders/benchmarking-rust-for-serverless-36ck</link>
      <guid>https://dev.to/aws-builders/benchmarking-rust-for-serverless-36ck</guid>
      <description>&lt;p&gt;Let's start with two &lt;strong&gt;very&lt;/strong&gt; important questions:&lt;/p&gt;

&lt;p&gt;(1)  Why should I care to &lt;strong&gt;benchmark&lt;/strong&gt; Rust since it's already super fast?&lt;/p&gt;

&lt;p&gt;That's the question we'll try to answer in this post! &lt;/p&gt;

&lt;p&gt;(2) Will there be a 🍕 demo?&lt;/p&gt;

&lt;p&gt;Of course, you know that I'm a true 🍕🍕🍕 lover!&lt;/p&gt;

&lt;h3&gt;
  
  
  What's so special about Serverless?
&lt;/h3&gt;

&lt;p&gt;Benchmarking is not specific to serverless. But in serverless components, such as AWS Lambda functions, performance really matters for two main reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cold start duration&lt;/strong&gt; (good news, Rust is really performant as you can see in &lt;a href="https://maxday.github.io/lambda-perf"&gt;my daily updated benchmark&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Runtime duration&lt;/strong&gt;, as AWS is billing &lt;strong&gt;per millisecond&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see how we can measure and improve this runtime duration using benchmarks!&lt;/p&gt;

&lt;h3&gt;
  
  
  What are we going to benchmark?
&lt;/h3&gt;

&lt;p&gt;Let's take a very simple example:&lt;br&gt;&lt;br&gt;
&lt;code&gt;a function which returns the pizza of the day.&lt;/code&gt; 🍕 (I told you)&lt;/p&gt;

&lt;p&gt;We will compare two different implementations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one with HashMap - &lt;code&gt;std::collections::HashMap&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;one with Vec - &lt;code&gt;std::vec::Vec&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;(if you don't know much about Rust, you might wish to take a look at some basic Rust code before we start, like the Rust book or my &lt;a href="https://youtube.com/@maxday_coding"&gt;Rust Youtube channel&lt;/a&gt; 😇)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First, let's define our &lt;code&gt;PizzaStore&lt;/code&gt; trait:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;PizzaStore&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_pizza_of_the_day&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;day_index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And our first implementation with HashMap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// let's make sure we don't initialize a new HashMap each time&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;PizzaHashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;PizzaHashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;PizzaHashMap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;HashMap&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"margherita"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"deluxe"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"veggie"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"mushrooms"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bacon"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"four cheese"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"pepperoni"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="c1"&gt;// what's your favorite?&lt;/span&gt;
            &lt;span class="p"&gt;]),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;PizzaStore&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;PizzaHashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// let's get the pizza of the day from the cache (HashMap)&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_pizza_of_the_day&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;day_index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.cache&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;day_index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pizza&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pizza&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nb"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;panic!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"could not find the pizza"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Writing our first benchmark
&lt;/h3&gt;

&lt;p&gt;There are quite some crates to create benchmarks but we'll use &lt;code&gt;criterion&lt;/code&gt; here.&lt;br&gt;
Let's start by creating a &lt;code&gt;benches&lt;/code&gt; folder containing a &lt;code&gt;benchmark.rs&lt;/code&gt; file and add our first criterion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;criterion_hashmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;Criterion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;rng&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;thread_rng&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// we create the cache outside of the bench function so only one HashMap will be created&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pizza_store_hashmap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;PizzaHashMap&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// we call get_pizza_of_the_day with a random day index&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="nf"&gt;.bench_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"with hashmap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="n"&gt;pizza_store_hashmap&lt;/span&gt;&lt;span class="nf"&gt;.get_pizza_of_the_day&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="nf"&gt;.gen_range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;))));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need a bench group (as we will add more criterion later)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;criterion_group!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;benches&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;criterion_hashmap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;criterion_main!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;benches&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! Let's run it with &lt;code&gt;cargo bench&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;By default, it runs our function for about 5seconds (that's about 300M+ iterations)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;     &lt;span class="n"&gt;Running&lt;/span&gt; &lt;span class="n"&gt;benches&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;benchmark&lt;/span&gt;&lt;span class="nf"&gt;.rs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;benchmark&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f28819806c8c7c9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;hashmap&lt;/span&gt;            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;13.069&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="mf"&gt;13.090&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="mf"&gt;13.114&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Left and right values are lower and upper bounds. &lt;/p&gt;

&lt;p&gt;The number in the middle is the best estimation on how long each iteration is likely to take. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that those 3 numbers are extremely alike. This won't be the case if you're depending on networking for instance.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Second implementation: with Vec
&lt;/h3&gt;

&lt;p&gt;Let's create a different implementation using Vec instead of using HashMap using the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;PizzaVec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;PizzaVec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;PizzaVec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"margherita"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"deluxe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"veggie"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"mushrooms"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"bacon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"four cheese"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"pepperoni"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;PizzaStore&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;PizzaVec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_pizza_of_the_day&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;day_index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.cache&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day_index&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pizza&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pizza&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nb"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;panic!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"could not find the pizza"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's create a new criterion so we can compare (that's the goal of benchmarks!)&lt;br&gt;&lt;br&gt;
Back in &lt;code&gt;benchmark.rs&lt;/code&gt; we can add&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;criterion_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;Criterion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;rng&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;thread_rng&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pizza_store_vec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;PizzaVec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="nf"&gt;.bench_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"with vector"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="n"&gt;pizza_store_vec&lt;/span&gt;&lt;span class="nf"&gt;.get_pizza_of_the_day&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rng&lt;/span&gt;&lt;span class="nf"&gt;.gen_range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;))));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and update our group to include this new criterion:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;criterion_group!(benches, criterion_hashmap, criterion_vec);&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;so we can re-run our  benchmarks with : &lt;code&gt;cargo bench&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and check the result!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;hashmap&lt;/span&gt;            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;13.096&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="mf"&gt;13.117&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="mf"&gt;13.141&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;             &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7.5832&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="mf"&gt;7.5958&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="mf"&gt;7.6097&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By replacing our HashMap with a Vec, our program is now running almost &lt;strong&gt;twice as fast&lt;/strong&gt;! &lt;/p&gt;

&lt;p&gt;This is a great reminder on how the data structure choice is really important depending on the use case 😇&lt;/p&gt;

&lt;h3&gt;
  
  
  Ok great, but how does it translate to Serverless?
&lt;/h3&gt;

&lt;p&gt;Two AWS Lambda Functions have been deployed embedding each one of the implementations.&lt;/p&gt;

&lt;p&gt;Each lambda function calls &lt;strong&gt;10_000_000 times&lt;/strong&gt; &lt;code&gt;get_pizza_of_the_day&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;In &lt;code&gt;us-east-1&lt;/code&gt; with &lt;code&gt;128MB&lt;/code&gt;, here are the results:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implementation&lt;/th&gt;
&lt;th&gt;Runtime duration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HashMap&lt;/td&gt;
&lt;td&gt;267.92 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vec&lt;/td&gt;
&lt;td&gt;87.98 ms 🤯🤯&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That's it! &lt;/p&gt;

&lt;p&gt;Of course this was a simple example but I hope I've convinced you to use benchmarks to optimize your code!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bonus question:&lt;/strong&gt; where does this overhead come from? &lt;/p&gt;

&lt;p&gt;Stay tuned for the next blog post about &lt;strong&gt;Rust profiling&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;❤️ ❤️ ❤️ Did you like this content? ❤️ ❤️ ❤️ &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Follow me on &lt;a href="https://linkedin.com/in/maxday"&gt;LinkedIn&lt;/a&gt; &amp;amp; &lt;a href="https://twitter.com/_maxday"&gt;Twitter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Check my &lt;a href="https://youtube.com/@maxday_coding"&gt;Rust Youtube channel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Share with your friends &amp;lt;3&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>serverless</category>
      <category>rust</category>
      <category>lambda</category>
      <category>aws</category>
    </item>
    <item>
      <title>RUST: How to test println!() ?</title>
      <dc:creator>Maxime David</dc:creator>
      <pubDate>Tue, 22 Nov 2022 21:07:02 +0000</pubDate>
      <link>https://dev.to/maxday/rust-how-to-test-println--1bd8</link>
      <guid>https://dev.to/maxday/rust-how-to-test-println--1bd8</guid>
      <description>&lt;p&gt;Let's say we want to test that a function is correctly outputting something.&lt;/p&gt;

&lt;p&gt;Our function may looks like this simple example: print n times the name given in parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;nb&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hi {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;   
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How to test it? 🤔 It looks hard.&lt;/p&gt;

&lt;p&gt;One easy way is to refactor our code using a &lt;code&gt;Trait&lt;/code&gt;.&lt;br&gt;
You can see Traits as interfaces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="k"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, let's define a &lt;code&gt;struct&lt;/code&gt; which implements this &lt;code&gt;trait&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;ConsoleLogger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ConsoleLogger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="k"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! Now we can refactor our &lt;code&gt;greeting&lt;/code&gt; function to use this &lt;code&gt;trait&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;nb&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="nf"&gt;.log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hi {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok but how this is helpful for testing?&lt;/p&gt;

&lt;p&gt;Well, now, in tests, we could define a new struct with a different implementation for our trait. &lt;/p&gt;

&lt;p&gt;Here, instead of outputting our strings using &lt;code&gt;println!&lt;/code&gt; we will store those in a &lt;code&gt;Vec&amp;lt;String&amp;gt;&lt;/code&gt;&lt;br&gt;
This way, it will be super easy to assert that our values are valid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nf"&gt;TestLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;TestLogger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="k"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can finally test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[test]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;greeting_test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;test_logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;TestLogger&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"maxday"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;test_logger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test_logger&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hi maxday"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test_logger&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hi maxday"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test_logger&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voila! 🎉&lt;/p&gt;

&lt;p&gt;Full code here: &lt;a href="https://gist.github.com/maxday/ae3c9f219c35c228dadd5359def5a833"&gt;https://gist.github.com/maxday/ae3c9f219c35c228dadd5359def5a833&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🚀 🚀 🚀 If you want more Rust, feel free to check my new YouTube channel here: &lt;a href="https://youtube.com/@maxday_coding"&gt;https://youtube.com/@maxday_coding&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>testing</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
