<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title></title>
        <link>https://www.mysteriouspants.com</link>
        <description></description>
        <generator>Zola</generator>
        <language>en</language>
        <atom:link href="https://www.mysteriouspants.com/rss.xml" rel="self" type="application/rss+xml"/>
        <lastBuildDate>Wed, 22 Jan 2020 00:00:00 +0000</lastBuildDate>
        
            <item>
                <title>From Excel to TSV to Rust</title>
                <pubDate>Wed, 22 Jan 2020 00:00:00 +0000</pubDate>
                <link>https://www.mysteriouspants.com/blog/xlsx-2-tsv-2-rs/</link>
                <guid>https://www.mysteriouspants.com/blog/xlsx-2-tsv-2-rs/</guid>
                <description>&lt;p&gt;I&#x27;m trying to build a simple card game, but that&#x27;s not even the horrifying part
of this story. The horrifying part is that I&#x27;m keeping my data in Microsoft
Excel.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s perfect! It flattens the data into something that can be more easily
expressed as an object, and the relationships between cards are easy to model.
Should one card always be 20% more expensive than another, or half as expensive?
Easy solution: use an Excel formula. Spreadsheets were built for this. But
reading a spreadsheet from a game is madness.&lt;&#x2F;p&gt;
&lt;p&gt;Initially I exported the spreadsheet as Tab-separated Values (TSV), a simple
format that obeys CSV rules and Excel can export natively. This happily reduced
the problem to reading TSV, but as I wrote a Rust parser for reading that TSV
there were enough unwraps and error handling occurring that I decided it would
be easier to move all this error-prone part further back in my asset pipeline.&lt;&#x2F;p&gt;
&lt;p&gt;So I decided to turn TSV directly into a &lt;code&gt;.rs&lt;&#x2F;code&gt; file. This is the madness, the
horrifying part which is why someone ought to take my keyboard away.&lt;&#x2F;p&gt;
&lt;p&gt;My go-to language for hacky things is Ruby, so I wrote a small Ruby script which
can read the TSV and then echo it back out using an ERB template to turn it into
Rust code.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;# tsv2rs.rb
#!ruby

require &#x27;csv&#x27;
require &#x27;erb&#x27;

TSV=&#x27;ARCOMAGE_CARDS.txt&#x27;
RST=&#x27;src&#x2F;cards.rs.erb&#x27;
RS =&#x27;src&#x2F;cards.rs&#x27;

def value_or_default(value, default)
  if value == nil or value.empty?; default; else value; end
end

File.new(RS, File::CREAT|File::TRUNC|File::RDWR, 0644)
    .write ERB.new(File.read(RST)).result(binding)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s very simple, aside from the helper function &lt;code&gt;value_or_default&lt;&#x2F;code&gt; it&#x27;s just
two lines: open a file, then write out the result.&lt;&#x2F;p&gt;
&lt;p&gt;The ERB template is where frightening things happen, where we write code which
writes code. But it&#x27;s not that scary, actually. I want something static, but
also in a &lt;code&gt;Vec&lt;&#x2F;code&gt;, so &lt;code&gt;lazy_static&lt;&#x2F;code&gt; showed up. After that it&#x27;s very simple Rust
constructors.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;use lazy_static::lazy_static;
use crate::card::*;

