<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Vivek Shukla - Programming</title>
    <subtitle>I am a Software Engineer from India. I am currently building Daestro. I work in Rust, Javascript and Python.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://vshukla.com/tags/programming/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://vshukla.com/tags/programming/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2025-09-08T00:00:00+00:00</updated>
    <id>https://vshukla.com/tags/programming/atom.xml</id>
    <entry xml:lang="en">
        <title>Setup Redis TLS With Self-signed Certificate</title>
        <published>2025-09-08T00:00:00+00:00</published>
        <updated>2025-09-08T00:00:00+00:00</updated>
        <author>
          <name>Vivek Shukla</name>
        </author>
        <link rel="alternate" type="text/html" href="https://vshukla.com/tech/setup-redis-tls-with-self-signed-certs/"/>
        <id>https://vshukla.com/tech/setup-redis-tls-with-self-signed-certs/</id>
        <summary type="html">Brief guide on how to setup Redis TLS using Self-signed certificate.</summary>
        <content type="html" xml:base="https://vshukla.com/tech/setup-redis-tls-with-self-signed-certs/">&lt;blockquote&gt;
&lt;p&gt;This method is only recommended when connecting to redis server via local network.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;generate-server-certificates&quot;&gt;Generate Server Certificates&lt;/h2&gt;
&lt;p&gt;Generate Cert and Key file for self signed TLS, then move both these files to redis directory and set the proper permissions. Delete the Key file and copy the cert file to the client machine which will connect to the redis-server.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-14&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; ~&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;openssl&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; req&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -x509 -nodes -days&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; 3650&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -newkey&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; rsa:2048&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;  -keyout&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; redis_tls.key&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -out&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; redis_tls.crt&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;  -subj&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;/CN=YourOrg&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; cp redis_tls.key redis_tls.crt /etc/redis/&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; rm&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; redis_tls.key&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; chmod&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; 600&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; /etc/redis/redis_tls.key&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; chmod&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; 644&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; /etc/redis/redis_tls.crt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; chown redis:redis /etc/redis/redis_tls.key&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; chown redis:redis /etc/redis/redis_tls.crt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;update-redis-configuration-file&quot;&gt;Update Redis Configuration File&lt;/h2&gt;
&lt;p&gt;This command will append the value to &lt;code&gt;redis.conf&lt;/code&gt; (redis configuration file). Make sure to update the password.&lt;/p&gt;
&lt;p&gt;It will disable the non-tls support and enable the tls connection at port &lt;code&gt;6379&lt;/code&gt; with previously generated key and cert files.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; tee&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -a&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; /etc/redis/redis.conf&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt; EOF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;bind * -::*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;port 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;tls-port 6379&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;tls-cert-file /etc/redis/redis_tls.crt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;tls-key-file /etc/redis/redis_tls.key&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;tls-auth-clients no&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;tls-prefer-server-ciphers yes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;requirepass YOUR_PASSWORD_HERE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;EOF&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Restart and enable redis&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; systemctl restart redis-server&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; systemctl enable redis-server&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Check status with&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; systemctl status redis-server&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If any error then check journal (log)&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; journalctl&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -u&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; redis-server&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -f&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;add-redis-certificate-to-trusted-ca-store-in-client-machine&quot;&gt;Add Redis Certificate to Trusted CA Store in Client Machine&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# Copy your certificate to CA certificates directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; mv redis_tls.crt /usr/local/share/ca-certificates/redis_tls.crt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# Update CA certificates&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; update-ca-certificates&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;redis-connection-url&quot;&gt;Redis Connection URL&lt;/h2&gt;
&lt;p&gt;Since we want to connect to redis using TLS connection, so the protocol in the url will be &lt;code&gt;rediss&lt;/code&gt; (with double “ss”).&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rediss://:&amp;lt;your_password_here&amp;gt;@&amp;lt;redis_server_ip&amp;gt;:6379/0#insecure&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    </entry>
    <entry xml:lang="en">
        <title>How I Use Cargo Workspace to structure my Rust projects</title>
        <published>2025-09-03T00:00:00+00:00</published>
        <updated>2025-09-05T00:00:00+00:00</updated>
        <author>
          <name>Vivek Shukla</name>
        </author>
        <link rel="alternate" type="text/html" href="https://vshukla.com/tech/2025/use-cargo-workspace-rust/"/>
        <id>https://vshukla.com/tech/2025/use-cargo-workspace-rust/</id>
        <summary type="html">Learn how to use Cargo Workspaces to break your project into multiple modules (libs and bins).</summary>
        <content type="html" xml:base="https://vshukla.com/tech/2025/use-cargo-workspace-rust/">&lt;blockquote&gt;