lazy_static! {
  pub static ref CARDS: Vec&amp;lt;Card&amp;gt; = vec![&amp;lt;%
  first = true
  CSV.foreach(TSV, col_sep: &amp;quot;\t&amp;quot;) do |row|
    # skips header rows, assumes your first column is always a number
    next unless row.first.match? &#x2F;^[0-9]+$&#x2F;
  %&amp;gt;
  &amp;lt;% unless first %&amp;gt;,&amp;lt;% end %&amp;gt;
  &amp;lt;% first = false %&amp;gt;
  Card {
    atlas_row: &amp;lt;%= row[0] %&amp;gt;,
    atlas_col: &amp;lt;%= row[1] %&amp;gt;,
    category: Category::&amp;lt;%= row[2].capitalize %&amp;gt;,
    card_name: &amp;quot;&amp;lt;%= row[3] %&amp;gt;&amp;quot;.to_owned(),
    cost: PlayCost {
      bricks: &amp;lt;%= value_or_default row[4], 0 %&amp;gt;,
      ...
    }
    ...
  }
  &amp;lt;% end %&amp;gt;
  ];
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There&#x27;s some complexity in keeping track of the first time the loop has been
iterated over so a comma can be printed between items, but otherwise it&#x27;s plain
ERB that shouldn&#x27;t look terribly unfamiliar to anyone who&#x27;s used Ruby on Rails
before. Or Jinja with Python.&lt;&#x2F;p&gt;
&lt;p&gt;I highly suggest running &lt;code&gt;cargo fmt&lt;&#x2F;code&gt; afterward, because ERB isn&#x27;t well known for
cleaning up whitespace effectively.&lt;&#x2F;p&gt;
&lt;p&gt;Following this, it was time to glue everything together. For this I found that
PowerShell worked marvelously. I found a &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;1858234&quot;&gt;StackOverflow&lt;&#x2F;a&gt; answer which
provided the basics of a script which can save Excel files as other formats,
then the &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;office&#x2F;vba&#x2F;api&#x2F;excel.xlfileformat&quot;&gt;Microsoft documentation&lt;&#x2F;a&gt; provided the right format code for the
TSV I want. Finally, the command runs the Ruby script from earlier.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;# xlsx2tsv2rs.ps1
$ExcelFile = Join-Path $(Get-Location) ARCOMAGE_CARDS.xlsx
$TsvFile = Join-Path $(Get-Location) ARCOMAGE_CARDS.tsv
$TsvFmtCode = -4158
$Excel = New-Object -Com Excel.Application
$Excel.DisplayAlerts=$False
$WorkBook = $Excel.Workbooks.Open($ExcelFile)
$WorkBook.SaveAs($TsvFile, $TsvFmtCode)
$Excel.quit()
ruby tsv2rs.rb
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The natural next step for this is to use a &lt;code&gt;build.rs&lt;&#x2F;code&gt; file to invoke this
automatically when &lt;code&gt;cargo build&lt;&#x2F;code&gt; is run, however, there&#x27;s a reason why I &lt;em&gt;don&#x27;t&lt;&#x2F;em&gt;
think that&#x27;s a good idea: it destroys cross-platform compatibility. The way it
is now, I can rebuild my static objects when I&#x27;m on a Windows PC which has
PowerShell, Excel, and Ruby. While PowerShell is now cross-platform, the only
other native platform for Excel is Mac. I&#x27;m not even sure if PowerShell on Mac
would interface with Excel for Mac the way it has on Windows.&lt;&#x2F;p&gt;
&lt;p&gt;And that&#x27;s how I learned to convert Excel to Rust.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Level up your Crate</title>
                <pubDate>Wed, 27 Mar 2019 00:00:00 +0000</pubDate>
                <link>https://www.mysteriouspants.com/blog/level-up-your-crate/</link>
                <guid>https://www.mysteriouspants.com/blog/level-up-your-crate/</guid>
                <description>&lt;p&gt;This is adapted from a talk given on 27 March 2019 at &lt;a href=&quot;https:&#x2F;&#x2F;www.meetup.com&#x2F;Desert-Rustaceans&#x2F;&quot;&gt;Desert Rust&lt;&#x2F;a&gt;, a meetup group of Rust enthusiasts in Mesa, Arizona. If you live in the area or are just visiting during a meetup, please stop by - we&#x27;d love to see you there!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;You probably already know how to make a Rust crate.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;cargo new --lib crate
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You&#x27;ve probably written some Rust code in it, code that is good and ought to be shared. You&#x27;ve published it to crates.io, and nothing happened. Nobody appreciated it, why?&lt;&#x2F;p&gt;
&lt;p&gt;When I was a young boy and still foolish, my brother had a soccer (football) coach who would tell him, &amp;quot;if you look good, you play good.&amp;quot; In the spirit of that council, I believe that even the best software will be ignored if it&#x27;s not dressed up to impress.&lt;&#x2F;p&gt;
&lt;p&gt;The following tips can help juice up your crate and help it sell itself to potential users.&lt;&#x2F;p&gt;
&lt;p&gt;The elements of a solid crate, unless you know better ones, are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;README&lt;&#x2F;li&gt;
&lt;li&gt;Documentation&lt;&#x2F;li&gt;
&lt;li&gt;Tests&lt;&#x2F;li&gt;
&lt;li&gt;Continuous Integration (if applicable)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;readme&quot;&gt;README&lt;&#x2F;h2&gt;
&lt;p&gt;The README is your 60-seconds in an elevator pitch to your potential user. This is the part of your craft where you should throw modesty to the wind, because this is advertising, and advertising is war.&lt;&#x2F;p&gt;
&lt;p&gt;I organize my README into four parts. Everything else is extraneous and belongs in separate documents. These parts are:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;What is this? What does it do?&lt;&#x2F;li&gt;
&lt;li&gt;How does this work? No, how does it work for me? (Best approached with a short code sample).&lt;&#x2F;li&gt;
&lt;li&gt;How do I get it? (This is Rust, so I assume it&#x27;s a crate).&lt;&#x2F;li&gt;
&lt;li&gt;Can I use this? By this I mean licensing - not everybody can use every license of software.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I try to be as customer-centric as possible when writing these. The template for my idea of a perfect README looks like the following:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;vim README.md
# Crate Name
Elevator pitch! What does this do, and why is it awesome
at doing it?

```
fn main() {
  println!(&amp;quot;Code sample!&amp;quot;);
}
```

Elaboration about what this does, with more code samples,
or a link to a wiki or some other documentation.

# License
[2-Clause BSD](https:&#x2F;&#x2F;opensource.org&#x2F;licenses&#x2F;BSD-2-Clause)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s short, and it frontloads the most pertinent information to someone who&#x27;s shopping for crates and may have dozens of tabs open for research.&lt;&#x2F;p&gt;
&lt;p&gt;Remember to add your README to your &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; file so it gets picked up by &lt;code&gt;cargo build&lt;&#x2F;code&gt; and shows upon your Crates.io listing page as well, such as with &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;mysteriouspants-throttle&quot;&gt;throttle&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;vim Cargo.toml
[package]
readme = &amp;quot;README.md&amp;quot;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While it may seem trivial, this is another point of contact to make it easy for potential customers to quickly learn about your crate.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;badges&quot;&gt;Badges&lt;&#x2F;h3&gt;
&lt;p&gt;Badges are little images which automatically updated and tell consumers information about your crate. By being on Crates.io, you get the these two badges for free,&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;a crates.io current version badge, which looks like &lt;img src=&quot;https:&#x2F;&#x2F;img.shields.io&#x2F;crates&#x2F;v&#x2F;mysteriouspants-throttle.png&quot; style=&quot;width: auto;&quot;&#x2F;&gt;, and&lt;&#x2F;li&gt;
&lt;li&gt;a docs.rs current version badge, which looks like &lt;img src=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;mysteriouspants-throttle&#x2F;badge.svg&quot; style=&quot;width: auto;&quot;&#x2F;&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Use these badges to link readers on your Github&#x2F;Gitlab page to crates.io or to docs.rs.&lt;&#x2F;p&gt;
&lt;p&gt;I like to add these to my README directly below the Crate name, but just before the elevator pitch.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;vim README.md
# Crate name

[![Crates.io][cios]][cio] [![Docs.rs][drss]][]drs

Elevator pitch!

...

[cio]: https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;crate-name
[cios]: https:&#x2F;&#x2F;img.shields.io&#x2F;crates&#x2F;v1&#x2F;crate-name.svg
[drs]: https:&#x2F;&#x2F;docs.rs&#x2F;crate-name
[drss]: https:&#x2F;&#x2F;docs.rs&#x2F;crate-name&#x2F;badge.svg
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can also add these links to your &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; so they are visible from your Crates.io listing as well.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;vim Cargo.toml
[package]
documentation = &amp;quot;https:&#x2F;&#x2F;docs.rs&#x2F;crate-name&amp;quot;
repository = &amp;quot;https:&#x2F;&#x2F;github.com&#x2F;...&amp;quot;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;documentation&quot;&gt;Documentation&lt;&#x2F;h2&gt;
&lt;p&gt;Documentation is what separates code for me from code for you - and code for future me who has forgotten how everything works.&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;ve probably already worked out that Rust documentation is in CommonMark (or Markdown) format. Docs for ordinary items, such as structs, fields, and functions, are given by three slashes.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&#x2F;&#x2F;&#x2F; Control the rate of novertrunnions.
pub mut novertrunnion_choke: f32;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Bigger ideas, such as how an entire crate is to be used or a module within that crate, are given by module docs, which use two slashes and a bang!&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&#x2F;&#x2F;! For a number of years now, work has been proceeding
&#x2F;&#x2F;! in order to bring perfection to the crudely conceived
&#x2F;&#x2F;! idea of a transmission that would not only supply
&#x2F;&#x2F;! ...
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;tests&quot;&gt;Tests&lt;&#x2F;h2&gt;
&lt;p&gt;You probably don&#x27;t write bugs, but I do, and I try to prove that my code works using tests. Writing good tests is among the harder things to do, and entire books have been written on the subject, so I&#x27;ll spare you any incomplete thoughts on the subject here.&lt;&#x2F;p&gt;
&lt;p&gt;The default crate template comes with a stub for you to fill in some tests:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;vim src&#x2F;lib.rs
...
#[cfg(test)]
mod tests {
  #[test]
  fn it_works() {
    assert!(1 + 1 == 2);
  }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Cargo comes with a built-in test runner, so running those tests is remarkably easy.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;➜  retry git:(master) ✗ cargo test
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running target&#x2F;debug&#x2F;deps&#x2F;mysteriouspants_retry-6c4c9e88511db7ca

running 2 tests
test tests::succeeds_after_two_retries ... ok
test tests::fails_after_exhausting_retries ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests mysteriouspants-retry

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Going further, we arrive at my favorite Rust feature, the part that I think takes Rust from a toy language to something capable of building durable software: doctests.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;cargo test&lt;&#x2F;code&gt; will try to run code samples in your documentation, so if you change your crate&#x27;s implementation, you can easily catch idiosyncrasies in your documentation&#x27;s code examples. This encourages you to document using prose &lt;em&gt;and&lt;&#x2F;em&gt; code, creating APIs with rich reference material.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&#x2F;&#x2F;&#x2F; The main winding was of the normal lotus-o-delta type
&#x2F;&#x2F;&#x2F; placed in pandndermic semi-boloid slots of the stator,
&#x2F;&#x2F;&#x2F; ...
&#x2F;&#x2F;&#x2F;
&#x2F;&#x2F;&#x2F; ```rust
&#x2F;&#x2F;&#x2F; # extern crate mysteriouspants_rockwell;
&#x2F;&#x2F;&#x2F; # use rockwell::TurboEncabulator;
&#x2F;&#x2F;&#x2F; # fn main() {
&#x2F;&#x2F;&#x2F; &#x2F;&#x2F; create a new TurboEncabulator
&#x2F;&#x2F;&#x2F; let mut encabulator = TurboEncabulator {
&#x2F;&#x2F;&#x2F;   cardinal_grammeters: 3
&#x2F;&#x2F;&#x2F; };
&#x2F;&#x2F;&#x2F; assert_eq!(encabulator.cardinal_grammeters, 3);
&#x2F;&#x2F;&#x2F; # }
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Any code sample line that does not begin with a &lt;code&gt;#&lt;&#x2F;code&gt; (octothorpe) will appear in your documentation, letting you de-noise what shows up on docs.rs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;travis&quot;&gt;Travis&lt;&#x2F;h2&gt;
&lt;p&gt;The last thing I look for in a well-constructed crate meant for third-party consumption is some kind of Continuous Integration. For Open-Source, the easiest I know of it &lt;a href=&quot;https:&#x2F;&#x2F;travis-ci.org&quot;&gt;Travis CI&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Tell Travis how to build your Crate by telling it that you&#x27;re writing Rust in a &lt;code&gt;.travis.yml&lt;&#x2F;code&gt; file.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;vim .travis.yml
language: rust
rust:
  - stable
  - beta
  - nightly
matrix:
  allow_failures:
    - rust: nightly
fast_finish: true
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using Travis gets you another badge for your README, as well.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;vim Cargo.toml
[badges]
travis-ci = { repository = &amp;quot;github-user&#x2F;repo&amp;quot; }

vim README.md
[other badges from before] [![Build Status][traviss]][travis]

...

[travis]: https:&#x2F;&#x2F;travis-ci.org&#x2F;github-user&#x2F;repo
[traviss]: https:&#x2F;&#x2F;travis-ci.org&#x2F;github-user&#x2F;repo.svg?branch=master
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;If you&#x27;ve followed these suggestions, I consider your crate as having leveled up! Potential users can&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;see what your crate is about at a glance in your README, both on your repo page and on crates.io,&lt;&#x2F;li&gt;
&lt;li&gt;read detailed documentation and examples to confirm that what you&#x27;ve written is what they&#x27;re after, and&lt;&#x2F;li&gt;
&lt;li&gt;see that your code does everything you say that it does with a passing CI build!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;These suggestions are&lt;&#x2F;em&gt; unless you know better ones. &lt;em&gt;If you do, please open an issue or PR on &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mysteriouspants&#x2F;mysteriouspants.com&quot;&gt;github&lt;&#x2F;a&gt; and be clear it&#x27;s this post you think ought to be revised.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Headfirst into Rust - Throttle and Mutability</title>
                <pubDate>Sat, 01 Sep 2018 00:00:00 +0000</pubDate>
                <link>https://www.mysteriouspants.com/blog/mutability-in-rust/</link>
                <guid>https://www.mysteriouspants.com/blog/mutability-in-rust/</guid>
                <description>&lt;p&gt;In the first iteration of my Throttle, I packaged the state of the
throttle into a &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;cell&#x2F;&quot;&gt;&lt;code&gt;Cell&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; so that an otherwise immutable throttle
could still function.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;pub struct Throttle&amp;lt;TArg&amp;gt; {
  delay_calculator: Box&amp;lt;Fn(TArg, Duration) -&amp;gt; Duration + Send + Sync&amp;gt;,
  state: Cell&amp;lt;ThrottleState&amp;gt;
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This has the interesting side effect of making the throttle unsafe in
threaded environments. Two threads could attempt to mutate the state at
the same time, which would have undefined results.&lt;&#x2F;p&gt;
&lt;p&gt;Fishing for opinions, the suggestion to use an &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;sync&#x2F;struct.RwLock.html#method.write&quot;&gt;&lt;code&gt;RwLock&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to
control access to the &lt;code&gt;Cell&lt;&#x2F;code&gt; came up. The implication being that, if two
threads try to modify the state of a throttle at the same time, then the
second thread to do so will spin wait until the throttle becomes
available again. This is acceptable behavior, since the throttle may
just wait that thread again anyway as soon as it acquires the lock.&lt;&#x2F;p&gt;
&lt;p&gt;Looking at &lt;code&gt;RwLock&lt;&#x2F;code&gt;, however, it is not a happy story. Getting a lock
may fail and that requires propagating that failure to the caller. This
would make the implementation for acquire look something like the
following:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;impl &amp;lt;TArg&amp;gt; Throttle&amp;lt;TArg&amp;gt; {
  pub fn acquire(&amp;amp;self, arg: TArg): LockResult { ... }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Callers would have to match on the result or call &lt;code&gt;unwrap&lt;&#x2F;code&gt; on the result
to determine if there was an error or not, which is more complicated
than I want the API to be in its most basic case.&lt;&#x2F;p&gt;
&lt;p&gt;In my opinion, how to handle concurrency failures is not a concern of
the throttle, so instead I chose to make the throttle itself mutable.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;pub struct Throttle&amp;lt;TArg&amp;gt; {
  delay_calculator: Box&amp;lt;Fn(TArg, Duration) -&amp;gt; Duration + Send + Sync&amp;gt;,
  state: ThrottleState
}

impl &amp;lt;TArg&amp;gt; Throttle&amp;lt;TArg&amp;gt; {
  pub fn acquire(&amp;amp;mut self, arg: TArg) { ... }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rust&#x27;s borrow checker forces the caller to handle thread safety (or
unsafety), in a way that is most sensible to the caller. In the simple
case: there is only a single thread, so the API remains clean of any
concurrency; in the complex case: the consumer can use whatever
concurrency methods are necessary.&lt;&#x2F;p&gt;
&lt;p&gt;In the future I think it would be wise to refactor this down into a
trait for Throttles, with specializations for different kinds of
throttling - simple throttles, closure-controlled throttles, threadsafe
closure-controlled throttles, throttle-buckets, threadsafe throttle
buckets, and so on. But as I iteratively dive deeper into the Rust
language, such things are fun thoughts that can stand to be pondered a
while longer.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Headfirst into Rust - Building a Throttle</title>
                <pubDate>Wed, 06 Jun 2018 00:00:00 +0000</pubDate>
                <link>https://www.mysteriouspants.com/blog/headfirst-into-rust/</link>
                <guid>https://www.mysteriouspants.com/blog/headfirst-into-rust/</guid>
                <description>&lt;p&gt;This is a development journal of my first Rust crate, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mysteriouspants&#x2F;throttle&quot;&gt;Throttle&lt;&#x2F;a&gt;, which I built over the course of a weekend and a few weeknights. I based my crate authorship standard on literally a single livecoding session by &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=KS14JIRZTBw&quot;&gt;Jon &amp;quot;Jonhoo&amp;quot; Gjengset&lt;&#x2F;a&gt;, took courage in the Jeremy Clarkson motto &amp;quot;how hard can it be?&amp;quot; and set to the task. The follows how I wrote some really bad code and made a crate.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Most of the code listings are reconstructions and not completely accurate to what I eventually hammered out which compiled.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-throttle&quot;&gt;The Throttle&lt;&#x2F;h2&gt;
&lt;p&gt;I decided to build a TPS throttle because I want to build some tooling around Squizz&#x27; &lt;a href=&quot;https:&#x2F;&#x2F;www.zkillboard.com&#x2F;&quot;&gt;zKillboard&lt;&#x2F;a&gt; for EVE Online. First of my concerns is that I don&#x27;t get blocked for spamming his website too much - and to slow down a program I reckon I want a throttle. I started by using the default crate template I got out of IntelliJ, and in the testing section wrote out how I wanted to use the throttle. I got something like the following:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&#x2F;&#x2F; simple throttle configured for 10 TPS
let throttle = Throttle::new(10);

let iteration_start = Instant::now();

for _i in 0..11 {
    throttle.acquire();
}

&#x2F;&#x2F; prove that it waited by showing that one second has elapsed
assert_eq!(iteration_start.elapsed().as_secs() == 1, true);
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The basic idea is that by calling &lt;code&gt;acquire&lt;&#x2F;code&gt; you&#x27;re really saying &amp;quot;call &lt;code&gt;thread::sleep&lt;&#x2F;code&gt; if and only if I need to slow down,&amp;quot; and by making it an object it could even be used by multiple threads of execution at the same time (using a lock). That way multiple threads could be pulling work, and all safely not viciously slaughtering zKillboard.&lt;&#x2F;p&gt;
&lt;p&gt;I started with a perusal of the standard library and found some APIs which will form the backbone of the throttle: &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;time&#x2F;struct.Duration.html&quot;&gt;&lt;code&gt;Duration&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;time&#x2F;struct.Instant.html&quot;&gt;&lt;code&gt;Instant&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;thread&#x2F;fn.sleep.html&quot;&gt;&lt;code&gt;sleep&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Thus armed, I charged in and created a struct which looked something like the following, and then the first problem happened.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;#[derive(Copy, Clone)]
enum ThrottleState {
    Uninitialized,
    Initialized {
        previous_invocation: Instant
    }
}

pub struct Throttle {
  tps: f32,
  previous_invocation: Cell&amp;lt;ThrottleState&amp;gt;
}

impl Throttle {
  fn new(tps: f32) -&amp;gt; Throttle { ... }
  fn acquire(&amp;amp;self) { ... }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Yes, the first problem happened before I had even implemented the methods. My first problem was a single thought:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;wouldn&#x27;t it be cool if the throttle could be dynamic, getting faster and slower?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I write Java in my day job (trying to transition to Kotlin, but for present purposes the reflex is the same), so the concept of &amp;quot;thing that tells how long to delay&amp;quot; feels like a dependency and should not be an aspect of the &lt;code&gt;Throttle&lt;&#x2F;code&gt; itself, and it didn&#x27;t feel like something that I should slap &lt;code&gt;Cell&amp;lt;f32&amp;gt;&lt;&#x2F;code&gt; as the type for &lt;code&gt;tps&lt;&#x2F;code&gt; and call it done, either.&lt;&#x2F;p&gt;
&lt;p&gt;Well you say dependency and so I try to make a bean or at least a struct. That was my first problem.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;storing-a-trait-or-don-t-write-java-in-rust&quot;&gt;Storing a Trait, or Don&#x27;t Write Java in Rust&lt;&#x2F;h2&gt;
&lt;p&gt;My first reflex was to create a trait for the thing which controls the variance of the &lt;code&gt;Throttle&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;pub Trait DelayCalculator&amp;lt;TArg&amp;gt; {
  fn calculate(arg: TArg) -&amp;gt; Duration;
}

impl &amp;lt;TArg&amp;gt; DelayCalculator&amp;lt;TArg&amp;gt; for f32 {
  fn calculate(&amp;amp;self, arg: TArg) -&amp;gt; Duration {
    return Duration::from_millis((1.0 &#x2F; self) * 1000.0);
  }
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So in my head the nifty thing is that now &lt;code&gt;f32&lt;&#x2F;code&gt; itself implements &lt;code&gt;DelayCalculator&lt;&#x2F;code&gt;, so I should be able to keep my example and pass a straight &lt;code&gt;f32&lt;&#x2F;code&gt; into &lt;code&gt;Throttle::new&lt;&#x2F;code&gt; and it should &lt;em&gt;just work.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;But when I modified &lt;code&gt;Throttle&lt;&#x2F;code&gt; itself, things broke apart.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;pub struct Throttle&amp;lt;TArg&amp;gt; {
  &#x2F;&#x2F; ERROR: DelayCalculator is not sized
  delay_calculator: DelayCalculator&amp;lt;TArg&amp;gt;,
  previous_invocation: Cell&amp;lt;ThrottleState&amp;gt;
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;An experienced Rustacean is likely chuckling a bit, but for the uninitiated, this actually makes a lot of sense only after you stop to consider what you&#x27;re describing the memory layout to be. To put a &lt;code&gt;Throttle&lt;&#x2F;code&gt; somewhere the compiler needs to know how big it is. But a Trait is unsized because it could be implemented by something as small as &lt;code&gt;u8&lt;&#x2F;code&gt; or as large as an array of them making a bitmap image of your mom (so filling all addressable memory). There is no way to know.&lt;&#x2F;p&gt;
&lt;p&gt;The compiler helpfully suggests putting the field in a &lt;code&gt;Box&lt;&#x2F;code&gt;, or storing it on the heap, so &lt;code&gt;Throttle&lt;&#x2F;code&gt; would contain a pointer to allocated memory of any size, which I tried. But it felt wrong. A &lt;code&gt;Throttle&lt;&#x2F;code&gt; is simple enough it ought to be expressable without any recourse to the heap!&lt;&#x2F;p&gt;
&lt;p&gt;The next option is to make it a generic parameter, making the &lt;code&gt;Throttle&lt;&#x2F;code&gt; look something like the following:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;pub struct Throttle&amp;lt;TDelayCalculator, TArg&amp;gt;
    where TDelayCalculator : DelayCalculator&amp;lt;TArg&amp;gt; {
  delay_calculator: TDelayCalculator,
  previous_invocation: Cell&amp;lt;ThrottleState&amp;gt;
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is better, maybe even good. It makes it harder to work with &lt;code&gt;Throttle&lt;&#x2F;code&gt;, however, as you need to know about the &lt;code&gt;DelayCalculator&lt;&#x2F;code&gt; it uses to size it and therefore store it. Also a point of detraction, it&#x27;s heavier. Java-style heavier. It requires the introduction of a new type where perhaps one is unneeded.&lt;&#x2F;p&gt;
&lt;p&gt;Next I decided to try to make it a functional interface.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;storing-a-closure-or-template-all-the-things&quot;&gt;Storing a Closure, or Template All The Things&lt;&#x2F;h2&gt;
&lt;p&gt;By making the &lt;code&gt;Throttle&lt;&#x2F;code&gt; take a delay calculator as a functional interface I hoped to ameilorate the need for making additional implementations like some deranged late nineties Java developer. I also hoped to elide the need for using those &lt;code&gt;Box&lt;&#x2F;code&gt;es and generics. This was not to be.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;pub struct Throttle&amp;lt;TArg&amp;gt; {
  &#x2F;&#x2F; ERROR: Fn&amp;lt;TArg&amp;gt; -&amp;gt; Duration is not sized
  delay_calculator: Fn&amp;lt;TArg&amp;gt; -&amp;gt; Duration,
  previous_invocation: Cell&amp;lt;ThrottleState&amp;gt;
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Oops, same errors as before. But it again makes sense. A closure can capture its surrounding state, which means that any closure may have a different size depending on what local state it captured.&lt;&#x2F;p&gt;
&lt;p&gt;So it&#x27;s back to using a generic:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;pub struct Throttle&amp;lt;TArg, TDelayCalculator&amp;gt; 
    where TDelayCalculator : Fn&amp;lt;TArg&amp;gt; -&amp;gt; Duration {
  delay_calculator: TDelayCalculator,
  previous_invocation: Cell&amp;lt;ThrottleState&amp;gt;,
  delay_arg_type: PhantomData&amp;lt;TArg&amp;gt;
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But this simply bubbles the issue of the &lt;code&gt;TDelayCalculator&lt;&#x2F;code&gt; being unsizeable back up to the calling code. In the trivial case it doesn&#x27;t matter because it will live on the stack. But if it&#x27;s packaged into a client it becomes unergonomic or the whole thing must be &lt;code&gt;Box&lt;&#x2F;code&gt;ed. Yuk.&lt;&#x2F;p&gt;
&lt;p&gt;It feels like the &lt;code&gt;Box&lt;&#x2F;code&gt; is unavoidable, so for now it&#x27;s inside the &lt;code&gt;Throttle&lt;&#x2F;code&gt; to keep the struct as portable as it possibly can be.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;pub struct Throttle&amp;lt;TArg&amp;gt; {
  delay_calculator: Box&amp;lt;Fn(TArg, Duration) -&amp;gt; Duration&amp;gt;,
  state: Cell&amp;lt;ThrottleState&amp;gt;
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This makes the constructors of the struct very simple:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;pub fn new&amp;lt;TDelayCalculator&amp;gt;(delay_calculator: TDelayCalculator) -&amp;gt; Throttle&amp;lt;TArg&amp;gt;
    where TDelayCalculator: Fn(TArg, Duration) -&amp;gt; Duration + &#x27;static {
  return Throttle {
    delay_calculator: Box::new(delay_calculator),
    state: Cell::new(ThrottleState::Uninitialized)
  };
}

pub fn new_tps_throttle(tps: f32) -&amp;gt; Throttle&amp;lt;TArg&amp;gt; {
  return Throttle {
    delay_calculator: Box::new(move |_, _|
      Duration::from_millis(((1.0 &#x2F; tps) * 1000.0) as u64)),
    state: Cell::new(ThrottleState::Uninitialized)
  };
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;documentation-that-also-tests&quot;&gt;Documentation that also Tests&lt;&#x2F;h2&gt;
&lt;p&gt;Thus far Rust has been delightful. The language is terse, yet expressive, and the compiler, while unforgiving, is helpful with well-written error messages with suggestions to resolution. But perhaps the most impressive to me is how documentation is written for Rust. Beyond a good README file, which has been shown to be the single most important factor in the adoption of an open-source project, the documentation can either be an asset or a liability, depending on the quality and accuracy.&lt;&#x2F;p&gt;
&lt;p&gt;Rust aims to prevent documentation drift by simply compiling it.&lt;&#x2F;p&gt;
&lt;p&gt;The module documentation for Throttle, the top of the package and the introduction when a potential consumer first sees the documentation page, looks like the following:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&#x2F;&#x2F;! A simple throttle, used for slowing down repeated code. Use this to avoid
&#x2F;&#x2F;! drowning out downstream systems. For example, if I were reading the contents
&#x2F;&#x2F;! of a file repeatedly (polling for data, perhaps), or calling an external
&#x2F;&#x2F;! network resource, I could use a `Throttle` to slow that down to avoid
&#x2F;&#x2F;! resource contention or browning out a downstream service.
&#x2F;&#x2F;!
&#x2F;&#x2F;! This ranges in utility from a simple TPS throttle, &amp;quot;never go faster than *x*
&#x2F;&#x2F;! transactions per second,&amp;quot;
&#x2F;&#x2F;!
&#x2F;&#x2F;! ```rust
&#x2F;&#x2F;! # extern crate mysteriouspants_throttle;
&#x2F;&#x2F;! # use std::time::Instant;
&#x2F;&#x2F;! # use mysteriouspants_throttle::Throttle;
&#x2F;&#x2F;! # fn main() {
&#x2F;&#x2F;! &#x2F;&#x2F; create a new Throttle that rate limits to 10 TPS
&#x2F;&#x2F;! let throttle = Throttle::new_tps_throttle(10.0);
&#x2F;&#x2F;!
&#x2F;&#x2F;! let iteration_start = Instant::now();
&#x2F;&#x2F;!
&#x2F;&#x2F;! &#x2F;&#x2F; iterate eleven times, which at 10 TPS should take just over 1 second
&#x2F;&#x2F;! for _i in 0..11 {
&#x2F;&#x2F;!   throttle.acquire(());
&#x2F;&#x2F;!   &#x2F;&#x2F; do the needful
&#x2F;&#x2F;! }
&#x2F;&#x2F;!
&#x2F;&#x2F;! &#x2F;&#x2F; prove that it did, in fact, take 1 second
&#x2F;&#x2F;! assert_eq!(iteration_start.elapsed().as_secs() == 1, true);
&#x2F;&#x2F;! # }
&#x2F;&#x2F;! ```
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The documentation is itself in CommonMark, so it&#x27;s remarkably easy to write. But the code sample is compiled, so when I run &lt;code&gt;cargo test&lt;&#x2F;code&gt; I see that it runs the documentation code listing as well:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;PS C:\Users\xpm\Projects\mysteriouspants-throttle&amp;gt; cargo test
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running target\debug\deps\mysteriouspants_throttle-62cc10bf6d8c5f7f.exe

running 1 test
test tests::it_works ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests mysteriouspants-throttle

running 4 tests
test src\lib.rs -  (line 10) ... ok
test src\lib.rs -  (line 34) ... ok
test src\lib.rs - Throttle&amp;lt;TArg&amp;gt;::new_variable_throttle (line 76) ... ok
test src\lib.rs - Throttle&amp;lt;TArg&amp;gt;::new_variable_throttle (line 92) ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And to the user, the person viewing the webpage, it looks like any normal code listing.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&#x2F;&#x2F; create a new Throttle that rate limits to 10 TPS
let throttle = Throttle::new_tps_throttle(10.0);

let iteration_start = Instant::now();

&#x2F;&#x2F; iterate eleven times, which at 10 TPS should take just over 1 second
for _i in 0..11 {
  throttle.acquire(());
  &#x2F;&#x2F; do the needful
}

&#x2F;&#x2F; prove that it did, in fact, take 1 second
assert_eq!(iteration_start.elapsed().as_secs() == 1, true);
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The combined effect is that I ended up putting more of my tests in the documentation, both as a test-driven measure, and to make sure my tests are really showing how the crate works from a consumer-driven perspective. If I change the API contract, the test should break right in the documentation, so the documentation should not be able to drift away from how the crate actually works, so long as I&#x27;m still running the tests.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;Rust is a language I&#x27;ve had my eye on for a very long time now. It promises to be close to the metal, fast, and expressive, focusing on letting the programmer build abstractions that don&#x27;t cost in performance as much as possible. It&#x27;s portable, and it has a great build system with an easy way of taking on new dependencies.&lt;&#x2F;p&gt;
&lt;p&gt;I personally prefer it over more popular modern languages like Go, because Rust dares to ignore the draw of garbage collection to say that the programmer can write proper code with a low water mark in memory (I distrust garbage collectors).&lt;&#x2F;p&gt;
&lt;p&gt;In short, Rust values the things that I value, and for that I enjoy it.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Let&#x27;s Encrypt on Nginx Setup</title>
                <pubDate>Wed, 31 Aug 2016 00:00:00 +0000</pubDate>
                <link>https://www.mysteriouspants.com/blog/encrypt-all-the-things/</link>
                <guid>https://www.mysteriouspants.com/blog/encrypt-all-the-things/</guid>
                <description>&lt;p&gt;Encryption is a thing now, 314, proliferated to the point that Google
will downrank site which do not have it. I&#x27;ve never exactly cared who,
if anyone, reads this site, but I thought I&#x27;d give Let&#x27;s Encrypt a try -
if for no better reason than because I&#x27;d like to use HTTP2 on a web app
I&#x27;m writing.&lt;&#x2F;p&gt;
&lt;p&gt;These notes are really for my benefit, though it might benefit you as
well.&lt;&#x2F;p&gt;
&lt;p&gt;First, install Let&#x27;s Encrypt.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt install -y letsencrypt
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For every domain, modify the virtual server definition to look like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;sudo vim &#x2F;etc&#x2F;nginx&#x2F;sites-available&#x2F;mysteriouspants.com
  # a reflector domain that just redirects to www.,
  # and serves .well-known files
  server {
    listen 80;
    server_name mysteriouspants.com;
    access_log off;

    root &#x2F;var&#x2F;www&#x2F;empty;

    location &#x2F;.well-known {
      root &#x2F;var&#x2F;www&#x2F;letsencrypt;
      try_files $uri &#x2F;dev&#x2F;null =404;
    }

    location &#x2F; {
      return 301 https:&#x2F;&#x2F;www.$host$request_uri;
    }
  }

  server {
    listen 443 ssl http2;
    server_name mysteriouspants.com;
    access_log off;

    ssl_certificate &#x2F;etc&#x2F;letsencrypt&#x2F;live&#x2F;mysteriouspants.com&#x2F;fullchain.pem;
    ssl_certificate_key &#x2F;etc&#x2F;letsencrypt&#x2F;live&#x2F;mysteriouspants.com&#x2F;privkey.pem;

    return 301 https:&#x2F;&#x2F;www.$host$request_uri;
  }
sudo vim &#x2F;etc&#x2F;nginx&#x2F;sites-available&#x2F;www.mysteriouspants.com
  server {
    listen 80;
    server_name www.mysteriouspants.com;
    access_log off;

    root &#x2F;var&#x2F;www&#x2F;empty;

    location &#x2F;.well-known {
      root &#x2F;var&#x2F;www&#x2F;letsencrypt;
      try_files $uri &#x2F;dev&#x2F;null =404;
    }

    location &#x2F; {
      return 301 https:&#x2F;&#x2F;$host$request_uri;
    }
  }

  server {
    listen 443 ssl http2;
    server_name www.mysteriouspants.com;
    access_log off;

    ssl_certificate &#x2F;etc&#x2F;letsencrypt&#x2F;live&#x2F;mysteriouspants.com&#x2F;fullchain.pem;
    ssl_certificate_key &#x2F;etc&#x2F;letsencrypt&#x2F;live&#x2F;mysteriouspants.com&#x2F;privkey.pem;

    root &#x2F;var&#x2F;www&#x2F;www.mysteriouspants.com;
  }
sudo service nginx reload
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Make some directories. The &lt;code&gt;empty&lt;&#x2F;code&gt; directory in particular is for the
root of the redirection mirrors.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;sudo mkdir &#x2F;var&#x2F;www&#x2F;empty
sudo mkdir &#x2F;var&#x2F;www&#x2F;letsencrypt
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Actually grab your first SSL certificate. It will ask you to accept a
EULA, then it will populate &lt;code&gt;&#x2F;var&#x2F;www&#x2F;letsencrypt&lt;&#x2F;code&gt; with some challenge
files. Their servers will ask your domains for those files to prove that
you control the domains - so they&#x27;re not just handing out certificates
willy-nilly.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;sudo letsencrypt certonly --webroot -w &#x2F;var&#x2F;www&#x2F;letsencrypt \
  -d mysteriouspants.com \
  -d www.mysteriouspants.com
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This command should complete with no errors, if it does, your Nginx
configuration is likely messed up.&lt;&#x2F;p&gt;
&lt;p&gt;At this point, your web pages are actually SSL&#x27;d now that your SSL
certificates exist. Harden up your Nginx server by adding this set of
ciphers I totally didn&#x27;t just pull off some webpage.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;sudo vim &#x2F;etc&#x2F;nginx&#x2F;nginx.conf
  ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally, Let&#x27;s Encrypt certificates are only good for 90 days, so it&#x27;s
best to renew them. It&#x27;s simple enough to renew it using a cron job.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;sudo vim &#x2F;etc&#x2F;cron.daily&#x2F;letencrypt
  #!&#x2F;bin&#x2F;sh

  letsencrypt renew
  service nginx reload
  # reload any other services that may need to take the new certificates
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And there you have it.&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title>Deploying Elixir&#x2F;Phoenix</title>
                <pubDate>Mon, 18 Jul 2016 00:00:00 +0000</pubDate>
                <link>https://www.mysteriouspants.com/blog/deploying-phoenix/</link>
                <guid>https://www.mysteriouspants.com/blog/deploying-phoenix/</guid>
                <description>&lt;p&gt;&lt;em&gt;This page is something of a living blog post, and it does get updated
from time to time. I suggest you look at the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mysteriouspants&#x2F;mysteriouspants.com&#x2F;commits&#x2F;master&#x2F;_posts&#x2F;2016-07-18-deploying-phoenix.md&quot;&gt;file&#x27;s history&lt;&#x2F;a&gt;
if you need to know how fresh&#x2F;stale this guide is.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Well 314, it has been a while, has it not? I have recently completed a
bit of an adventure (or completed the adventure nearly enough to share,
at any rate). I&#x27;ve gone and fallen in love with the &lt;a href=&quot;http:&#x2F;&#x2F;elixir-lang.org&#x2F;&quot;&gt;Elixir programming
language&lt;&#x2F;a&gt;, and the star of the Elixir world right now is
&lt;a href=&quot;http:&#x2F;&#x2F;www.phoenixframework.org&#x2F;&quot;&gt;Phoenix&lt;&#x2F;a&gt;, a web framework. Now, cutting websites it&#x27;s nearly
as sexy as it was in the late nineties, but this nearly makes up for it.&lt;&#x2F;p&gt;
&lt;p&gt;Phoenix&#x27;s one-two punch of a Rails-ish paradigm and a nice database
layer in Ecto makes it a true joy to work with. Where Phoenix gains on
Rails, however, is in Elixir, a language which keeps much of the
happiness of Ruby while handing you the speed of Erlang. Even on
database-backed pages Phoenix returns pages in tens of milliseconds.&lt;&#x2F;p&gt;
&lt;p&gt;So it&#x27;s some hot stuff, and it makes me happy. But with all web apps,
there comes a time when running it on my laptop is not enough. So I
embarked upon a journey to learn to deploy Elixir&#x2F;Phoenix apps to a
server using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;boldpoker&#x2F;edeliver&quot;&gt;edeliver&lt;&#x2F;a&gt; and exrm.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;The overall model of deployment is to commit and push code to your source repository. edeliver will then pull that to a build server (a server that resembles your production server - in OS and architecture, so you can build a compatible package). On this build server it uses exrm to compile a release (or upgrade, which can patch your running code - pretty dope), and downloads that to your computer. You then upload this package to your production server(s).&lt;&#x2F;p&gt;
&lt;p&gt;These exrm releases themselves are pretty cool. They are self-contained
releases, they include an Erlang VM, all the package and dependencies to
make your app run. Gone are the days of hammering rubygems.org from
three dozen machines every deploy!&lt;&#x2F;p&gt;
&lt;p&gt;For my build server, I simply set up a new user account on my Digital
Ocean droplet, running Ubuntu Linux, which runs this site and my IRC
bouncer. My production server was similarly yet another account on this
server. edeliver, however, supports a plurality of production servers.
Cleverly, it uses SSH, so you can use keys to make things happen without
a single password getting in the way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setting-up-a-build-server&quot;&gt;Setting up a Build Server&lt;&#x2F;h2&gt;
&lt;p&gt;SSH to the server as &lt;code&gt;root&lt;&#x2F;code&gt; or any &lt;code&gt;sudo&lt;&#x2F;code&gt;-capable user.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll be using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;asdf-vm&#x2F;asdf&quot;&gt;asdf&lt;&#x2F;a&gt; to manage our development dependencies
(erlang, elixir, and nodejs). This allows us to install a plurality of
versions in case you have to build different projects requiring
different versions from the same build user.&lt;&#x2F;p&gt;
&lt;p&gt;First we&#x27;ll install some prerequisites via &lt;code&gt;apt&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install -y git vim unzip \
    build-essential autoconf m4 libncurses5-dev \
    libwxgtk3.0-dev libgl1-mesa-dev libglu1-mesa-dev \
    libpng3 libssh-dev unixodbc-dev
sudo update-alternatives --set editor &#x2F;usr&#x2F;bin&#x2F;vim.basic
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now create a build user.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;sudo useradd --shell=&#x2F;bin&#x2F;bash build
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You should install any applicable SSH key for the &lt;code&gt;build&lt;&#x2F;code&gt; user into
&lt;code&gt;~build&#x2F;.ssh&#x2F;authorized_keys&lt;&#x2F;code&gt; now.&lt;&#x2F;p&gt;
&lt;p&gt;Login as the &lt;code&gt;build&lt;&#x2F;code&gt; user now and install asdf and its plugins.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;git clone https:&#x2F;&#x2F;github.com&#x2F;asdf-vm&#x2F;asdf.git ~&#x2F;.asdf
echo &#x27;. $HOME&#x2F;.asdf&#x2F;asdf.sh&#x27; &amp;gt;&amp;gt; ~&#x2F;.profile
echo &#x27;. $HOME&#x2F;.asdf&#x2F;completions&#x2F;asdf.bash&#x27; &amp;gt;&amp;gt; ~&#x2F;.profile
source ~&#x2F;.profile
asdf plugin-add erlang https:&#x2F;&#x2F;github.com&#x2F;asdf-vm&#x2F;asdf-erlang.git
asdf plugin-add elixir https:&#x2F;&#x2F;github.com&#x2F;asdf-vm&#x2F;asdf-elixir.git
asdf plugin-add nodejs https:&#x2F;&#x2F;github.com&#x2F;asdf-vm&#x2F;asdf-nodejs.git
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This next step will install the actual tools. This can take a while, so
I suggest separating each command by a comma, then running off to get
something to eat. It can take a moment.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;asdf install erlang 20.1
asdf global  erlang 20.1
asdf install elixir 1.5.2
asdf global  elixir 1.5.2
asdf install nodejs 8.7.0
addf global  nodejs 8.7.0
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; Erlang requires somewhere slightly north of 1GB of RAM to
build successfully, or it dies somewhere in a WxWidgets library compile.
I suggest that you &lt;a href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;community&#x2F;tutorials&#x2F;how-to-add-swap-space-on-ubuntu-16-04&quot;&gt;enable a swapfile&lt;&#x2F;a&gt; during the build if you
have less than 2GB of free RAM before starting the build. As this will
degrade the SSD hardware you&#x27;re probably running on, I suggest you
remove the swapfile after the build is completed.&lt;&#x2F;p&gt;
&lt;p&gt;If this worked, then installing Hex and Rebar will work.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;mix local.hex
mix local.rebar
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Your build server is almost ready to get to work! Create the
&lt;code&gt;my-app_prod.secret.exs&lt;&#x2F;code&gt; file, which should follow the following
template.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;vim my-app_prod.secret.exs
  use Mix.Config

  config :my_app, MyApp.Repo,
    adapter: Ecto.Adapters.Postgres,
    username: &amp;quot;u&amp;quot;,
    password: &amp;quot;p&amp;quot;,
    database: &amp;quot;d&amp;quot;,
    hostname: &amp;quot;localhost&amp;quot;,
    template: &amp;quot;template0&amp;quot;,
    pool_size: 10
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;ll leave the configuration of your PostgreSQL server to you - there
are plenty of tutorials and how-to&#x27;s for it. Suffice it to say, you
should substitute real values where I have left placeholders.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setting-up-a-production-server&quot;&gt;Setting up a Production Server&lt;&#x2F;h2&gt;
&lt;p&gt;Some of these steps will be identical to the steps performed on the
build server. If these servers are the same, you can safely skip the
redundant steps.&lt;&#x2F;p&gt;
&lt;p&gt;First, SSH to the new production server as &lt;code&gt;root&lt;&#x2F;code&gt; or a &lt;code&gt;sudo&lt;&#x2F;code&gt;-capable
user. First we&#x27;ll install Elixir and some Erlang dependencies, as well
as PostgreSQL. Again, if this isn&#x27;t your database host, then you might
try omitting some. Also, I&#x27;m not too sure if the Erlang dependencies are
even necessary. If someone does know, please drop me a message.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;sudo useradd -s &#x2F;bin&#x2F;bash my-app
sudo mkdir -p ~my-app&#x2F;.ssh
# add relevant keys to ~my-app&#x2F;.ssh&#x2F;authorized_keys
sudo chown -R my-app:users ~my-app
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On deploy and start the application will be running on port &lt;code&gt;4001&lt;&#x2F;code&gt; or
whatever port you configure in your &lt;code&gt;prod.exs&lt;&#x2F;code&gt; file, so firewall that
sucker up.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;sudo ufw deny 4001
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next configure Nginx to reverse proxy to port &lt;code&gt;4001&lt;&#x2F;code&gt;. Be sure to replace
the IP address with the public IP address of your production server.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;sudo vim &#x2F;etc&#x2F;nginx&#x2F;sites-available&#x2F;my-app.com
  map $http_upgrade $connection_upgrade {
    default upgrade;
    &#x27;&#x27; close;
  }

  server {
    listen 80;
    server_name my-app.com;

    access_log off;

    location &#x2F;.well-known {
      root &#x2F;var&#x2F;www&#x2F;letsencrypt;
      try_files $uri &#x2F;dev&#x2F;null =404;
    }

    location &#x2F; {
      return 301 https:&#x2F;&#x2F;$host$request_uri;
    }
  }

  server {
    listen 443 ssl http2;
    server_name my-app.com;
    access_log off;

    ssl_certificate &#x2F;etc&#x2F;letsencrypt&#x2F;live&#x2F;my-app.com&#x2F;fullchain.pem;
    ssl_certificate_key &#x2F;etc&#x2F;letsencrypt&#x2F;live&#x2F;my-app.com&#x2F;privkey.pem;

    location &#x2F; {
      proxy_pass http:&#x2F;&#x2F;127.0.0.1:4001;

      include proxy_params;

      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
    }
  }
sudo ln -s &#x2F;etc&#x2F;nginx&#x2F;sites-{available,enabled}&#x2F;my-app.com
sudo service nginx reload
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally, set the app to autostart on machine boot. So that random things
like rebooting for a kernel update doesn&#x27;t leave the app high and dry
until someone pokes you on Slack.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;sudo vim &#x2F;etc&#x2F;init.d&#x2F;my-app-prod.conf
  description &amp;quot;my-app-prod&amp;quot;

  ## Uncomment the following two lines to run the
  ## application as www-data:www-data
  setuid my-app
  setgid my-app

  start on runlevel [2345]
  stop on runlevel [016]

  expect stop
  respawn

  env MIX_ENV=prod
  export MIX_ENV

  ## Uncomment the following two lines if we configured
  ## our port with an environment variable.
  # env PORT=4001
  # export PORT

  env HOME=&#x2F;home&#x2F;my-app&#x2F;my_app
  export HOME

  pre-start exec &#x2F;bin&#x2F;sh &#x2F;home&#x2F;my-app&#x2F;my_app&#x2F;bin&#x2F;my_app start

  post-stop exec &#x2F;bin&#x2F;sh &#x2F;home&#x2F;my-app&#x2F;my_app&#x2F;bin&#x2F;my_app stop
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;configuring-your-phoenix-project&quot;&gt;Configuring your Phoenix Project&lt;&#x2F;h2&gt;
&lt;p&gt;There isn&#x27;t a whole lot to do here, but some of these steps are
important and missing one can lead to about a day of very confused
debugging.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;vim config&#x2F;prod.exs
  use Mix.Config

  config :my_app, MyApp.Endpoint,
    http: [port: 4001], # configure the port to rproxy to here!
    url: [host: &amp;quot;my_app.com&amp;quot;, port: 80],
    cache_static_manifest: &amp;quot;priv&#x2F;static&#x2F;manifest.json&amp;quot;,
    server: true # DON&#x27;T FORGET THIS LINE

  config :logger, level: :info

  import_config &amp;quot;prod.secret.exs&amp;quot;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There will be a mess of comments in there, I haven&#x27;t explored what they
all do yet.&lt;&#x2F;p&gt;
&lt;p&gt;The next file to change is &lt;code&gt;mix.exs&lt;&#x2F;code&gt;, which you need to add edeliver to
as a dependency.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;vim mix.exs
  # ...

  def application do
    [mod: {MyApp, []},
     applications: [:phoenix, :phoenix_pubsub, :phoenix_html, :cowboy,
                    :logger, :gettext, :phoenix_ecto, :postgrex, :edeliver]]
  end

  # ...

  defp deps do
    [{:phoenix, &amp;quot;~&amp;gt; 1.2.0&amp;quot;},
     {:postgrex, &amp;quot;&amp;gt;= 0.11.2&amp;quot;},
     {:phoenix_ecto, &amp;quot;~&amp;gt; 3.0&amp;quot;},
     {:phoenix_html, &amp;quot;~&amp;gt; 2.6.1&amp;quot;},
     {:phoenix_live_reload, &amp;quot;~&amp;gt; 1.0.5&amp;quot;, only: :dev},
     {:gettext, &amp;quot;~&amp;gt; 0.11&amp;quot;},
     {:cowboy, &amp;quot;~&amp;gt; 1.0.4&amp;quot;},
     {:edeliver, &amp;quot;~&amp;gt; 1.4.3&amp;quot;}]
  end
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You&#x27;ll notice that we&#x27;ve added edeliver to both applications and deps.
Note that there is a release version in this file. You can and should
increment that from time to time. It&#x27;ll show up in your builds -
speaking of which, we need to configure edeliver to know about all the
work we&#x27;ve just done! Do this by creating an edeliver configuration
file, that should look something like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;mkdir -p .deliver
vim .deliver&#x2F;config
  #!&#x2F;usr&#x2F;bin&#x2F;env bash

  APP=&amp;quot;my_app&amp;quot; # name of your release

  # You can experiment around with this to see what you like best.
  # I&#x27;m a retard, so I build a lot without incrementing the version
  # number, so I like having the extra info. More disciplined developers
  # can probably forgo that, however.
  AUTO_VERSION=&amp;quot;commit-count+branch+git-revision&amp;quot;

  BUILD_HOST=&amp;quot;build.my-app.com&amp;quot; # host where to build the release
  BUILD_USER=&amp;quot;build&amp;quot; # local user at build host
  BUILD_AT=&amp;quot;&#x2F;home&#x2F;build&#x2F;builds&#x2F;my_app&amp;quot; # build directory on build host

  # I don&#x27;t use any staging servers, so these are really kind of
  # moot point for me. #YOLO
  STAGING_HOSTS=&amp;quot;stage-01.my-app.com&amp;quot;
  STAGING_USER=&amp;quot;my-app-stage&amp;quot;
  TEST_AT=&amp;quot;&#x2F;home&#x2F;my-app-stage&amp;quot;

  PRODUCTION_HOSTS=&amp;quot;my-app.com&amp;quot;
  PRODUCTION_USER=&amp;quot;my-app&amp;quot;
  DELIVER_TO=&amp;quot;&#x2F;home&#x2F;my-app&amp;quot;

  # runs the phoenix.digest mix command, which gets rid of a missing
  # manifest file error
  pre_erlang_clean_compile() {
    status &amp;quot;Installing NodeJS dependencies&amp;quot;
    __sync_remote &amp;quot;
      [ -f ~&#x2F;.profile ] &amp;amp;&amp;amp; source ~&#x2F;.profile # load profile (optional)
      set -e # fail if any command fails (recommended)
      cd &#x27;$BUILD_AT&#x27; # enter the build directory on the build host (required)
      # prepare something
      mkdir -p priv&#x2F;static # required by the phoenix.digest task
      # run your custom task
      APP=&#x27;$APP&#x27; MIX_ENV=&#x27;$TARGET_MIX_ENV&#x27; npm install
    &amp;quot;
    status &amp;quot;Building frontend items&amp;quot;
    __sync_remote &amp;quot;
      [ -f ~&#x2F;.profile ] &amp;amp;&amp;amp; source ~&#x2F;.profile # load profile (optional)
      set -e # fail if any command fails (recommended)
      cd &#x27;$BUILD_AT&#x27; # enter the build directory on the build host (required)
      # prepare something
      mkdir -p priv&#x2F;static # required by the phoenix.digest task
      # run your custom task
      APP=&#x27;$APP&#x27; MIX_ENV=&#x27;$TARGET_MIX_ENV&#x27; npm run deploy
    &amp;quot;
    status &amp;quot;Running phoenix.digest&amp;quot; # log output prepended with &amp;quot;-----&amp;gt;&amp;quot;
    __sync_remote &amp;quot; # runs the commands on the build host
      [ -f ~&#x2F;.profile ] &amp;amp;&amp;amp; source ~&#x2F;.profile # load profile (optional)
      set -e # fail if any command fails (recommended)
      cd &#x27;$BUILD_AT&#x27; # enter the build directory on the build host (required)
      # prepare something
      mkdir -p priv&#x2F;static # required by the phoenix.digest task
      # run your custom task
      APP=&#x27;$APP&#x27; MIX_ENV=&#x27;$TARGET_MIX_ENV&#x27; $MIX_CMD phoenix.digest $SILENCE
    &amp;quot;
  }

  # copies the prod.secret.exs file you keep sequestered on your build
  # machine into the build directory.
  pre_erlang_get_and_update_deps() {
    # copy it on the build host to the build directory when building
    local _secret_config_file_on_build_host=&amp;quot;&#x2F;home&#x2F;build&#x2F;my-app_prod.secret.exs&amp;quot;
    if [ &amp;quot;$TARGET_MIX_ENV&amp;quot; = &amp;quot;prod&amp;quot; ]; then
      status &amp;quot;Linking &#x27;$_secret_config_file_on_build_host&#x27; to build config dir&amp;quot;
      __sync_remote &amp;quot;
        ln -sfn &#x27;$_secret_config_file_on_build_host&#x27; &#x27;$BUILD_AT&#x2F;config&#x2F;prod.secret.exs&#x27;
      &amp;quot;
    fi
  }
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;building-and-deploying-a-release&quot;&gt;Building and Deploying a Release&lt;&#x2F;h2&gt;
&lt;p&gt;All this work, and it boils down to some very simple commands!&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;mix edeliver build release
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Copy the release tag from the output, and deploy that sucker.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;mix edeliver deploy release to production --version=&amp;lt;&amp;lt;that release tag&amp;gt;&amp;gt;
mix edeliver start production
mix edeliver migrate production # runs your database migrations!
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;All that work, but look at what was gained! A very slick deployment
process that encourages sustainable versioning. These have been my notes
from the adventure, which I hope you benefit from in some way. If you
find any error, I encourage you to let me know, preferably by making a
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mysteriouspants&#x2F;mysteriouspants.com&#x2F;blob&#x2F;master&#x2F;_posts&#x2F;2016-07-18-deploying-phoenix.md&quot;&gt;pull request on this file&lt;&#x2F;a&gt; with the fix.&lt;&#x2F;p&gt;
&lt;p&gt;Happy coding, and more importantly, happy deploying, 314!&lt;&#x2F;p&gt;
</description>
            </item>
        
            <item>
                <title></title>
                <pubDate>Wed, 02 Mar 2016 00:00:00 +0000</pubDate>
                <link>https://www.mysteriouspants.com/sig/</link>
                <guid>https://www.mysteriouspants.com/sig/</guid>
                <description>&lt;p&gt;&lt;em&gt;8 July 2011, 11:26:46 AM Eastern Daylight Time&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&amp;quot;A thousand strangers chanted together with the countdown. And then it
happened.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;sig&#x2F;STS-135_begins_takeoff.jpg&quot;&gt;&lt;img src=&quot;&#x2F;sig&#x2F;STS-135_begins_takeoff.jpg&quot; alt=&quot;STS-135 begins takeoff&quot; style=&quot;float: left; margin-right: 0.75em; margin-bottom: 0.75em; width: 50%;&quot;&#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&amp;quot;The massive clouds of smoke billowed out the sides of the tower poking
out above the trees. The shuttle rising slowly, and then faster. And
then the noise shaking your guts from over 3 miles away. As the shuttle
gets higher you see this column of fire pushing it up faster and faster.&lt;&#x2F;p&gt;
&lt;p&gt;&amp;quot;And then it was gone: lost in the clouds. The last time human eyes will
see a shuttle leave a launchpad.&lt;&#x2F;p&gt;
&lt;p&gt;&amp;quot;I actually teared up, but I&#x27;m pretty sure nobody noticed me wiping my
eyes with my shirt. The folks closest to me know that this isn&#x27;t exactly
an uncommon event for me, but I felt it all come back: A little kid
alone in his basement building a puzzle of the shuttle, dreaming of
space. &lt;a href=&quot;&#x2F;sig&#x2F;STS-135_launch_viewed_from_Shuttle_Training_Aircraft.jpg&quot;&gt;&lt;img src=&quot;&#x2F;sig&#x2F;STS-135_launch_viewed_from_Shuttle_Training_Aircraft.jpg&quot; alt=&quot;STS-135 viewed from Shuttle Training Aircraft&quot; style=&quot;float: right; margin-left: 0.75em; margin-bottom: 0.75em; width: 50%;&quot;&#x2F;&gt;&lt;&#x2F;a&gt; Seeing Challenger through the library window on a day when I was
too young to understand what it meant for 7 people to die in the name of
science exploration. I learned about computers because of all this
stuff. The Space Shuttle was an honest to god spaceship. It filled the
gap between science fiction and science reality.&lt;&#x2F;p&gt;
&lt;p&gt;&amp;quot;I have a 3 year old now, and I told him before I left that I was going
to go see a Spaceship, and I think he thought I was lying. He knows the
Millennium Falcon is a spaceship, but that it&#x27;s also pretend. &lt;em&gt;Atlantis&lt;&#x2F;em&gt;
was real. I saw it with my own eyes with a tower of fire underneath it.
It shook my body and I hope my sons have something to inspire them the
same way.&lt;&#x2F;p&gt;
&lt;p&gt;&amp;quot;But where is the shared mission to be bigger, louder, higher, faster and
further than anything that came before? What are we doing that will
inspire a 6 year-old to sit in the dark in his basement and dream over a
puzzle?&amp;quot;&lt;&#x2F;p&gt;
&lt;p&gt;- Rob &amp;quot;CmdrTaco&amp;quot; Malda&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;science.slashdot.org&#x2F;story&#x2F;11&#x2F;07&#x2F;11&#x2F;1559219&#x2F;cmdrtaco-watches-atlantis-liftoff&quot;&gt;science.slashdot.org&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
&lt;a href=&quot;http:&#x2F;&#x2F;www.washingtonpost.com&#x2F;national&#x2F;on-innovations&#x2F;shuttling-the-shuttle-discoverys-last-flight&#x2F;2012&#x2F;04&#x2F;18&#x2F;gIQA1wmMRT_story.html&quot;&gt;washingtonpost.com&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;&#x2F;sig&#x2F;launchDay-by-stanleyVonMedvey.jpg&quot; alt=&quot;Launch Day by Stanley Von Medvey&quot; width=&quot;100%&quot; &#x2F;&gt;
  &lt;figcaption&gt;&lt;i&gt;Launch Day&lt;&#x2F;i&gt; by Stanley Von Medvey&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
</description>
            </item>
        
            <item>
                <title>The Case of the Leaky Pool</title>
                <pubDate>Tue, 04 Dec 2012 00:00:00 +0000</pubDate>
                <link>https://www.mysteriouspants.com/blog/leaky-pool/</link>
                <guid>https://www.mysteriouspants.com/blog/leaky-pool/</guid>
                <description>&lt;p&gt;It always has to happen right before your system administrator leaves on vacation. The game is set, the stakes are high, and nobody is willing to fold. It was at a time like this that the Java Virtual Machine (JVM) on our second production server was discovered to be leaking memory like a gangster leaking blood in the Valentine&#x27;s Day Massacre. Unlike the mafiosos in Chicago, we couldn&#x27;t figure out why our JVM was bleeding.&lt;&#x2F;p&gt;
&lt;!--more--&gt;
&lt;p&gt;&lt;em&gt;Note that this post is best read in a 1920&#x27;s-style detective voice. I tried to have fun with the writing style, so just give it a go, OK? You might want to go re-read that first paragraph again, 314, just for practice. Additionally, some of the technical information might be slightly off-base (though I&#x27;m pretty certain that it&#x27;s not too far from the truth;) if you know better, please consider doing me a favor and letting me know in the comments section! I&#x27;d love the correction!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Like any good beat, we got two production servers with a fat load balancer in front. &lt;code&gt;app01.prod&lt;&#x2F;code&gt; is usually the point man, with &lt;code&gt;app02.prod&lt;&#x2F;code&gt; ready to take the heat if &lt;code&gt;app01.prod&lt;&#x2F;code&gt; gets iced. The cool kids call it a &amp;quot;hot failover,&amp;quot; but me? I just call it smart.&lt;&#x2F;p&gt;
&lt;p&gt;And being smart paid off. On Monday we looked at our Munin graphs to check in on the situation. The admin likes to do that before he checks out. Whether for peace of mind, or through grizzled experience doesn&#x27;t matter as much. Our monitoring reported all systems normal - except &lt;code&gt;app02.prod&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;&#x2F;leaky-pool&#x2F;app02_prod_proxy_memory_use_day4.png&quot; alt=&quot;graphs!&quot;&gt;
  &lt;figcaption&gt;app02.prod.proxy memory-use-day4&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;Unlike most smart shops, we were running a different setup. &lt;code&gt;app01.prod&lt;&#x2F;code&gt; was running our code using Apache Passenger and MRI Ruby 1.8.7. It was the first gig we could get in the club of the corporate private cloud. The bouncer wouldn&#x27;t let any cool toys inside the party, so we had to dance to the music they played.&lt;&#x2F;p&gt;
&lt;p&gt;But that was a year and a half ago, and the bouncer changed his mind. And we got good at smuggling.&lt;&#x2F;p&gt;
&lt;p&gt;We were running into teething issues with MRI 1.8.7. MRI&#x2F;YARV 1.9.3 has been roaming the streets for a while now, and we&#x27;re not sure we want to be stuck on yesterday&#x27;s ride. With MRI&#x2F;YARV 2.0 just around the corner, it made sense to make a push for a better stack. So for the past four months we&#x27;ve been in the garage trying to refit the old car for a new trick: JRuby.&lt;&#x2F;p&gt;
&lt;p&gt;Particularly handy is the JRuby way of deploying to J2EE servers, which we can push into the private cloud like we own the joint. The whole organization is chill with anything Java, so we&#x27;re golden, right? Just grab a server, stand it up, and we&#x27;re in to the hottest cloud in town. A quick snoop around the scene shows a few promising candidates. I could deploy through GlassFish and cut WAR files using Warbler. I like GlassFish. I used it before at an old job. We go way back, GlassFish and I.&lt;&#x2F;p&gt;
&lt;p&gt;Or I could try this new kid on the block. It supports clustering, queues, and scheduled tasks. Long-running requests (for WebSockets and such) are included. I wryly thought back to a few dirty hacks I had running with &lt;code&gt;delayed_job&lt;&#x2F;code&gt;. Yeah, this &lt;a href=&quot;http:&#x2F;&#x2F;torquebox.org&#x2F;&quot;&gt;TorqueBox&lt;&#x2F;a&gt; kid is the right tool for the job. I tossed out the hacks and spruced up the app, and faster than you could say &amp;quot;UTF-8&amp;quot; it worked.&lt;&#x2F;p&gt;
&lt;p&gt;The sysadmin packaged up TorqueBox into a Debian package so we could install it in our private cloud on our production servers. Because of some legacy decisions in our build servers we had to take the whole &lt;code&gt;.tar.gz&lt;&#x2F;code&gt; file and rename it &lt;code&gt;.png&lt;&#x2F;code&gt;, then un-tar that in a post-install script. Yeah, we got good at smuggling. But it beat the bouncers, and we had our best tools inside the club for the first time.&lt;&#x2F;p&gt;
&lt;p&gt;But it&#x27;s not all roses when you&#x27;re trying to deploy something as complex as this. You look at a cron-style task schedule the wrong way and you can find yourself in a world of pain. Like I did this past week.&lt;&#x2F;p&gt;
&lt;p&gt;The leak was huge. We weren&#x27;t really sure how it could leak 18GB of memory on a 6GB dime, but it had. And the sysadmin was on his way out the door. In order to keep our production systems reliable he tore down &lt;code&gt;app02.prod&lt;&#x2F;code&gt;, which was running our experimental TorqueBox server, and restored it to running the same Apache&#x2F;Passenger MRI 1.8.7 gig that &lt;code&gt;app01.prod&lt;&#x2F;code&gt; is running. If &lt;code&gt;app01.prod&lt;&#x2F;code&gt; gets iced, &lt;code&gt;app02.prod&lt;&#x2F;code&gt; will be at least as good as it was. And ain&#x27;t nobody wanted to think about what would happen if they both went down in a hail of requests. There are some things too horrifying to plan for.&lt;&#x2F;p&gt;
&lt;p&gt;This put my investigation in a pickle. The memory leak was only manifesting on &lt;code&gt;app02.prod&lt;&#x2F;code&gt;, and without the extant bug, it was my job to try and replicate it. I started spinning up VirtualBox VMs and tried to start replicating the bug in an environment as close to prod as was possible. But again, the sysadmin saved me.&lt;&#x2F;p&gt;
&lt;p&gt;He installed Munin on a little-known dame sitting in the other aisle, &lt;code&gt;app01.stage&lt;&#x2F;code&gt;, where we try out our new kicks before promoting them to a full prod showing.&lt;&#x2F;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;&#x2F;leaky-pool&#x2F;app01_stage__proxy_leak_day2.png&quot; alt=&quot;graphs!&quot;&gt;
  &lt;figcaption&gt;app01.stage.proxy leak-day2&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;Stage was showing the same kind of problem as prod: an 18GB memory leak. &lt;code&gt;app01.stage&lt;&#x2F;code&gt; had been booted around the same time we last rebooted &lt;code&gt;app02.prod&lt;&#x2F;code&gt;, so the similar velocity in leak proved that we had the same dirt bag in our sights. The sysadmin left for the week, leaving me with &lt;code&gt;app01.stage&lt;&#x2F;code&gt; and a bug to find.&lt;&#x2F;p&gt;
&lt;p&gt;I spun down my VMs and SSH&#x27;d into &lt;code&gt;app01.stage&lt;&#x2F;code&gt; to take a look. I didn&#x27;t think I&#x27;d find anything, but it was worth a try. The system was stable, and it seemed to think that the culprit JVM was only taking 800MB of memory.&lt;&#x2F;p&gt;
&lt;p&gt;A clue!&lt;&#x2F;p&gt;
&lt;p&gt;I looked at the graph again. Munin says it was taking well beyond the memory space, yet there wasn&#x27;t any swap activity. Years of tracking down bugs hadn&#x27;t prepared me for this. But a crash-course in memory mapping I&#x27;d taken when experimenting with &lt;code&gt;libdispatch&lt;&#x2F;code&gt;&#x27;s I&#x2F;O facilities had prepared me for this. Funny how the gigs you take for fun end up saving you in the end!&lt;&#x2F;p&gt;
&lt;p&gt;What I learned from &lt;code&gt;libdispatch&lt;&#x2F;code&gt; is that all programs are incurably greedy.&lt;&#x2F;p&gt;
&lt;p&gt;They allocate a city of memory, but only ever use a few blocks. Maybe they just keep the rest for a rainy day? Back in the old days of DOS and tommy guns this wasn&#x27;t a concern. You only ever ran a program at a time, and so nobody cared that the racketeers were running away with the city hall. There was one capo and he set The Rules. Life was simpler back then.&lt;&#x2F;p&gt;
&lt;p&gt;But the world got bigger, and more gangs started vying for the limelight. And they all wanted the same city - all of it. So we give it to them. All of it. And things got more complex.&lt;&#x2F;p&gt;
&lt;p&gt;When a program allocates memory, it runs through a call to either &lt;code&gt;malloc&lt;&#x2F;code&gt; or &lt;code&gt;calloc&lt;&#x2F;code&gt;, and a few others. But those are the big two. &lt;code&gt;malloc&lt;&#x2F;code&gt; returns unformatted memory, while &lt;code&gt;calloc&lt;&#x2F;code&gt; fills the memory with zeroes. &lt;code&gt;malloc&lt;&#x2F;code&gt; and &lt;code&gt;calloc&lt;&#x2F;code&gt; themselves chains down through the local runtime memory manager to see if it has free memory in a held page.&lt;&#x2F;p&gt;
&lt;p&gt;Memory is cordoned off into pages, like the blocks of a city. Unlike a city block, only one program can own a single page at a time - we can&#x27;t split &#x27;em up. So the local runtime has a small memory manager which will try and give you parts of existing pages it holds when you need more memory. If you have a 4KB page, and you have used 1KB of it, and you ask for 2KB of memory, it should give you part of that existing page. There are tools like guard malloc which change this slightly, but for everyone else this is the way it works.&lt;&#x2F;p&gt;
&lt;p&gt;If the local memory manager doesn&#x27;t have the memory, it hits the operating system kernel.&lt;&#x2F;p&gt;
&lt;p&gt;Now, kernels are smart. They know that programs are greedy, and so they cheat them. When the program &lt;code&gt;malloc&lt;&#x2F;code&gt;&#x27;s a fat load of memory, the kernel just pretends to give it what it wants. But in reality it just gives it pages of memory. Address space. Imaginary property. A deed with no land. Smoke and mirrors. A mirage. It even does this for &lt;code&gt;calloc&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In Linux and Darwin (a FreeBSD fork), the kernel allocates a page of all-zero memory. Whenever a made man demands a leveled (zero-filled) block, the kernel gives him one, but it just forwards to that pre-made zero page. The mafioso can go look at the page and read it all. Everything&#x27;s zeroes. And that page is shared between potentially hundreds of gangsters at a time. It&#x27;s a city of addresses which all go to the same vacant lot. It&#x27;s deception on a grand scale!&lt;&#x2F;p&gt;
&lt;p&gt;The trick happens when they try to build a safe house on that block. The moment that they try to write to that zero-filled page, the kernel gets wise and creates a zero-filled page, then hands that right over to the program. Because of CPU-level magic, the address doesn&#x27;t change - everything is still distinct. If a page size is 4KB (which is typical), and a program asks for 2040KB of zero-filled pages, that program will get 510 pages which all map back to a single zero-filled page.&lt;&#x2F;p&gt;
&lt;p&gt;The program has 2040KB of address space allocated, but is only taking 0KB of physical memory.&lt;&#x2F;p&gt;
&lt;p&gt;The kernel beat the system, and over-sold the city.&lt;&#x2F;p&gt;
&lt;p&gt;When that program tries to write to that first page, the kernel fixes the situation and hands the program a real page, so now the program has 509 references to the shared page and one reference to a real, private page. It&#x27;s a slick trick called &amp;quot;Copy on Write.&amp;quot;&lt;&#x2F;p&gt;
&lt;p&gt;Now, the linearly increasing line on the Munin graph is showing the &lt;em&gt;committed memory&lt;&#x2F;em&gt;, which is address space given to programs, but which may or may not actually be used. That the real memory graph down below is incredibly low suggests that the program, in this case the JVM, is allocating lots of memory, but never touching it. Because of the fancy footwork on part of the kernel, this prevented the program from crashing due to a memory shortage.&lt;&#x2F;p&gt;
&lt;p&gt;Believe it or not, this narrows down the culprit significantly. But it requires some savvy with the JVM itself.&lt;&#x2F;p&gt;
&lt;p&gt;The JVM, as a virtual machine, allocates a heap space, usually something fairly large, like 64MB. It also enforces a heap space ceiling, usually at 256MB. In my server&#x27;s case, the JVM started with 64MB and had a ceiling of 512MB. But it also has a &amp;quot;permanent generation&amp;quot; space, which in this case was 256MB. This is where class definitions live, and other such things.&lt;&#x2F;p&gt;
&lt;p&gt;Anything Java, and by extension JRuby, is going to live in the Java heap space. Because of how the heap works, it won&#x27;t be living in mapped pages, so it should always be in physical RAM. To prove this, I used a tool called VisualVM to get a bug in their court. I watched the gang, and they never knew any better.&lt;&#x2F;p&gt;
&lt;p&gt;At first I installed VisualVM on my iMac, and then enabled the remote JMX connector on &lt;code&gt;app01.stage&lt;&#x2F;code&gt;. But then the corporate firewall blocked everything. A few experiments with SSH port forwarding similarly failed. I needed a way in, or I couldn&#x27;t see if I was right.&lt;&#x2F;p&gt;
&lt;p&gt;So I cheated. I ran &lt;code&gt;wget&lt;&#x2F;code&gt; on &lt;code&gt;app01.stage&lt;&#x2F;code&gt; to put VisualVM on the staging server, which is running headless. Then I ran SSH with X11 forwarding to put that window onto my local X server (XQuartz for Mac).&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;ssh -X app01.stage &#x2F;root&#x2F;visualvm&#x2F;bin&#x2F;visualvm
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I had a way in. And it didn&#x27;t look bad. These mafia types are much nicer than the drug runners from LA.&lt;&#x2F;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;&#x2F;leaky-pool&#x2F;app01_stage__proxy_visualvm_threadleak_day2.png&quot; alt=&quot;magic applications!&quot;&gt;
  &lt;figcaption&gt;app01.stage.proxy visualvm-threadleak-day2&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;The heap space is normal. So it&#x27;s something causing a memory allocation that&#x27;s going deeper in the JVM.&lt;&#x2F;p&gt;
&lt;p&gt;Another clue.&lt;&#x2F;p&gt;
&lt;p&gt;This narrows down the list of suspects a lot. Nothing pure-Java or pure-JRuby will be doing this. It has to be a native call. Something is leaking inside the JVM itself.&lt;&#x2F;p&gt;
&lt;p&gt;I called in my friends. TorqueBox and JRuby have friendly, helpful communities. I hopped on IRC, my favorite diner, &lt;code&gt;freenode.net&lt;&#x2F;code&gt;, and poked the folks in &lt;code&gt;#torquebox&lt;&#x2F;code&gt; and &lt;code&gt;#jruby&lt;&#x2F;code&gt;. They confirmed my suspicions throughout. I&#x27;m on the right track.&lt;&#x2F;p&gt;
&lt;p&gt;After an APB to Google, I found a tool called &lt;code&gt;pmap&lt;&#x2F;code&gt;, which shows all allocated memory space for a process. Given that I was profiling a JVM with a full enterprise stack, running in a clustered High-Availability mode, there was a lot of stuff. I saw the Java heap space, the permanent generation space, as well as a few memory-mapped files.&lt;&#x2F;p&gt;
&lt;p&gt;The kernel is tricky again. When you read a file into memory, it will pretend to do so. Using the same ideas behind copy-on-write, it will expose the whole file&#x27;s length to your address space, but will swap out the actual memory. This partial in-memory caching can save big on space without impacting performance too much. &lt;code&gt;pmap&lt;&#x2F;code&gt; shows you files mapped to memory, which really helps to figure out what memory is doing what. Throw away all the files and you&#x27;re left with potentials for leaks.&lt;&#x2F;p&gt;
&lt;p&gt;But most interesting to me were hundreds of 2040KB &amp;quot;anonymous&amp;quot; pages. An anonymous page isn&#x27;t mapped to a specific file or network stream. It&#x27;s memory the program has allocated because the program needs memory. The Java heap space was a huge 300MB anonymous memory block. The permanent generation space was a similarly large 250MB anonymous memory block.&lt;&#x2F;p&gt;
&lt;p&gt;But what are these 2040KB blocks? And they were &lt;em&gt;all&lt;&#x2F;em&gt; &lt;strong&gt;exactly&lt;&#x2F;strong&gt; 2040KB.&lt;&#x2F;p&gt;
&lt;p&gt;By piping &lt;code&gt;pmap&lt;&#x2F;code&gt; into &lt;code&gt;grep&lt;&#x2F;code&gt;, I started counting them:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;pmap 3248 | grep -c &amp;quot;2040K\\ rwx--\\ \\ \\ \\ \\[\\ anon\\ \\]&amp;quot;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I would run that, wait a little while, then run it again. I was getting another 2040KB allocation every minute. Then I noticed the VisualVM window behind that. I noticed the VM thread count.&lt;&#x2F;p&gt;
&lt;p&gt;1,740 threads sounds a little high, and it&#x27;s climbing. I know it&#x27;s an enterprise application server, but 1,740 is gratuitous. And I have 1,741 2040KB pages.&lt;&#x2F;p&gt;
&lt;p&gt;And the default stack size for a thread is 2040KB. After a few more minutes of watching, I&#x27;m sure. There&#x27;s a huge thread leak. Something is creating threads and never destroying them when it&#x27;s done.&lt;&#x2F;p&gt;
&lt;p&gt;VisualVM has a thread tab, which shows pure chaos: among the normal threads are around 1,550 threads, all helpfully named things like &lt;code&gt;pool-1350-thread-1&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Another clue.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not just leaking threads, it&#x27;s leaking thread pools with just one thread in them. That narrows it down a lot. Lots of code creates threads, but less code creates thread pools.&lt;&#x2F;p&gt;
&lt;p&gt;At this point I&#x27;m sure as Machine Gun Kelly&#x27;s spit that it&#x27;s thread leaks. A thread allocates a stack which lives outside the heap space, which fits the M.O. of the leak perfectly. My TorqueBox and JRuby associates on IRC heartily agreed.&lt;&#x2F;p&gt;
&lt;p&gt;My application doesn&#x27;t perform any manual threading, so it&#x27;s all going to be something from a underlying framework. The list of possibilities was nauseatingly endless, however:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;oauth&lt;&#x2F;code&gt;, which shouldn&#x27;t be spawning thread pools every minute. But it&#x27;s possible. It has to whack an external server and check back, so it could be using a thread.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;jdbc-mysql&lt;&#x2F;code&gt;, which could very well be naughty with threads. I wasn&#x27;t too sure though. This one&#x27;s been through a lot, and he doesn&#x27;t seem like the type to simply throw caution to the wind and start doing illegal things.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;torquebox&lt;&#x2F;code&gt;, which gets me crazy fun distributed caching and session stores, as well as exposes a logger which chains down to the JBoss AS 7 logger.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;torquebox-messaging&lt;&#x2F;code&gt;, used to enqueue a delayed job.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The hunt went on. I started commenting out code and disabling parts of my app to try and shake out the leak, which helpfully reproduced on my iMac without complaint. But the app was too big, too complex to start tearing out suspects. I needed another in.&lt;&#x2F;p&gt;
&lt;p&gt;So I started a new, blank Rails app. I started a TorqueBox server, installed the app, and watched the thread count. The leak wasn&#x27;t there - good.&lt;&#x2F;p&gt;
&lt;p&gt;I added a few render-able pages, and checked the session for a user id (to verify that it wasn&#x27;t happening somewhere in the Infinispan cache). Still no leak.&lt;&#x2F;p&gt;
&lt;p&gt;I added a scheduled task. I had a scheduled task to run every 15 minutes and another to run every hour on my production app, so I was sure that it wasn&#x27;t in Quartz, the system which dispatches the scheduled tasks. Still no leak.&lt;&#x2F;p&gt;
&lt;p&gt;Then I added something innocent. I added a &lt;em&gt;timeout&lt;&#x2F;em&gt;. TorqueBox, via Quartz, will enforce a timeout on your tasks, notifying them when they should stop running. And sure enough, that timeout spawned a thread pool with a single thread to effect that notification, but there was no code to clean up that thread when it finished.&lt;&#x2F;p&gt;
&lt;p&gt;I looked at my production application. I had made a mistake. My hourly task was firing every minute, hence the leaked thread pool every minute. If I had caught that mistake I might have suspected the scheduled task earlier, and thereby caught the bug faster. Or I could have fixed it and never seen the bug again because one hour is far too intermittent to try and track down a single thread leak. My timeout was correctly set at 59 minutes, but even so, after that 59 minutes the timeout should have fired and cleaned itself up.&lt;&#x2F;p&gt;
&lt;p&gt;However, the important thing is that I caught the leaker red-handed. I had the whole police department surrounding the building, so I sent in a SWAT team to rustle out the no-good. I sent in one of the TorqueBox lead developers, Benjamin Browning. (&lt;em&gt;Or rather he decided to help fix this of his own volition, but just work with the writing style a bit, please&lt;&#x2F;em&gt;). He raced through the TorqueBox (and JBoss Polyglot) code base and discovered &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;projectodd&#x2F;jboss-polyglot&#x2F;blob&#x2F;f5a82960e2443a7701154decec8174f0c43ab281&#x2F;jobs&#x2F;src&#x2F;main&#x2F;java&#x2F;org&#x2F;projectodd&#x2F;polyglot&#x2F;jobs&#x2F;TimeoutListener.java#L43&quot;&gt;the culprit&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And Benjamin Browning, being the awesome person he is, &lt;a href=&quot;https:&#x2F;&#x2F;issues.jboss.org&#x2F;browse&#x2F;TORQUE-976&quot;&gt;fixed it&lt;&#x2F;a&gt;. People using TorqueBox 2.2.0 will never have to worry about their scheduled tasks leaking timeout threads.&lt;&#x2F;p&gt;
&lt;p&gt;As I sat at my desk in the middle of the bullpen that afternoon I leaned back in my old chair and grinned. I was a heck of a chase, but in the end, I found the bad guy, and we brought him to justice.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;There were a few other steps I didn&#x27;t mention, such as a cryptic spawn-stack trace I saw using a trial version of YourKit analyzer. This is also my first attempt at writing like a pulp-fiction crime novel. I hope you enjoyed it, 314!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
            </item>
        
    </channel>
</rss>