&lt;p&gt;I’ve learn to use Cargo Workspace from &lt;a rel=&quot;external&quot; href=&quot;https://bsky.app/profile/iolivia.me/post/3lu5elia4w62u&quot;&gt;Olivia’s post in bluesky&lt;/a&gt;, which you should checkout. This article is a way of self-documenting since I’ve come back to it more often.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;what-is-a-cargo-workspace&quot;&gt;What is a Cargo Workspace&lt;/h2&gt;
&lt;p&gt;A cargo workspace is collection of one or more library or binary crates. Cargo workspace let’s you break your rust project into multiple different crates (or packages), which may aid you in better project structure and management.&lt;/p&gt;
&lt;h2 id=&quot;why-use-cargo-workspace&quot;&gt;Why use Cargo Workspace&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Your rust project has grown big and is hard to manage&lt;/li&gt;
&lt;li&gt;Multiple people work on a project, so breaking your project into multiple crates can help with better ownership and less conflict among developers&lt;/li&gt;
&lt;li&gt;You want to reduce your project’s compile time&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Read this (external link): &lt;a rel=&quot;external&quot; href=&quot;https://www.feldera.com/blog/cutting-down-rust-compile-times-from-30-to-2-minutes-with-one-thousand-crates&quot;&gt;Cutting Down Rust Compile Times From 30 to 2 Minutes With One Thousand Crates&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;creating-a-workspace&quot;&gt;Creating a Workspace&lt;/h2&gt;
&lt;p&gt;Create a new workspace directory&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;mkdir&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; runner&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-14&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; runner&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now create &lt;code&gt;Cargo.toml&lt;/code&gt; with following content&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;workspace&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;resolver&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;3&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we are using &lt;code&gt;resolver&lt;/code&gt; version 3, which is the latest version and comes in Rust 2024 edition (Rust 1.84+). Resolver tells cargo how to resolve the dependencies.&lt;/p&gt;
&lt;h3 id=&quot;create-a-binary-crate&quot;&gt;Create a binary crate&lt;/h3&gt;
&lt;p&gt;We are going to use &lt;code&gt;cargo new&lt;/code&gt; command to create a binary crate. When no argument is passed, cargo new command will create binary crate by default, you can use &lt;code&gt;--lib&lt;/code&gt; as argument to create library crate or &lt;code&gt;--bin&lt;/code&gt; to explicit that you want binary crate.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; new run&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now your workspace will look like this:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└── run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ├── Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    └── src&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        └── main.rs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you look at your workspace’s &lt;code&gt;Cargo.toml&lt;/code&gt; you will notice that cargo has already added the newly added crate &lt;code&gt;run&lt;/code&gt; against the &lt;code&gt;members&lt;/code&gt; key.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;workspace&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;resolver&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;3&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;members&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;run&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;adding-lib-crates&quot;&gt;Adding lib crates&lt;/h3&gt;
&lt;p&gt;Let’s add two lib crates&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; new participant&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --lib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; new track&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --lib&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Updated structure:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── Cargo.lock&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── participant&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   └── src&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│       └── lib.rs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   └── src&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│       └── main.rs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└── track&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ├── Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    └── src&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        └── lib.rs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;adding-dependencies&quot;&gt;Adding dependencies&lt;/h3&gt;
&lt;p&gt;If you try to simply add a dependency like this&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; add uuid&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --features&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; v4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;‼️ it will fail and you will see this error&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;error: `cargo add` could not determine which package to modify. Use the `--package` option to specify a package. &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;available packages: participant, run, track&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since inside our Cargo workspace we have 3 packages, therefore cargo is unable to determine to which package dependency belongs to. ✅ We can solve this by using &lt;code&gt;--package&lt;/code&gt; arg.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; add uuid&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --features&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; v4&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --package&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; participant&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;dependency-resolution&quot;&gt;Dependency Resolution&lt;/h3&gt;
&lt;p&gt;Since in cargo workspace we can have multiple crates, which means we have to add dependency to each crate separately and in that sometimes there may be a version mismatch.&lt;/p&gt;
&lt;p&gt;Like with &lt;code&gt;uuid&lt;/code&gt; in &lt;code&gt;participant&lt;/code&gt; crate, it is using version &lt;code&gt;1.18.1&lt;/code&gt; and now you if you try to add &lt;code&gt;uuid&lt;/code&gt; of different version in &lt;code&gt;run&lt;/code&gt; crate, for example if we want to stick to only &lt;code&gt;1.17&lt;/code&gt; version of the &lt;code&gt;uuid&lt;/code&gt; crate:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; add uuid@=&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;1.17&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --features&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; v4&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --package&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; run&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But wait, we got error&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;error: failed to select a version for `uuid`.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... required by package `run v0.1.0 (/home/vivek/Documents/code/hands-on/runner/run)`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;versions that meet the requirements `=1.17` are: 1.17.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;all possible versions conflict with previously selected packages.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  previously selected package `uuid v1.18.1`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... which satisfies dependency `uuid = &amp;quot;^1.18.1&amp;quot;` of package `participant v0.1.0 (/home/vivek/Documents/code/hands-on/runner/participant)`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;failed to select a version for `uuid` which could resolve this conflict&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s because a Cargo workspace can only have one &lt;code&gt;Cargo.lock&lt;/code&gt; file, which is shared between all the members of the workspace, so it can only have one version of the dependency across the workspace. So instead of pinning to &lt;code&gt;=1.17&lt;/code&gt; version of uuid, we had used just &lt;code&gt;1.17&lt;/code&gt;, cargo would have choosen &lt;code&gt;uuid@1.18.1&lt;/code&gt; since that was already being used by &lt;code&gt;participant&lt;/code&gt; crate.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In order to resolve the dependency across workspace, cargo will try to find the most suitable version of a crate, mostly by downgrading to the appropriate version.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;better-way-to-declare-dependency&quot;&gt;Better way to declare dependency&lt;/h3&gt;
&lt;p&gt;It’s very normal to have common dependencies across crates, that is why Cargo Workspace let us declare dependencies in workspace’s &lt;code&gt;Cargo.toml&lt;/code&gt; and then you can re-use the same dependency inside of your crate.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;workspace&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;uuid&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { version&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;=1.17&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;span&gt; features&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;v4&amp;quot;&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then in your crates you can use the dependency with:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# participant/Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;uuid&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { workspace&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# run/Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;uuid&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { workspace&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;importing-members-as-dependencies&quot;&gt;Importing members as dependencies&lt;/h3&gt;
&lt;p&gt;A common way to import a crate (or package) inside another crate is like this:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# run/Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;participant&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { path&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;../participant&amp;quot;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;track&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { path&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;../track&amp;quot;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# track/Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;participant&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { path&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;../participant&amp;quot;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But now if you had to do this for each of the crate in your project and sometime there can be a lot of crates. Also the path is relative to the current Cargo.toml file, so if you dare re-structure your workspace, it can backfire and you will have another mess to deal with.&lt;/p&gt;
&lt;p&gt;However we can use the same way of delcaring the dependency in the workspace’s &lt;code&gt;Cargo.toml&lt;/code&gt; and then just use it inside the members by telling cargo to use workspace’s dependency.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;workspace&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;resolver&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;3&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;members&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;participant&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;run&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;track&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;workspace&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;participant&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { path&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;participant&amp;quot;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;track&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { path&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;track&amp;quot;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# run/Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;participant&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { workspace&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;track&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { workspace&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# track/Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;participant&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { workspace&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;multiple-binaries&quot;&gt;Multiple Binaries&lt;/h3&gt;
&lt;p&gt;When you have multiple binaries in your workspace, &lt;code&gt;cargo run&lt;/code&gt; won’t work since it doesn’t know which binary crate to run. So instead explicitly pass the crate name:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --package&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; my_bin_crate&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;cheat-sheet&quot;&gt;Cheat sheet&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Create workspace:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;workspace&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;resolver&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;3&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Adding bin and lib to workspace:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# creates binary crate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; new my_bin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# crates lib crate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; new my_lib&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --lib&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Importing dependencies:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# Add dependencies in workspace&amp;#39;s Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;workspace&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;uuid&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { version&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;=1.17&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;span&gt; features&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;v4&amp;quot;&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# import in members like this: my_lib/Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;uuid&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { workspace&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Import members like this:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;workspace&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;resolver&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;3&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;members&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;my_bin&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;my_lib&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;workspace&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;my_lib&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { path&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;my_lib&amp;quot;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# my_bin/Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;my_lib&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { workspace&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Other commands:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# run if multiple binaries exist&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; run&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --package&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; my_bin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# build specific binary&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; build&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --package&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; my_bin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# build all&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; build&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --all&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;# test all&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; test&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --all&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    </entry>
    <entry xml:lang="en">
        <title>How I use Postgres DB as Key Value Store in Rust with SQLx</title>
        <published>2025-09-02T00:00:00+00:00</published>
        <updated>2025-09-03T00:00:00+00:00</updated>
        <author>
          <name>Vivek Shukla</name>
        </author>
        <link rel="alternate" type="text/html" href="https://vshukla.com/tech/2025/postgres-key-value-store-rust-sqlx/"/>
        <id>https://vshukla.com/tech/2025/postgres-key-value-store-rust-sqlx/</id>
        <summary type="html">This guide demonstrate how to use Postgres DB for you KV storage needs.</summary>
        <content type="html" xml:base="https://vshukla.com/tech/2025/postgres-key-value-store-rust-sqlx/">&lt;p&gt;For my smaller application (or personal) or when I’m starting out a new app, I would like to keep the dependencies of my program to minimum. Since I’m going to need a DB anyway, so instead of using Redis and adding one more component to my tech stack, I would like to use &lt;a href=&quot;/tags/postgresql/&quot;&gt;Postgres&lt;/a&gt; as my key value store.&lt;/p&gt;
&lt;p&gt;Prematurely thinking about scaling your system when you don’t even know if it would be successful enough to actually need all those bells and whistle is sure way to extend the deadline and procrastinate.&lt;/p&gt;
&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;
&lt;p&gt;We are going to create a &lt;code&gt;trait&lt;/code&gt; called &lt;code&gt;PgStore&lt;/code&gt;, which will implement all the functions to set, get, pop and delete the value.&lt;/p&gt;
&lt;p&gt;Then you can implement this trait for your own types. Your types must derive serde’s &lt;code&gt;Serialize&lt;/code&gt; and &lt;code&gt;Deserialize&lt;/code&gt; for this to work.&lt;/p&gt;
&lt;h2 id=&quot;dependencies&quot;&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;You need the following dependencies in your &lt;code&gt;Cargo.toml&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;chrono&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { version&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;0.4&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;span&gt; features&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;serde&amp;quot;&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;serde&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { version&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;1.0&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;span&gt; features&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;derive&amp;quot;&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;serde_json&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { version&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;1.0&amp;quot;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sqlx&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { version&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;0.8&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;span&gt; features&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    &amp;quot;runtime-tokio&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    &amp;quot;tls-rustls-ring-native-roots&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    &amp;quot;migrate&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    &amp;quot;postgres&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    &amp;quot;macros&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    &amp;quot;chrono&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;creating-static-pgpool-connection&quot;&gt;Creating static PgPool connection&lt;/h2&gt;
&lt;p&gt;I don’t like to pass around DB connection across functions or threads or tasks. Instead I like to use tokio’s &lt;code&gt;OnceCell&lt;/code&gt; which is a thread safe Cell which can be written to only once, it’s thread safe which means we can use async code in it.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;PgPool&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; tokio&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;OnceCell&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; PG_POOL&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; OnceCell&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;PgPool&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; OnceCell&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;const_new&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;pub async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; pg_pool&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt; &amp;amp;&lt;/span&gt;&lt;span&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;static PgPool&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;    PG_POOL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;get_or_init&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;async&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; ||&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;            PgPool&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;connect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;env&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;DATABASE_URL&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;DATABASE_URL is not set&amp;quot;&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;❌ PgPool connection failed&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can just use &lt;code&gt;pg_pool().await&lt;/code&gt; to fetch the db pool connection wherever we need.&lt;/p&gt;
&lt;h2 id=&quot;db-migration&quot;&gt;DB Migration&lt;/h2&gt;
&lt;p&gt;We are creating a new table &lt;code&gt;kv_store&lt;/code&gt; in our Postgres DB. If you notice we are using &lt;code&gt;UNLOGGED&lt;/code&gt; keyword to create the table, this tells postgres to not write WAL (write-ahead log) for &lt;code&gt;kv_store&lt;/code&gt; table, which improves the performance at the expanse of data durability.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;CREATE&lt;/span&gt;&lt;span&gt; UNLOGGED &lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;kv_store&amp;quot;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    &amp;quot;key&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;2048&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt; PRIMARY KEY&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    &amp;quot;value&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt; TEXT NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    &amp;quot;expires&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt; TIMESTAMPTZ NOT NULL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;pgstore-trait&quot;&gt;PgStore Trait&lt;/h2&gt;
&lt;p&gt;We are creating &lt;code&gt;PgStore&lt;/code&gt; trait which will have methods to store, retrieve and delete the value in the &lt;code&gt;kv_store&lt;/code&gt; table.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; chrono&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;DateTime&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Utc&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; serde&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Serialize&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; serde&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;de&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;DeserializeOwned&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; std&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Duration&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[allow(async_fn_in_trait)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;pub trait&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; PgStore&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Serialize&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; +&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; DeserializeOwned&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    const&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; EXPIRE_IN&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; usize&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt; // seconds&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; key_format&lt;/span&gt;&lt;span&gt;(key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; get_expire_time&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; DateTime&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Utc&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        Utc&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;now&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; +&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Duration&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_secs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-1 z-i&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;EXPIRE_IN&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt; as&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; u64&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; set_ex&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-1 z-i&quot;&gt;self&lt;/span&gt;&lt;span&gt;, key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Result&lt;/span&gt;&lt;span&gt;&amp;lt;(),&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;        let&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;            serde_json&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-1 z-i&quot;&gt;self&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;map_err&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;Failed to serialize value.&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;query!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            r#&amp;quot;INSERT INTO kv_store (&amp;quot;key&amp;quot;, &amp;quot;value&amp;quot;, expires) VALUES ($1, $2, $3)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            ON CONFLICT (&amp;quot;key&amp;quot;) DO UPDATE SET &amp;quot;value&amp;quot; = $2, expires = $3&amp;quot;#&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1 z-i&quot;&gt;            Self&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;key_format&lt;/span&gt;&lt;span&gt;(key),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            value,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1 z-i&quot;&gt;            Self&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;get_expire_time&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;execute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;pg_pool&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;map_err&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;Failed to set value in kv_store&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        Ok&lt;/span&gt;&lt;span&gt;(())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // it will just fetch the value if it exists&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; get&lt;/span&gt;&lt;span&gt;(key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Result&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1 z-i&quot;&gt;Self&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;        let&lt;/span&gt;&lt;span&gt; record&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;query!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            r#&amp;quot;SELECT &amp;quot;value&amp;quot; FROM kv_store WHERE &amp;quot;key&amp;quot; = $1&amp;quot;#&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1 z-i&quot;&gt;            Self&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;key_format&lt;/span&gt;&lt;span&gt;(key)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;fetch_one&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;pg_pool&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;map_err&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;Failed to get value from kv_store&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        serde_json&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_str&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;record&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span&gt;value)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;map_err&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;Failed to deserialize value&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // this will fetch the value while extending the expire time&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; get_ex&lt;/span&gt;&lt;span&gt;(key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Result&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1 z-i&quot;&gt;Self&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;        let&lt;/span&gt;&lt;span&gt; record&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;query!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            r#&amp;quot;UPDATE kv_store SET expires=$2 WHERE &amp;quot;key&amp;quot;=$1 RETURNING &amp;quot;value&amp;quot;&amp;quot;#&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1 z-i&quot;&gt;            Self&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;key_format&lt;/span&gt;&lt;span&gt;(key),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1 z-i&quot;&gt;            Self&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;get_expire_time&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;fetch_one&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;pg_pool&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;map_err&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;Failed to get value from kv_store&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        serde_json&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_str&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;record&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span&gt;value)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;map_err&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;Failed to deserialize value&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // it will fetch the value while deleting the key&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; get_del&lt;/span&gt;&lt;span&gt;(key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Result&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-1 z-i&quot;&gt;Self&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;        let&lt;/span&gt;&lt;span&gt; record&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;query!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            r#&amp;quot;DELETE FROM kv_store WHERE key=$1 RETURNING &amp;quot;value&amp;quot;&amp;quot;#&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1 z-i&quot;&gt;            Self&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;key_format&lt;/span&gt;&lt;span&gt;(key)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;fetch_one&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;pg_pool&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;map_err&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;Failed to get value from kv_store&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        serde_json&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_str&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;record&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span&gt;value)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;map_err&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;Failed to deserialize value&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; del&lt;/span&gt;&lt;span&gt;(key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Result&lt;/span&gt;&lt;span&gt;&amp;lt;(),&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;query!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            r#&amp;quot;DELETE FROM kv_store WHERE key=$1&amp;quot;#&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-1 z-i&quot;&gt;            Self&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;key_format&lt;/span&gt;&lt;span&gt;(key)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;execute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;pg_pool&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;map_err&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;Failed to delete value&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        Ok&lt;/span&gt;&lt;span&gt;(())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By defining our trait like &lt;code&gt;PgStore: Serialize + DeserializeOwned&lt;/code&gt;, we are telling that whichever type is going to implement &lt;code&gt;PgStore&lt;/code&gt; trait it must also have &lt;code&gt;Serialize&lt;/code&gt; and &lt;code&gt;DeserializeOwned&lt;/code&gt; implemented.&lt;/p&gt;
&lt;p&gt;Following are the brief explaination of &lt;code&gt;PgStore&lt;/code&gt;’s attributes:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;EXPIRE_IN:&lt;/strong&gt; This will be used to set the to be expired in seconds. It must be implemented by the Type you are using it for.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;key_format:&lt;/strong&gt; This function needs to be implemented. It will be used as a way to generate key.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;set_ex:&lt;/strong&gt; This method will store the type against the passed key in DB, overwriting value if it already exists.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;get:&lt;/strong&gt; It will fetch the value for a given key, error will be returned if it does not exist.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;get_ex:&lt;/strong&gt; Fetches the value while resetting the expire time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;get_del:&lt;/strong&gt; Fetch the value while deleting the key. It’s more like pop.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;del:&lt;/strong&gt; Just deletes the value. Doesn’t return error even if key doesn’t exist.&lt;/p&gt;
&lt;h2 id=&quot;cleaning-up-expired-keys&quot;&gt;Cleaning up expired keys&lt;/h2&gt;
&lt;p&gt;Then we have a helper function &lt;code&gt;pgstore_cleanup&lt;/code&gt; which will cleanup expired keys every 60 seconds. You must spawn to run this function in the background for all the time your program is running.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;pub async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; pgstore_cleanup&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    loop&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;        // tracing::info!(&amp;quot;🟡 PgStore cleanup is running...&amp;quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;query!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;r#&amp;quot;DELETE FROM kv_store WHERE expires &amp;lt; NOW()&amp;quot;#&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;            .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;execute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;pg_pool&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;            .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;            .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;ok&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;        tokio&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;sleep&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_secs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;60&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(serde&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Serialize&lt;/span&gt;&lt;span&gt;, serde&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Deserialize&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;pub struct&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Game&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    pub&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; usize&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    pub&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    pub&lt;/span&gt;&lt;span&gt; genre&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; PgStore&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt; for&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Game&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    const&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; EXPIRE_IN&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; usize&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; 3600&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; key_format&lt;/span&gt;&lt;span&gt;(key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-18&quot;&gt;        format!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;game-{}&amp;quot;&lt;/span&gt;&lt;span&gt;, key)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[tokio&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;main]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // make sure to run this to delete expired keys regularly&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    tokio&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;spawn&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;pgstore_cleanup&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; game&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Game&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        id&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; 1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        name&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;Skyrim&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        genre&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;rpg&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // storing value in kv_store&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // it will be store with key: &amp;quot;game-1&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; _&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span&gt; game&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;set_ex&lt;/span&gt;&lt;span&gt;(game&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // fetching value&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    if let&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Ok&lt;/span&gt;&lt;span&gt;(v)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Game&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-18&quot;&gt;        println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;fetched game with name: {}&amp;quot;&lt;/span&gt;&lt;span&gt;, v&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span&gt;name);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // deleting key&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; _&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Game&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;del&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly you can do this with your own types, as long as they derive serde’s Serialize and Deserialize.&lt;/p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Minify HTML in Axum Middleware</title>
        <published>2025-09-01T00:00:00+00:00</published>
        <updated>2025-09-01T00:00:00+00:00</updated>
        <author>
          <name>Vivek Shukla</name>
        </author>
        <link rel="alternate" type="text/html" href="https://vshukla.com/tech/2025/minify-html-axum-middleware/"/>
        <id>https://vshukla.com/tech/2025/minify-html-axum-middleware/</id>
        <summary type="html">We are going to create Axum middleware which maps to the response and minifies the HTML body on the fly.</summary>
        <content type="html" xml:base="https://vshukla.com/tech/2025/minify-html-axum-middleware/">&lt;p&gt;Minifying HTML is one of the simplest way to save bandwidth and decrease the time in transit. We can easily lower page size by 30-50% by minifying HTML.&lt;/p&gt;
&lt;p&gt;We will be using &lt;a rel=&quot;external&quot; href=&quot;https://crates.io/crates/minify-html&quot;&gt;minify-html&lt;/a&gt; crate for this. With the use of Axum middleware, minification will be applied to all the eligible routes.&lt;/p&gt;
&lt;p&gt;Using axum middleware for HTML minification is template agnostic which means it will work with any template engine such as Askama, Tera, Maud, etc., as long as response type is HTML, it should work fine.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cargo.toml&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;code&gt;minify-html&lt;/code&gt; to your Cargo.toml.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;minify&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;-&lt;/span&gt;&lt;span&gt;html&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;0.16.4&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;basic-usage-of-minify-html&quot;&gt;Basic Usage of minify-html&lt;/h2&gt;
&lt;p&gt;minify-html provides &lt;code&gt;minify&lt;/code&gt; function which accepts array of bytes and reference to configuration struct which tells it how to minify.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;let&lt;/span&gt;&lt;span&gt; cfg&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; minify_html&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Cfg&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        keep_closing_tags&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        keep_html_and_head_opening_tags&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        keep_comments&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        minify_doctype&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        minify_css&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        minify_js&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        ..&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Default&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;default&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;let mut&lt;/span&gt;&lt;span&gt; code&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;u8&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; b&amp;quot;&amp;lt;p&amp;gt;  Hello, world!  &amp;lt;/p&amp;gt;&amp;quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;let&lt;/span&gt;&lt;span&gt; minified&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; minify_html&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;minify&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;code,&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span&gt;cfg);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-18&quot;&gt;assert_eq!&lt;/span&gt;&lt;span&gt;(minified,&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; b&amp;quot;&amp;lt;p&amp;gt;Hello, world!&amp;lt;/p&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_vec&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;creating-axum-middleware&quot;&gt;Creating Axum Middleware&lt;/h2&gt;
&lt;p&gt;We are using Axum’s &lt;code&gt;axum::middleware::map_response&lt;/code&gt; middleware to modify the response on the fly by passing an async function.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Steps to be performed by middleware:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Only move forward if the &lt;code&gt;Content-Type&lt;/code&gt; header of the reponse is &lt;code&gt;text/html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;into_parts&lt;/code&gt; method of response to consume the response body give out parts (headers, status code, etc.) and body (actual html content)&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;to_bytes&lt;/code&gt; function we collect and convert &lt;code&gt;axum::body::Body&lt;/code&gt; type into &lt;code&gt;Bytes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Then using &lt;code&gt;minify_html::minify&lt;/code&gt; function we minify the html&lt;/li&gt;
&lt;li&gt;Finally build the new response using &lt;code&gt;Response::from_parts&lt;/code&gt; with the parts that we extracted earlier and new body (minified html)&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; std&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;LazyLock&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; axum&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    body&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Body&lt;/span&gt;&lt;span&gt;, to_bytes},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    http&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;header,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    response&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Response&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; MINIFY_CFG&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; LazyLock&lt;/span&gt;&lt;span&gt;&amp;lt;minify_html&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Cfg&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; LazyLock&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;new&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; minify_html&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Cfg&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    keep_closing_tags&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    keep_html_and_head_opening_tags&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    minify_doctype&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    minify_css&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    minify_js&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;    ..&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Default&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;default&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;pub async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; minify_html_response&lt;/span&gt;&lt;span&gt;(response&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Response&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Body&lt;/span&gt;&lt;span&gt;&amp;gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Response&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Body&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; content_type&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span&gt; response&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;headers&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;CONTENT_TYPE&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span&gt;h&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;|&lt;/span&gt;&lt;span&gt; h&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_str&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap_or_default&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap_or_default&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    if&lt;/span&gt;&lt;span&gt; content_type&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;contains&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;text/html&amp;quot;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;        let&lt;/span&gt;&lt;span&gt; (parts, body)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span&gt; response&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;into_parts&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;        let&lt;/span&gt;&lt;span&gt; bytes&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; to_bytes&lt;/span&gt;&lt;span&gt;(body,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; usize&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;MAX&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap_or_default&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;        let&lt;/span&gt;&lt;span&gt; minified&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; minify_html&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;minify&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;bytes,&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt;MINIFY_CFG&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;        let&lt;/span&gt;&lt;span&gt; new_response&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Response&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_parts&lt;/span&gt;&lt;span&gt;(parts,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Body&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from&lt;/span&gt;&lt;span&gt;(minified));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;        return&lt;/span&gt;&lt;span&gt; new_response;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    response&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note: We are using &lt;code&gt;LazyLock&lt;/code&gt; to initialize &lt;code&gt;minify_html::Cfg&lt;/code&gt; only once, since we are going to need the reference to it for each minify call.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Plugging into the Router:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;let&lt;/span&gt;&lt;span&gt; router&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; axum&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;new&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;    .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;route&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; get&lt;/span&gt;&lt;span&gt;(index_page))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;    .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;layer&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;axum&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;middleware&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;map_response&lt;/span&gt;&lt;span&gt;(minify_html_response));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;benchmark&quot;&gt;Benchmark&lt;/h2&gt;
&lt;p&gt;I’ve done very basic benchmarking on this&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Overhead:&lt;/strong&gt; The overhead of extracting response body and minifying adds around &lt;code&gt;600&lt;/code&gt; to &lt;code&gt;800&lt;/code&gt; µs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Size Reduction:&lt;/strong&gt; This will be varied for everyone and depends on the content they serve. However, I’ve consistently seen at least 30% reduction in HTML document size.&lt;/p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Using SQLite Database in Rust with Sqlx</title>
        <published>2025-04-13T00:00:00+00:00</published>
        <updated>2025-04-13T00:00:00+00:00</updated>
        <author>
          <name>Vivek Shukla</name>
        </author>
        <link rel="alternate" type="text/html" href="https://vshukla.com/tech/sqlite-in-rust-with-sqlx/"/>
        <id>https://vshukla.com/tech/sqlite-in-rust-with-sqlx/</id>
        <summary type="html">Guide to use SQLite database in Rust with Sqlx</summary>
        <content type="html" xml:base="https://vshukla.com/tech/sqlite-in-rust-with-sqlx/">&lt;p&gt;SQLite is self-contained, file based relational database. If you have a simple use case and want to avoid complex databases then SQLite is one of the best choice.&lt;/p&gt;
&lt;p&gt;We will use &lt;a rel=&quot;external&quot; href=&quot;https://github.com/launchbadge/sqlx&quot;&gt;&lt;code&gt;sqlx&lt;/code&gt; crate&lt;/a&gt; to interact with SQLite database.&lt;/p&gt;
&lt;p&gt;Why Sqlx?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Async support&lt;/li&gt;
&lt;li&gt;Supports migrations&lt;/li&gt;
&lt;li&gt;Compile time type safety&lt;/li&gt;
&lt;li&gt;Supports SQLite, Postgres and MySQL&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; init sqlite-demo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;cargo-toml&quot;&gt;Cargo.toml&lt;/h3&gt;
&lt;p&gt;Add the following dependencies to your &lt;code&gt;Cargo.toml&lt;/code&gt; file. We are using &lt;a rel=&quot;external&quot; href=&quot;https://github.com/tokio-rs/tokio&quot;&gt;tokio runtime&lt;/a&gt; and sqlite features of &lt;code&gt;sqlx&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;package&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;name&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;sqlite-demo&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;version&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;0.1.0&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;edition&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;2024&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;dependencies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sqlx&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { version&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;0.8&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;span&gt; features&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    &amp;quot;runtime-tokio&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    &amp;quot;sqlite&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;    &amp;quot;migrate&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tokio&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; { version&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;1.44.2&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;,&lt;/span&gt;&lt;span&gt; features&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;full&amp;quot;&lt;/span&gt;&lt;span&gt;] }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;connect-to-sqlite-database&quot;&gt;Connect to SQLite Database&lt;/h2&gt;
&lt;p&gt;Here we are using &lt;code&gt;SqliteConnectOptions&lt;/code&gt; to connect to SQLite database. We are also creating the database file if it doesn’t exist. We are using &lt;code&gt;SqliteJournalMode::Delete&lt;/code&gt; to delete the journal file after commit so that we will only have one file in the database directory.&lt;/p&gt;
&lt;p&gt;Since we want file based database, we are using &lt;code&gt;sqlite://main.db&lt;/code&gt; as connection string. For memory based database, we can use &lt;code&gt;sqlite::memory:&lt;/code&gt; as connection string.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;ConnectOptions&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Connection&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; sqlite&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;SqliteConnectOptions&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; std&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;FromStr&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[tokio&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;main]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; conn&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; SqliteConnectOptions&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_str&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;sqlite://main.db&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;create_if_missing&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;journal_mode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sqlite&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;SqliteJournalMode&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Delete&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;connect&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;Failed to connect to database&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // Create the users table if it doesn&amp;#39;t exist&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;query&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        &amp;quot;CREATE TABLE IF NOT EXISTS users (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            id INTEGER PRIMARY KEY AUTOINCREMENT,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            name TEXT NOT NULL,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            age INTEGER&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        )&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;    .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;execute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;mut&lt;/span&gt;&lt;span&gt; conn)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;    .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;    .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; _&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span&gt; conn&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;close&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;creating-connection-pool&quot;&gt;Creating Connection Pool&lt;/h2&gt;
&lt;p&gt;We will use &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/sqlx/latest/sqlx/sqlite/type.SqlitePoolOptions.html&quot;&gt;&lt;code&gt;SqlitePoolOptions&lt;/code&gt;&lt;/a&gt; to create a connection pool.&lt;/p&gt;
&lt;p&gt;We will create a helper function &lt;code&gt;db_conn&lt;/code&gt; to create a connection pool. This function will return a connection pool that can be used to interact with the database.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    Pool&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Sqlite&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    sqlite&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;SqliteConnectOptions&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; SqlitePoolOptions&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; std&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;FromStr&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; time&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Duration&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[tokio&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;main]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; conn&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; db_conn&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // Create the users table if it doesn&amp;#39;t exist&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;query&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        &amp;quot;CREATE TABLE IF NOT EXISTS users (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            id INTEGER PRIMARY KEY AUTOINCREMENT,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            name TEXT NOT NULL,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;            age INTEGER&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-8&quot;&gt;        )&amp;quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;    .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;execute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;conn)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;    .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;    .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; _&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span&gt; conn&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;close&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; db_conn&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Pool&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Sqlite&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; db_url&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;sqlite://main.db&amp;quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    SqlitePoolOptions&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;new&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;max_connections&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;20&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;idle_timeout&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_secs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;60&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;acquire_timeout&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_secs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;5&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;connect_with&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;            SqliteConnectOptions&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_str&lt;/span&gt;&lt;span&gt;(db_url)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;create_if_missing&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;journal_mode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sqlite&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;SqliteJournalMode&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Delete&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;using-oncecell-to-create-a-connection-pool&quot;&gt;Using OnceCell to create a connection pool&lt;/h2&gt;
&lt;p&gt;We can use &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/tokio/latest/tokio/sync/struct.OnceCell.html&quot;&gt;&lt;code&gt;OnceCell&lt;/code&gt;&lt;/a&gt; to create a connection pool. This will ensure that the connection pool is created only once and can be shared across multiple threads. So that we won’t to pass connection pool to every function, we can just use this helper function to get the connection pool and it will re-use the same one.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    Pool&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Sqlite&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    sqlite&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;SqliteConnectOptions&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; SqlitePoolOptions&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; std&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;FromStr&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; time&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Duration&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; tokio&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;OnceCell&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; DB_CONN&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; OnceCell&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Pool&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Sqlite&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; OnceCell&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;const_new&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; db_conn&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Pool&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Sqlite&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; db_url&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;sqlite://main.db&amp;quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;    DB_CONN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;get_or_init&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt; async&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;            SqlitePoolOptions&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;new&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;max_connections&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;20&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;idle_timeout&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_secs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;60&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;acquire_timeout&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_secs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;5&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;connect_with&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;                    SqliteConnectOptions&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_str&lt;/span&gt;&lt;span&gt;(db_url)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;create_if_missing&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;journal_mode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sqlite&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;SqliteJournalMode&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Delete&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;clone&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;handling-database-migrations&quot;&gt;Handling Database Migrations&lt;/h2&gt;
&lt;p&gt;We will use &lt;a rel=&quot;external&quot; href=&quot;https://github.com/launchbadge/sqlx/blob/main/sqlx-cli/README.md&quot;&gt;&lt;code&gt;sqlx-cli&lt;/code&gt;&lt;/a&gt; to handle migrations.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; install sqlx-cli&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create migration file for users table.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sqlx&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; migrate add users&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will create a migration file in &lt;code&gt;migrations&lt;/code&gt; directory with empty migration file for users table. Add the following content to the newly created migration file.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;-- Add migration script here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;CREATE TABLE&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; IF&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt; NOT EXISTS&lt;/span&gt;&lt;span&gt; users (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id &lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;INTEGER PRIMARY KEY&lt;/span&gt;&lt;span&gt; AUTOINCREMENT,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    name TEXT NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    age &lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;INTEGER&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Embed the migration file in the executable.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    Pool&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Sqlite&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    sqlite&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;SqliteConnectOptions&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; SqlitePoolOptions&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; std&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;FromStr&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; time&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Duration&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; tokio&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;OnceCell&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[tokio&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;main]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // this will make sure migrations are added to the executable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;migrate!&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;db_conn&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;Migrations went wrong :(&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; DB_CONN&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; OnceCell&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Pool&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Sqlite&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; OnceCell&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;const_new&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; db_conn&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Pool&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Sqlite&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; db_url&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;sqlite://main.db&amp;quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;    DB_CONN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;get_or_init&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt; async&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;            SqlitePoolOptions&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;new&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;max_connections&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;20&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;idle_timeout&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_secs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;60&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;acquire_timeout&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_secs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;5&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;connect_with&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;                    SqliteConnectOptions&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_str&lt;/span&gt;&lt;span&gt;(db_url)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;create_if_missing&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;journal_mode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sqlite&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;SqliteJournalMode&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Delete&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;clone&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;full-code-with-example-queries&quot;&gt;Full Code with Example Queries&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;main.rs&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    Pool&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Row&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Sqlite&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    prelude&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;FromRow&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    sqlite&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;SqliteConnectOptions&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; SqlitePoolOptions&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; std&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;FromStr&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; time&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Duration&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; tokio&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;OnceCell&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[tokio&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;main]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;migrate!&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;db_conn&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;❌ Migrations went wrong :(&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;query&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;INSERT INTO users (name, age) VALUES (?, ?)&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-4 z-i&quot;&gt; // Use ? for placeholders&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;bind&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;Alice&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;bind&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;30&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;execute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;db_conn&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; query&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;query&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;SELECT count(*) AS count FROM users&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;fetch_one&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;db_conn&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-18&quot;&gt;    println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;Count: {:?}&amp;quot;&lt;/span&gt;&lt;span&gt;, query&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;i64&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;str&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;count&amp;quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; users&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;query_as&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;&amp;lt;_,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; User&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;SELECT id, name, age FROM users&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;fetch_all&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;db_conn&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    for&lt;/span&gt;&lt;span&gt; user&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt; in&lt;/span&gt;&lt;span&gt; users {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-18&quot;&gt;        println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;Found user: {:?}&amp;quot;&lt;/span&gt;&lt;span&gt;, user);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; DB_CONN&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; OnceCell&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Pool&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Sqlite&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; OnceCell&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;const_new&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;async fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; db_conn&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Pool&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Sqlite&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; db_url&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;sqlite://main.db&amp;quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-7&quot;&gt;    DB_CONN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;get_or_init&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt; async&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;            SqlitePoolOptions&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;new&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;max_connections&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;20&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;idle_timeout&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_secs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;60&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;acquire_timeout&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_secs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;5&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;connect_with&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;                    SqliteConnectOptions&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_str&lt;/span&gt;&lt;span&gt;(db_url)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;create_if_missing&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;journal_mode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sqlx&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;sqlite&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;SqliteJournalMode&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Delete&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;                .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;unwrap&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;await&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;clone&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[derive(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Debug&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; FromRow&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; User&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; i64&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    age&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Option&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;i32&lt;/span&gt;&lt;span&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    </entry>
    <entry xml:lang="en">
        <title>Self Host PostgreSQL With TLS</title>
        <published>2025-02-03T00:00:00+00:00</published>
        <updated>2025-09-09T00:00:00+00:00</updated>
        <author>
          <name>Vivek Shukla</name>
        </author>
        <link rel="alternate" type="text/html" href="https://vshukla.com/tech/self-host-postgresql-with-tls/"/>
        <id>https://vshukla.com/tech/self-host-postgresql-with-tls/</id>
        <summary type="html">Complete tutorial on how to self-host PostgreSQL instance for production usage with TLS.</summary>
        <content type="html" xml:base="https://vshukla.com/tech/self-host-postgresql-with-tls/">&lt;p&gt;In this tutorial we will go through how to self-host PostgreSQL Database and setup TLS to securely connect.&lt;/p&gt;
&lt;h2 id=&quot;installing-postgresql&quot;&gt;Installing PostgreSQL&lt;/h2&gt;
&lt;p&gt;Postgres APT repository configuration:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; apt install&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -y&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; postgresql-common&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Install PostgreSQL 16&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; apt install postgresql-16&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After installing PostgreSQL, it creates a new user &lt;code&gt;postgres&lt;/code&gt;, which is the superuser of the database. We can switch to &lt;code&gt;postgres&lt;/code&gt; user in ubuntu to access postgresql command prompt:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -i -u&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; postgres&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now to create new user with passowrd and with privilege to create new db. It will ask you to enter your password, which will not be logged into history hence this is the recommended way to set password.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;createuser&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; your_db_user&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --pwprompt --createdb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can exit from &lt;code&gt;postgres&lt;/code&gt; account&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-14&quot;&gt;exit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We will add new user in our Ubuntu with the same name as the new user we created in postgresql. (Optional) Add &lt;code&gt;-m&lt;/code&gt; to create home directory for the user.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; useradd&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -s&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; /bin/bash your_db_user&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Accessing psql as the new user we just created. Since we do not have any database associated with our user therefore we are using ‘-d postgres’ to use postgres db for now.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -u&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; your_db_user psql&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -U&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; your_db_user&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -d&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; postgres&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create your database.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;CREATE&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; DATABASE your_db_name&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is how you can connect with your db if not already connected.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;\c&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; your_db_name&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;setting-up-ssl&quot;&gt;Setting Up SSL&lt;/h2&gt;
&lt;p&gt;It’s important that we secure our communication with the database while accessing it remotely. We are going to setup SSL certificate using &lt;code&gt;certbot&lt;/code&gt; from LetsEncrypt.&lt;/p&gt;
&lt;p&gt;Install certbot&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; snap install core&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; snap refresh core&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; apt-get remove certbot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; snap install&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --classic&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; certbot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; ln&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -s&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; /snap/bin/certbot /usr/bin/certbot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Obtain certificate&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; certbot certonly&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --standalone -d&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; psql.example.com&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Find PostgreSQL data directory&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -u&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; postgres psql&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -U&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; postgres&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -c&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;#39;SHOW data_directory&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create a renewal hook file&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; nano /etc/letsencrypt/renewal-hooks/deploy/postgresql.deploy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Paste the following&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;umask 0177&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;DOMAIN=psql.example.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;DATA_DIR=/var/lib/postgresql/16/main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cp /etc/letsencrypt/live/$DOMAIN/fullchain.pem $DATA_DIR/server.crt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cp /etc/letsencrypt/live/$DOMAIN/privkey.pem $DATA_DIR/server.key&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;chown postgres:postgres $DATA_DIR/server.crt $DATA_DIR/server.key&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Save and exit the file.&lt;/p&gt;
&lt;p&gt;Give file executable permission&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; chmod +x /etc/letsencrypt/renewal-hooks/deploy/postgresql.deploy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Get the path of PostgreSQL configuration file&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -u&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; postgres psql&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -U&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; postgres&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -c&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;#39;SHOW config_file&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Open the file in edit mode and update the SSL section of the file as below:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; nano /etc/postgresql/16/main/postgresql.conf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ssl = on&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ssl_cert_file = &amp;#39;server.crt&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ssl_key_file = &amp;#39;server.key&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ssl_prefer_server_ciphers = on&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Locate the Connection Settings section and verify the listen_address is to * for all addresses. Make sure the line is not commented out.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;listen_addresses = &amp;#39;*&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Edit &lt;code&gt;pg_hba.conf&lt;/code&gt; file which is in the same dir as config file:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; nano /etc/postgresql/16/main/pg_hba.conf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add the following line to enable connection over ssl for any user and database:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# TYPE DATABASE USER ADDRESS METHOD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hostssl all all 0.0.0.0/0 scram-sha-256&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hostssl all all ::/0 scram-sha-256&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Although in above config it’s shown to allow connection from all IPv4 and IPv6 addresses, however from the security point of view only allow the ip address of your connecting machine (client).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Renew the SSL certificate&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; certbot renew&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --force-renewal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Restart PostgreSQL&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;sudo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; service postgresql restart&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Connect to your db remotely&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;psql&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -d&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;dbname=your_db_name sslmode=require&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -h&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; psql.example.com&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -U&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; your_db_user&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    </entry>
    <entry xml:lang="en">
        <title>AES Encryption in Rust</title>
        <published>2024-03-22T00:00:00+00:00</published>
        <updated>2024-08-15T00:00:00+00:00</updated>
        <author>
          <name>Vivek Shukla</name>
        </author>
        <link rel="alternate" type="text/html" href="https://vshukla.com/tech/aes-encryption-rust/"/>
        <id>https://vshukla.com/tech/aes-encryption-rust/</id>
        <summary type="html">We will use aes-gcm crate from RustCrypto to add AES encryption in our Rust code. In this tutorial we will focus on AES-256.</summary>
        <content type="html" xml:base="https://vshukla.com/tech/aes-encryption-rust/">&lt;p&gt;&lt;strong&gt;What we will cover&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Brief explanation of AES encryption&lt;/li&gt;
&lt;li&gt;AES-256 encryption and decryption&lt;/li&gt;
&lt;li&gt;Full Rust code for AES-256 encryption&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;AES stands for Advanced Encryption Standard. It is a type of Symmetric key encryption algorithm, which means the same key is used for encryption and decryption.&lt;/p&gt;
&lt;p&gt;In this tutorial we will use &lt;a rel=&quot;external&quot; href=&quot;https://crates.io/crates/aes-gcm&quot;&gt;aes-gcm&lt;/a&gt; crate from &lt;a rel=&quot;external&quot; href=&quot;https://github.com/RustCrypto&quot;&gt;Rust Crypto&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are 3 type of AES encryption: AES-128, AES-192 and AES-256, which represents encryption &lt;em&gt;Key&lt;/em&gt; of length 128 bit (16 byte), 192 bit (24 byte) and 256 bit (32 byte) respectively.&lt;/p&gt;
&lt;p&gt;Both are pretty secure and hard to crack but for obvious reasons AES-256 is the most secure one.&lt;/p&gt;
&lt;p&gt;AES encryption requires key and nonce (for gcm variant) to encrypt/decrypt the data.&lt;/p&gt;
&lt;h2 id=&quot;key&quot;&gt;Key&lt;/h2&gt;
&lt;p&gt;Key means encryption key, which is used to encrypt and decrypt the data. Length of the key matters, AES-128 requires key of 16 byte and AES-256 requires key of 32 byte.&lt;/p&gt;
&lt;p&gt;For the simplicity from now on we will focus on AES-256, but the core concept is similar even for AES-128.&lt;/p&gt;
&lt;p&gt;Key is byte array of length 32, where each element is of 1 byte. We can either generate the key using aes-gcm crate itself or we can use our own key. It’s prefferable to use our own key, so let’s see it in action:&lt;/p&gt;
&lt;p&gt;Create new &lt;em&gt;crypto&lt;/em&gt; project and add aes-gcm crate.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; new crypto&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; add aes-gcm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;main.rs&lt;/em&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; aes_gcm&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    aead&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Aead&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; AeadCore&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; KeyInit&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; OsRng&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    Aes256Gcm&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Key&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Nonce&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; key_str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;thiskeystrmustbe32charlongtowork&amp;quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Aes256Gcm&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_slice&lt;/span&gt;&lt;span&gt;(key_str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;as_bytes&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s important that the string/str used for key must be 32 char long, since AES-256 requires key length of 32 byte.&lt;/p&gt;
&lt;p&gt;Note: If you want to use key string of any length (less or more than 32), you can use Key Derivation Function to generate secure 32 byte long key. Argon2, PBKDF2 are some of the fitting choices for this.&lt;/p&gt;
&lt;h2 id=&quot;nonce&quot;&gt;Nonce&lt;/h2&gt;
&lt;p&gt;Nonce means “number used only once”. It is an array of random numbers (type: u8) that is unique to each operation. For AES encryption the required size of Nonce is 12 byte.&lt;/p&gt;
&lt;p&gt;For each encryption operation the same key can be used but the &lt;u&gt;Nonce must be unique&lt;/u&gt;, so we generate Nonce each time we encrypt data.&lt;/p&gt;
&lt;p&gt;Since nonce is required to decrypt the data, it is stored along with the encrypted data itself.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;let&lt;/span&gt;&lt;span&gt; nonce&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Aes256Gcm&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;generate_nonce&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; OsRng&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;encryption&quot;&gt;Encryption&lt;/h2&gt;
&lt;p&gt;We will create &lt;code&gt;encrypt&lt;/code&gt; function which will take key_str and plaintext string. This will make our code more readable and easy to use.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; aes_gcm&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    aead&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Aead&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; AeadCore&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; KeyInit&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; OsRng&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    Aes256Gcm&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Key&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Nonce&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; plaintext&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;vivekshuk.la&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; key_str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;thiskeystrmustbe32charlongtowork&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; encrypted_data&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; encrypt&lt;/span&gt;&lt;span&gt;(key_str, plaintext);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; encrypt&lt;/span&gt;&lt;span&gt;(key_str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;, plaintext&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Vec&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;u8&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Aes256Gcm&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_slice&lt;/span&gt;&lt;span&gt;(key_str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;as_bytes&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; nonce&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Aes256Gcm&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;generate_nonce&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; OsRng&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; cipher&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Aes256Gcm&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;new&lt;/span&gt;&lt;span&gt;(key);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; ciphered_data&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span&gt; cipher&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;encrypt&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;nonce, plaintext&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;as_bytes&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;failed to encrypt&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // combining nonce and encrypted data together&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // for storage purpose&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; encrypted_data&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Vec&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;u8&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span&gt; nonce&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_vec&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    encrypted_data&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;extend_from_slice&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;ciphered_data);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    encrypted_data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;creating instance of &lt;code&gt;Aes256Gcm&lt;/code&gt; with our encryption key, which will be used for encryption.&lt;/li&gt;
&lt;li&gt;we need to convert our plaintext from string to byte array for the &lt;code&gt;encrypt&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;combine nonce and ciphered_data together&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;decryption&quot;&gt;Decryption&lt;/h2&gt;
&lt;p&gt;Here first we will separate out nonce and ciphered data by splitting encrypted data vector at 12th position (because we used nonce of length 12).&lt;/p&gt;
&lt;p&gt;Then we create Nonce instance from our nonce array that we got.&lt;/p&gt;
&lt;p&gt;After decrypting we will get byte array which we can pass to &lt;code&gt;String::from_utf8&lt;/code&gt; function to create our original string value back.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; decrypt&lt;/span&gt;&lt;span&gt;(key_str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;, encrypted_data&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Vec&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;u8&lt;/span&gt;&lt;span&gt;&amp;gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Aes256Gcm&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_slice&lt;/span&gt;&lt;span&gt;(key_str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;as_bytes&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; (nonce_arr, ciphered_data)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span&gt; encrypted_data&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;split_at&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;12&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; nonce&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Nonce&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_slice&lt;/span&gt;&lt;span&gt;(nonce_arr);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; cipher&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Aes256Gcm&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;new&lt;/span&gt;&lt;span&gt;(key);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; plaintext&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span&gt; cipher&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;decrypt&lt;/span&gt;&lt;span&gt;(nonce, ciphered_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;failed to decrypt data&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    String&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_utf8&lt;/span&gt;&lt;span&gt;(plaintext)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;failed to convert vector of bytes to string&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;storage&quot;&gt;Storage&lt;/h2&gt;
&lt;p&gt;There is one issue you might encounter that the encrypt function will give out Vector of numbers (u8), which is not easy to store. Of course you might convert it to string by joining them with comma but it’s not good solution.&lt;/p&gt;
&lt;p&gt;To solve this we can convert our vector of numbers to hex string, this will make storage and operation much easier for us.&lt;/p&gt;
&lt;p&gt;Let’s install &lt;code&gt;hex&lt;/code&gt; crate for this.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;cargo&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; add hex&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;hex&lt;/code&gt; crate provides &lt;code&gt;encode&lt;/code&gt; (vec to string) and &lt;code&gt;decode&lt;/code&gt; (string to vec) function for easy conversion.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;let&lt;/span&gt;&lt;span&gt; encoded_string&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; hex&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;encode&lt;/span&gt;&lt;span&gt;(encrypted_data);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;let&lt;/span&gt;&lt;span&gt; decoded_vec&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; hex&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;decode&lt;/span&gt;&lt;span&gt;(encoded_string)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;    .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;failed to decode hex string into vec&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;full-code&quot;&gt;Full Code&lt;/h2&gt;
&lt;p&gt;In this final version we have made few changes to incorporate &lt;code&gt;hex&lt;/code&gt; conversion within the &lt;code&gt;encrypt&lt;/code&gt; and &lt;code&gt;decrypt&lt;/code&gt; function itself.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; aes_gcm&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    aead&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Aead&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; AeadCore&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; KeyInit&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; OsRng&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    Aes256Gcm&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Key&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Nonce&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; plaintext&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;vivekshuk.la&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; key_str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;thiskeystrmustbe32charlongtowork&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_string&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; encrypted_data&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; encrypt&lt;/span&gt;&lt;span&gt;(key_str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;clone&lt;/span&gt;&lt;span&gt;(), plaintext);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-18&quot;&gt;    println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;encrypted_data: {:?}&amp;quot;&lt;/span&gt;&lt;span&gt;, encrypted_data&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;clone&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; original&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; decrypt&lt;/span&gt;&lt;span&gt;(key_str, encrypted_data);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-18&quot;&gt;    println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;original: {:?}&amp;quot;&lt;/span&gt;&lt;span&gt;, original);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; encrypt&lt;/span&gt;&lt;span&gt;(key_str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;, plaintext&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Aes256Gcm&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_slice&lt;/span&gt;&lt;span&gt;(key_str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;as_bytes&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; nonce&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Aes256Gcm&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;generate_nonce&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;z-17&quot;&gt;mut&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; OsRng&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; cipher&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Aes256Gcm&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;new&lt;/span&gt;&lt;span&gt;(key);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; ciphered_data&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span&gt; cipher&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;encrypt&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;nonce, plaintext&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;as_bytes&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;failed to encrypt&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // combining nonce and encrypted data together&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;    // for storage purpose&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; encrypted_data&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Vec&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;u8&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span&gt; nonce&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;to_vec&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    encrypted_data&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;extend_from_slice&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;ciphered_data);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    hex&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;encode&lt;/span&gt;&lt;span&gt;(encrypted_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt; decrypt&lt;/span&gt;&lt;span&gt;(key_str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;, encrypted_data&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; String&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; encrypted_data&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; hex&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;decode&lt;/span&gt;&lt;span&gt;(encrypted_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;failed to decode hex string into vec&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Key&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;Aes256Gcm&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_slice&lt;/span&gt;&lt;span&gt;(key_str&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;as_bytes&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; (nonce_arr, ciphered_data)&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span&gt; encrypted_data&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;split_at&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt;12&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; nonce&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Nonce&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_slice&lt;/span&gt;&lt;span&gt;(nonce_arr);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; cipher&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; Aes256Gcm&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;new&lt;/span&gt;&lt;span&gt;(key);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-17&quot;&gt;    let&lt;/span&gt;&lt;span&gt; plaintext&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; =&lt;/span&gt;&lt;span&gt; cipher&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;decrypt&lt;/span&gt;&lt;span&gt;(nonce, ciphered_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;failed to decrypt data&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;    String&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;from_utf8&lt;/span&gt;&lt;span&gt;(plaintext)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-16&quot;&gt;        .&lt;/span&gt;&lt;span class=&quot;z-18&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;failed to convert vector of bytes to string&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    </entry>
    <entry xml:lang="en">
        <title>Python Poetry Cheat Sheet</title>
        <published>2023-10-30T00:00:00+00:00</published>
        <updated>2023-10-30T00:00:00+00:00</updated>
        <author>
          <name>Vivek Shukla</name>
        </author>
        <link rel="alternate" type="text/html" href="https://vshukla.com/tech/poetry-cheat-sheet/"/>
        <id>https://vshukla.com/tech/poetry-cheat-sheet/</id>
        <summary type="html">Poetry is an amazing tool for dependancy management in Python, it solves a lot of problems of pip. Here in this Poetry Cheat Sheet we have useful commands that we may need frequently.</summary>
        <content type="html" xml:base="https://vshukla.com/tech/poetry-cheat-sheet/">&lt;p&gt;Poetry is an amazing tool for dependancy management in Python, it solves a lot of problems of pip. Here in this Poetry Cheat Sheet we have useful commands that we may need frequently.&lt;/p&gt;
&lt;h2 id=&quot;initializing&quot;&gt;Initializing&lt;/h2&gt;
&lt;h3 id=&quot;new-project&quot;&gt;New Project&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; new poetry-demo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;in-pre-existing-directory&quot;&gt;In Pre-existing Directory&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-14&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; pre-existing-project&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; init&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;environments&quot;&gt;Environments&lt;/h2&gt;
&lt;h3 id=&quot;displaying-the-environment-information&quot;&gt;Displaying the environment information&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; env info&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;using-your-own-virtual-environment&quot;&gt;Using your own virtual environment&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Keep virtualenv in project root&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;More on this &lt;a rel=&quot;external&quot; href=&quot;https://python-poetry.org/docs/configuration/#virtualenvsin-project&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This will also let VS Code discover your porject’s virtual env.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; config virtualenvs.in-project&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; true&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --local&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;External virtual environment management&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Poetry will detect and respect an existing virtual environment that has been externally activated. This is a powerful mechanism that is intended to be an alternative to Poetry’s built-in, simplified environment management.&lt;/p&gt;
&lt;p&gt;You can use &lt;a href=&quot;/tech/pyenv-cheat-sheet/&quot;&gt;pyenv&lt;/a&gt; to create external virtual environment.&lt;/p&gt;
&lt;h3 id=&quot;switching-between-environments&quot;&gt;Switching between environments&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; env use /full/path/to/python&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; env use&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; 3.7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; env use system&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;listing-the-environments-associated-with-the-project&quot;&gt;Listing the environments associated with the project&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; env list&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;deleting-the-environments&quot;&gt;Deleting the environments&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; env remove /full/path/to/python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; env remove python3.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; env remove&lt;/span&gt;&lt;span class=&quot;z-11&quot;&gt; 3.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; env remove test-O3eWbxRl-py3.7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use the &lt;strong&gt;&lt;code&gt;--all&lt;/code&gt;&lt;/strong&gt; option to delete all virtual environments at once.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; env remove&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --all&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;dependencies&quot;&gt;Dependencies&lt;/h2&gt;
&lt;h3 id=&quot;add-new-dependency&quot;&gt;Add new dependency&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; add&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;package nam&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;removing-dependency&quot;&gt;Removing dependency&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; remove&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;package nam&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;installing-dependencies&quot;&gt;Installing dependencies&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;updating-dependencies-to-their-latest-versions&quot;&gt;Updating dependencies to their latest versions&lt;/h3&gt;
&lt;p&gt;This will fetch the latest matching versions (according to your &lt;strong&gt;&lt;code&gt;pyproject.toml&lt;/code&gt;&lt;/strong&gt; file) and update the lock file with the new versions. (This is equivalent to deleting the &lt;strong&gt;&lt;code&gt;poetry.lock&lt;/code&gt;&lt;/strong&gt; file and running &lt;strong&gt;&lt;code&gt;install&lt;/code&gt;&lt;/strong&gt; again.)&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; update&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;adding-a-dependency-to-a-group&quot;&gt;Adding a dependency to a group&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; add pytest&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --group&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; test&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; add isort&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --group&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; dev&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;installing-group-dependencies&quot;&gt;Installing group dependencies&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;without&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; install&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --without&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; test, docs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;with&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; install&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --with&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; docs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;only&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; install&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --only&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; main&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;removing-dependencies-from-a-group&quot;&gt;Removing dependencies from a group&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; remove mkdocs&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --group&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; docs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;synchronizing-dependencies&quot;&gt;Synchronizing dependencies&lt;/h3&gt;
&lt;p&gt;Poetry supports what’s called dependency synchronization. Dependency synchronization ensures that the locked dependencies in the &lt;strong&gt;&lt;code&gt;poetry.lock&lt;/code&gt;&lt;/strong&gt; file are the only ones present in the environment, removing anything that’s not necessary.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; install&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --sync&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; install&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --without&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; dev&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --sync&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; install&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --with&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; docs&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --sync&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; install&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --only&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; dev&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;export&quot;&gt;Export&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; export&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -f&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; requirements.txt&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --output&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; requirements.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--format (-f)&lt;/code&gt;&lt;/strong&gt;: The format to export to (default: &lt;strong&gt;&lt;code&gt;requirements.txt&lt;/code&gt;&lt;/strong&gt;). Currently, only &lt;strong&gt;&lt;code&gt;constraints.txt&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;requirements.txt&lt;/code&gt;&lt;/strong&gt; are supported.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--output (-o)&lt;/code&gt;&lt;/strong&gt;: The name of the output file. If omitted, print to standard output.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--extras (-E)&lt;/code&gt;&lt;/strong&gt;: Extra sets of dependencies to include.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--without&lt;/code&gt;&lt;/strong&gt;: The dependency groups to ignore.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--with&lt;/code&gt;&lt;/strong&gt;: The optional dependency groups to include.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--only&lt;/code&gt;&lt;/strong&gt;: The only dependency groups to include.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--without-hashes&lt;/code&gt;&lt;/strong&gt;: Exclude hashes from the exported file.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--without-urls&lt;/code&gt;&lt;/strong&gt;: Exclude source repository urls from the exported file.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--with-credentials&lt;/code&gt;&lt;/strong&gt;: Include credentials for extra indices.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;packaging&quot;&gt;Packaging&lt;/h2&gt;
&lt;h3 id=&quot;build&quot;&gt;Build&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; build&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;publish&quot;&gt;Publish&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;poetry&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; publish&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;configuration&quot;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;You can find all the &lt;a rel=&quot;external&quot; href=&quot;https://python-poetry.org/docs/configuration/&quot;&gt;configuration options here&lt;/a&gt;.&lt;/p&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>pyenv Cheat Sheet</title>
        <published>2023-10-22T00:00:00+00:00</published>
        <updated>2023-10-22T00:00:00+00:00</updated>
        <author>
          <name>Vivek Shukla</name>
        </author>
        <link rel="alternate" type="text/html" href="https://vshukla.com/tech/pyenv-cheat-sheet/"/>
        <id>https://vshukla.com/tech/pyenv-cheat-sheet/</id>
        <summary type="html">pyenv is Python version management tool, it lets you easily switch between multiple versions of Python. Here is the pyenv cheat sheet of all the basic commands list.</summary>
        <content type="html" xml:base="https://vshukla.com/tech/pyenv-cheat-sheet/">&lt;p&gt;Here is the pyenv cheat sheet of all the basic commands list.&lt;/p&gt;
&lt;h2 id=&quot;what-is-pyenv&quot;&gt;What is pyenv&lt;/h2&gt;
&lt;p&gt;pyenv is &lt;a href=&quot;/tags/python/&quot;&gt;Python&lt;/a&gt; version management tool, it lets you easily switch between multiple versions of Python.&lt;/p&gt;
&lt;h2 id=&quot;what-it-does&quot;&gt;What it does&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Lets you change the global Python version on a per-user basis.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provides support for per-project Python versions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Allows you to override the Python version with an environment variable.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;list-available-python-versions-to-install&quot;&gt;List available python versions to install&lt;/h2&gt;
&lt;p&gt;This will list all the available version of python&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;pyenv&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; install&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --list&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can filter it using grep. Here we are filtering list by python version:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;pyenv&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; install&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; --list&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; |&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt; grep&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot; 3\.11&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;installing-python-version&quot;&gt;Installing Python Version&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;pyenv&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; install&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;versio&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;add &lt;code&gt;-v&lt;/code&gt; flag to see install progress output&lt;/p&gt;
&lt;h2 id=&quot;list-installed-python-versions&quot;&gt;List Installed Python Versions&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;pyenv&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; versions&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Astrick (*) indicate current active version.&lt;/p&gt;
&lt;h2 id=&quot;see-list-of-all-pyenv-commands&quot;&gt;See List Of All pyenv Commands&lt;/h2&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;pyenv&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; commands&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;activating-python-version&quot;&gt;Activating Python Version&lt;/h2&gt;
&lt;h3 id=&quot;global&quot;&gt;global&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Sets the given version as global python version.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It overrides system’s default python version.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;pyenv&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; global&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;versio&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;local&quot;&gt;local&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Use it to set directory / project specific python version.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It can override python version set by &lt;code&gt;global&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;pyenv&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; local&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;versio&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;shell&quot;&gt;shell&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Sets shell specific python version.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The python version stays active until shell has been closed or by using &lt;code&gt;--unset&lt;/code&gt; flag.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It can override python version set by &lt;code&gt;local&lt;/code&gt; and &lt;code&gt;global&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;pyenv&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; shell&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;versio&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;virtual-environments&quot;&gt;Virtual Environments&lt;/h2&gt;
&lt;h3 id=&quot;create-virtual-environments&quot;&gt;Create Virtual Environments&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;pyenv&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; virtualenv&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;versio&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;gt; &amp;lt;&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;env_nam&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;set-virtual-environment-as-default-for-dir-project&quot;&gt;Set virtual environment as default for dir/project&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;pyenv&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; local&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;env_nam&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;activate-virtual-environment&quot;&gt;Activate Virtual Environment&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;pyenv&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; activate&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;env_nam&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;deactivate-virtual-environment&quot;&gt;Deactivate Virtual Environment&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;pyenv&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; deactivate&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;recommended-reading-materials&quot;&gt;Recommended Reading Materials&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Official Page of &lt;a rel=&quot;external&quot; href=&quot;https://github.com/pyenv/pyenv&quot;&gt;pyenv&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Real Python: &lt;a rel=&quot;external&quot; href=&quot;https://realpython.com/intro-to-pyenv/#exploring-pyenv-commands&quot;&gt;Managing Multiple Python Versions With pyenv&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    <entry xml:lang="en">
        <title>Automate Postgres Database Backup and Upload to S3</title>
        <published>2023-10-20T00:00:00+00:00</published>
        <updated>2023-10-20T00:00:00+00:00</updated>
        <author>
          <name>Vivek Shukla</name>
        </author>
        <link rel="alternate" type="text/html" href="https://vshukla.com/tech/automate-postgres-database-backup-and-upload/"/>
        <id>https://vshukla.com/tech/automate-postgres-database-backup-and-upload/</id>
        <summary type="html">In this tutorial we will create a bash script to automate postgres database backup from a docker container and native postgres installation then upload to S3 based storage system.</summary>
        <content type="html" xml:base="https://vshukla.com/tech/automate-postgres-database-backup-and-upload/">&lt;p&gt;Database is a very critical system for an application. To prepare for any disaster we all must take regular backups of our database.&lt;/p&gt;
&lt;p&gt;In this tutorial we will create a bash script to automate &lt;a href=&quot;/tech/postgres-database-backup-from-docker-container/&quot;&gt;postgres database backup from a docker container&lt;/a&gt; and native postgres installation then upload to S3 based storage system. We will use crontab to create a &lt;a rel=&quot;external&quot; href=&quot;https://daestro.com/blog/cron-jobs&quot;&gt;cron job&lt;/a&gt; that will run everyday at 12 PM.&lt;/p&gt;
&lt;h2 id=&quot;what-we-will-cover&quot;&gt;What we will cover&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Write db backup automation script for docker and non-docker based system&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Upload backup file to AWS S3&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Setup the cron job for daily backup&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;steps&quot;&gt;Steps&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Move to your project folder, where docker-compose.yml is.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Take the database backup in container&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy the backup file from container filesystem to our desired location&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Delete the backup file inside the container&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Upload backup file to S3&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Delete the local backup file&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Code snippet below covers step 1 to 4. But it is not optimal, later we will make modification so that we can easily automate it and make it re-usable.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-14&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; project_dir&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; compose exec db_service_name sh&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -c&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;pg_dump -U db_user db_name &amp;gt; filename&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; compose cp db_service_name:filename destination/filename&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; compose exec db_service_name rm filename&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;upload-to-s3&quot;&gt;Upload to S3&lt;/h2&gt;
&lt;p&gt;To upload file to S3, we need to have aws cli installed, you can follow &lt;a rel=&quot;external&quot; href=&quot;https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html&quot;&gt;this guide from AWS docs to install awscli&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After installing awscli, you need to run &lt;code&gt;aws configure&lt;/code&gt; and provide your key id and key secret. You can use any S3 based storage system here.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;aws s3 cp filename s3&lt;/span&gt;&lt;span class=&quot;z-9&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;//&lt;/span&gt;&lt;span&gt;your&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;-&lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you are using some other S3 based storage system then you’ll have to provide custom &lt;code&gt;--endpoint-url&lt;/code&gt; argument here, make sure you read the respective docs for this.&lt;/p&gt;
&lt;h2 id=&quot;full-script&quot;&gt;Full Script&lt;/h2&gt;
&lt;p&gt;We have laid out all the steps and code to accomplish that, now let’s modify in such a way that we can easily automate it and make it reusable.&lt;/p&gt;
&lt;p&gt;The filename is created based on the current datetime of the system, so that we can avoid ambiguity and exactly know how old is the backup file.&lt;/p&gt;
&lt;h3 id=&quot;for-docker-compose&quot;&gt;For docker compose&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;#!/bin/bash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;############## ✅ Update These Values ##################&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;directory&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;your-project-dir&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;home&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;/home/&amp;lt;user&amp;gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;db_service_name&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;db&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;db_user&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;db_user&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;db_name&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;db_name&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;#####################################################&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;############ 🔴 CHANGE WITH CAUTION 🔴 #############&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;date&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;=&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; +&amp;quot;%Y-%m-%d-%H:%M:%S&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;filename&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;=&lt;/span&gt;&lt;span&gt;$db_name&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;_&amp;quot;&lt;/span&gt;&lt;span&gt;$date&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;.sql&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-14&quot;&gt;cd&lt;/span&gt;&lt;span&gt; $home&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-14&quot;&gt;cd&lt;/span&gt;&lt;span&gt; $directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; compose exec&lt;/span&gt;&lt;span&gt; $db_service_name&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; sh&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -c&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;quot;pg_dump -U &lt;/span&gt;&lt;span&gt;$db_user $db_name&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; &amp;gt; &lt;/span&gt;&lt;span&gt;$filename&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; compose cp&lt;/span&gt;&lt;span&gt; $db_service_name&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;:&lt;/span&gt;&lt;span&gt;$filename $home&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span&gt;$filename&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;docker&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; compose exec&lt;/span&gt;&lt;span&gt; $db_service_name&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; rm&lt;/span&gt;&lt;span&gt; $filename&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-14&quot;&gt;cd&lt;/span&gt;&lt;span&gt; $home&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;#####################################################&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;#####################################################&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;############## ✅ CAN CHANGE BELOW ##################&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;aws&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; s3 cp&lt;/span&gt;&lt;span&gt; $filename&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; s3://your-bucket&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;rm&lt;/span&gt;&lt;span&gt; $filename&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At the top, you’ve to update variable values based on your project and directory structure, and the main code will use that to backup the database.&lt;/p&gt;
&lt;p&gt;At the end of script, we have aws command to copy the backup file to S3, here you need to update bucket name and if you are using other S3 storage provider (other than AWS), then &lt;code&gt;--endpoint-url&lt;/code&gt; argument with appropriate value.&lt;/p&gt;
&lt;h3 id=&quot;for-native-postgres-installation&quot;&gt;For Native Postgres Installation&lt;/h3&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;#!/bin/bash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;############## ✅ Update These Values ##################&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;home&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;/home/&amp;lt;user&amp;gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;db_user&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;db_user&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;db_name&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;db_name&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;#####################################################&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;############ 🔴 CHANGE WITH CAUTION 🔴 ##############&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;date&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;=&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span class=&quot;z-3&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; +&amp;quot;%Y-%m-%d-%H:%M:%S&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;filename&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt;=&lt;/span&gt;&lt;span&gt;$db_name&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;_&amp;quot;&lt;/span&gt;&lt;span&gt;$date&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt;&amp;quot;.sql&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;ch&lt;/span&gt;&lt;span&gt; $home&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;pg_dump&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -U&lt;/span&gt;&lt;span&gt; $db_user $db_name&lt;/span&gt;&lt;span class=&quot;z-16&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span&gt; $filename&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;#####################################################&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-4 z-i&quot;&gt;############## ✅ CAN CHANGE BELOW ##################&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;aws&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; s3 cp&lt;/span&gt;&lt;span&gt; $filename&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; s3://urlify-db-backup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;rm&lt;/span&gt;&lt;span&gt; $filename&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When running pg_dump in the native installation, there are two ways postgres will try to authenticate the user.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.postgresql.org/docs/current/auth-peer.html&quot;&gt;Peer based authentication&lt;/a&gt;: It will check if the current user (system logged in user) is same as user passed to pg_dump.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If peer auth fails then postgres looks for &lt;code&gt;.pgpass&lt;/code&gt; file in home directory for the password.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If both fails then it might ask for password.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, make sure you use 1st method and run the script on the same user as the one passed to pg_dump.&lt;/p&gt;
&lt;h2 id=&quot;setup-cron-job&quot;&gt;Setup Cron Job&lt;/h2&gt;
&lt;p&gt;To automate backup and upload of our database, we will use crontab. It comes built-in with almost all the Linux distros and are very easy to setup.&lt;/p&gt;
&lt;p&gt;Give your script executable permission:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;chmod&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; +x db_backup.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Open crontab:&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;crontab&lt;/span&gt;&lt;span class=&quot;z-7&quot;&gt; -e&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will open up crontab in your prefered choice of editor. Use the below statement to run the backup script everyday at 12 PM.&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0 12 * * * /home/&amp;lt;user&amp;gt;/db_backup.sh &amp;gt;&amp;gt; cron.log 2&amp;gt;&amp;amp;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create cron.log file&lt;/p&gt;
&lt;pre class=&quot;giallo z-code&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-3&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;z-8&quot;&gt; cron.log&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use full path if cron.log is not in current user’s home folder.&lt;/p&gt;
</content>
    </entry>
</feed>
