<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<title type="text">Stuart Hinson</title>
<generator uri="https://github.com/jekyll/jekyll">Jekyll</generator>
<link rel="self" type="application/atom+xml" href="https://stuarth.github.io/feed.xml" />
<link rel="alternate" type="text/html" href="https://stuarth.github.io" />
<updated>2021-07-30T19:04:03+00:00</updated>
<id>https://stuarth.github.io/</id>
<author>
  <name>Stuart Hinson</name>
  <uri>https://stuarth.github.io/</uri>
  
</author>


<entry>
  <title type="html"><![CDATA[Rocket v0.5 Error Handling Best Practices]]></title>
  <link rel="alternate" type="text/html" href="https://stuarth.github.io/rocket-error-handling/" />
  <id>https://stuarth.github.io/rocket-error-handling</id>
  <published>2021-07-28T12:36:00+00:00</published>
  <updated>2021-07-28T12:36:00+00:00</updated>
  <author>
    <name>Stuart Hinson</name>
    <uri>https://stuarth.github.io</uri>
    
  </author>
  <content type="html">&lt;p&gt;A common question in &lt;a href=&quot;https://kiwiirc.com/client/irc.libera.chat/#rocket&quot;&gt;#rocket&lt;/a&gt; is how to go beyond the basics in error handling. Specifically, there’s a bit of a jump that’s needed to connect the dots between defining a custom error type (e.g. with &lt;a href=&quot;https://github.com/dtolnay/thiserror&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;thiserror&lt;/code&gt;&lt;/a&gt;) and the &lt;a href=&quot;https://api.rocket.rs/v0.5-rc/rocket/response/trait.Responder.html&quot;&gt;Responder trait&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We can put these together and write handlers with idiomatic early returns, e.g.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;#[derive(Error,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;Debug)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;#[error(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;HTTP Error {source:?}&quot;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;)]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Reqwest&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;#[from]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;reqwest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;#[error(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;SerdeJson Error {source:?}&quot;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;)]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;SerdeJson&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;#[from]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;serde_json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;nd&quot;&gt;#[get(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/hello&quot;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Todo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;// a  https://docs.rs/reqwest/0.11.4/reqwest/struct.Error.html&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;reqwest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://jsonplaceholder.typicode.com/todos/1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;.await&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;.text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;.await&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;// https://docs.serde.rs/serde_json/struct.Error.html&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;todo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Todo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;serde_json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;todo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Setting aside the contrived logic, this is error handling as we’d expect in Rust – we’re leaning on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt; and its implicit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;into&lt;/code&gt; to map errors into our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Error&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;But, in a real-world application, we’re not typically happy to simply render a 500 back to the user. How do we respond differently to different error conditions? How do we log an error into a monitoring service like Sentry?&lt;/p&gt;

&lt;p&gt;Here (and as of 0.5), the best practice I’ve found is to implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Responder&lt;/code&gt; for your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Error&lt;/code&gt; type&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;'r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;'o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;'r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Responder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;'r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;'o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;respond_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;'r&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;'_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;'o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;// log `self` to your favored error tracker, e.g.&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;// sentry::capture_error(&amp;amp;self);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c&quot;&gt;// in our simplistic example, we're happy to respond with the default 500 responder in all cases &lt;/span&gt;
            &lt;span class=&quot;mi&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;InternalServerError&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.respond_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With this approach, we have a natural place to centralize error tracking as well as flexibility in the responses we send from the server. Not bad!&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://stuarth.github.io/rocket-error-handling/&quot;&gt;Rocket v0.5 Error Handling Best Practices&lt;/a&gt; was originally published by Stuart Hinson at &lt;a href=&quot;https://stuarth.github.io&quot;&gt;Stuart Hinson&lt;/a&gt; on July 28, 2021.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Effective (and Simple!) Predictive Recommendations]]></title>
  <link rel="alternate" type="text/html" href="https://stuarth.github.io/machine-learning/" />
  <id>https://stuarth.github.io/machine-learning</id>
  <published>2020-01-22T12:36:00+00:00</published>
  <updated>2020-01-22T12:36:00+00:00</updated>
  <author>
    <name>Stuart Hinson</name>
    <uri>https://stuarth.github.io</uri>
    
  </author>
  <content type="html">&lt;p&gt;I want to give a quick illustration of the idea that effective applications of machine learning – especially early versions – can be almost embarrassingly simple. This is the broad strokes of a system I implemented that produced a substantial lift in revenue for a large online marketplace.&lt;/p&gt;

&lt;p&gt;This marketplace is a bit unusual in that its products are all one of a kind. Every day, we’d list a new batch of products for sale, and the problem I faced was how do I pick which products to recommend to each user.&lt;/p&gt;

&lt;p&gt;That each product was unique meant that the most common solutions for generating recommendations like a correlation matrix couldn’t be applied since we don’t have historical data about what users who’ve bought the same products had also bought. I did notice, however, when I looked into our data that users had a high affinity for particular types of products. At a coarse level, that meant we could use our product categorization as the basis for recommendations.&lt;/p&gt;

&lt;p&gt;The implementation is simple and took less than a plane ride to finish. I wrote a background job that scored each user for their affinity for a category based on usage signals we had available (say, viewing a product, saving a product a wishlist (better signal than just viewing!), purchasing a product (great signal!)), producing a set of scores normalized across our categories that represented each user’s preferences. Those scores were then used when a known user viewed new products to predict which they’d be most interested in.&lt;/p&gt;

&lt;p&gt;Split tests showed a substantial lift in revenue from its introduction.&lt;/p&gt;

&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;There are, of course, a few wrinkles when deploying a system like this. One is the idea that our confidence in our predictions should be proportional to how well we know that user. The less that’s known about a user, the easier it is to make predictions that overfit for the little we do know.&lt;/li&gt;
  &lt;li&gt;Predictive recommendations for engagement are important, but definitely don’t speak to the whole picture for either a user or the business. The ranking system I wrote also incorporated factors like anticipated customer reviews, support workload, customer churn, profitability, etc.&lt;/li&gt;
&lt;/ul&gt;


  &lt;p&gt;&lt;a href=&quot;https://stuarth.github.io/machine-learning/&quot;&gt;Effective (and Simple!) Predictive Recommendations&lt;/a&gt; was originally published by Stuart Hinson at &lt;a href=&quot;https://stuarth.github.io&quot;&gt;Stuart Hinson&lt;/a&gt; on January 22, 2020.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Connecting Remote Controlled Blinds to Alexa Smart Home]]></title>
  <link rel="alternate" type="text/html" href="https://stuarth.github.io/alexa-blinds/" />
  <id>https://stuarth.github.io/alexa-blinds</id>
  <published>2018-09-08T12:36:00+00:00</published>
  <updated>2018-09-08T12:36:00+00:00</updated>
  <author>
    <name>Stuart Hinson</name>
    <uri>https://stuarth.github.io</uri>
    
  </author>
  <content type="html">&lt;p&gt;My intuition is to begin with a bit about the pragmatic motivations for the project, but if I’m being honest this came from a place of ‘I bet I could do this’ rather than ‘what my life needs isn’t remote controlled blinds, it’s &lt;em&gt;voice&lt;/em&gt; controlled blinds’.&lt;/p&gt;

&lt;p&gt;Anyway. My coworking space recently bought some remote controlled blinds. This is a story about how I connected them to Alexa.&lt;/p&gt;

&lt;p&gt;The idea is to have an architecture like so&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/alexa-blinds/arch.png&quot; alt=&quot;The architecture&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And we’d flow data through it&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/alexa-blinds/action.png&quot; alt=&quot;Data flow&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Digging into the details, we’ll start with the last step in our diagram: How do we replicate the remote’s commands?&lt;/p&gt;

&lt;p&gt;We’re off to an easy start as the remote lists its transmitting frequency on the back. Similar devices will have an FCC id that can be referenced to find the same information.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/alexa-blinds/remote.jpg&quot; alt=&quot;SDR&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Next we’ll rely on a software defined radio and the amazing &lt;a href=&quot;https://github.com/jopohl/urh&quot;&gt;Universal Radio Hacker&lt;/a&gt; to record and analyze the remote’s messages.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/alexa-blinds/sdr.jpg&quot; alt=&quot;SDR&quot; /&gt;&lt;/p&gt;

&lt;p&gt;My SDR, similar to &lt;a href=&quot;https://www.aliexpress.com/item/Ham-Radio-Receiver-100KHz-1-7GHz-full-Band-UV-HF-RTL-SDR-USB-Tuner-Receiver-USB/32894229299.html&quot;&gt;https://www.aliexpress.com/item/Ham-Radio-Receiver-100KHz-1-7GHz-full-Band-UV-HF-RTL-SDR-USB-Tuner-Receiver-USB/32894229299.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After recording a few taps of the remote, we can use Universal Radio Hacker to decode the message&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/alexa-blinds/urh-analysis.png&quot; alt=&quot;URH&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The process couldn’t have been easier. Looking at the raw signal, I took a (lucky?) guess that it used &lt;a href=&quot;https://en.wikipedia.org/wiki/Amplitude-shift_keying&quot;&gt;ASK modulation&lt;/a&gt;, and the software will then detect the bit length and produce an interpretation of the signal.&lt;/p&gt;

&lt;p&gt;Next step is to check that we’re on the right path by transmitting the same code ourselves and making sure we can control the blinds. I used two components for this, an &lt;a href=&quot;https://www.aliexpress.com/item/New-Wireless-module-NodeMcu-Lua-WIFI-Internet-of-Things-development-board-based-ESP8266-with-pcb-Antenna/32656775273.html&quot;&gt;ESP8266&lt;/a&gt; and a &lt;a href=&quot;https://www.aliexpress.com/item/RF-wireless-receiver-module-transmitter-module-board-Ordinary-super-regeneration-315-433MHZ-DC5V-ASK-OOK-for/32298304710.html&quot;&gt;433Mhz transmitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Connected on a breadboard along with an LED give a cue when it’s transmitting&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/alexa-blinds/device.jpg&quot; alt=&quot;The device&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now we can write some quick and dirty code to see whether we can move the blinds&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/260bb5d048b55b7364b39cad19f54f86.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;And it works! I’m not sure I expected it to.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I feel self conscious posting that example using a String to store the command. Later we’ll switch to a more efficient encoding, but as a proof of concept, well, it proves the concept.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Moving on.&lt;/p&gt;

&lt;p&gt;Next we’ll look at exposing the microcontroller over an HTTP interface. The plan here is to make a simple HTTP server to receive high-level actions like ‘Raise the blinds’ and pass them on the microcontroller in the form of the bits necessary to take that action.&lt;/p&gt;

&lt;p&gt;This means we’ll have a process that’s listening on two ports. One port for incoming HTTP requests, and one port that our microcontrollers will connect to as they come online. We’ll then use the device information from the HTTP request to find the microcontroller to communicate with, look up its action mapping (e.g. for Stu’s blinds controller, the action ‘up’ means send 10101011’ at 300 bits / second), and encode and transmit the action to the microcontroller. To serialize the action we’ll use&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;MESSAGE TYPE: 1 byte&amp;gt;&amp;lt;BIT DURATION: 4 bytes&amp;gt;&amp;lt;MSG LENGTH: 4 bytes&amp;gt;&amp;lt;MSG: MSG LENGTH bytes&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The microcontroller side of this code was pleasingly simple to write. The ESP8266 has a built in wifi chip, and nice library support for creating a TCP connection. All we need to do is to write code to connect to our server and then handle the two message types our server sends: keep alives and actions.&lt;/p&gt;

&lt;p&gt;We’re close now. We can control the blinds with curl, so we’re already living large. The last step is connecting our HTTP interface to the Alexa Smart Device system.&lt;/p&gt;

&lt;p&gt;A couple of things need to happen here, and I’ll only touch on them as they’re well covered in &lt;a href=&quot;https://developer.amazon.com/docs/smarthome/steps-to-build-a-smart-home-skill.html&quot;&gt;Amazon’s docs&lt;/a&gt;. We need to write a lambda function that exposes our &lt;a href=&quot;https://developer.amazon.com/docs/device-apis/list-of-interfaces.html&quot;&gt;device’s interface&lt;/a&gt; and responds to voice commands from Alexa, and then provide an &lt;a href=&quot;https://developer.amazon.com/docs/smarthome/steps-to-build-a-smart-home-skill.html#provide-account-linking-information&quot;&gt;OAuth endpoint&lt;/a&gt;. All are well documented on Amazon.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://stuarth.github.io/alexa-blinds/&quot;&gt;Connecting Remote Controlled Blinds to Alexa Smart Home&lt;/a&gt; was originally published by Stuart Hinson at &lt;a href=&quot;https://stuarth.github.io&quot;&gt;Stuart Hinson&lt;/a&gt; on September 08, 2018.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Building Clojure projects with the Jenkins Kubernetes Plugin]]></title>
  <link rel="alternate" type="text/html" href="https://stuarth.github.io/clojure/jenkins-docker-kubernetes-clojure/" />
  <id>https://stuarth.github.io/clojure/jenkins-docker-kubernetes-clojure</id>
  <published>2015-11-05T10:30:00+00:00</published>
  <updated>2015-11-05T10:30:00+00:00</updated>
  <author>
    <name>Stuart Hinson</name>
    <uri>https://stuarth.github.io</uri>
    
  </author>
  <content type="html">&lt;p&gt;The &lt;a href=&quot;https://wiki.jenkins-ci.org/display/JENKINS/Kubernetes+Plugin&quot;&gt;Jenkins Kubernetes plugin&lt;/a&gt; is a very cool bit of tech that allows Jenkins to dynamically provision workers from a pool of Docker hosts managed by Kubernetes.&lt;/p&gt;

&lt;p&gt;Setting up a worker with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lein&lt;/code&gt; is straightforward. With the Kubernetes plugin installed, visit your Jenkins configuration page and add a pod template along the lines of&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/kubernetes-pod-template.png&quot; alt=&quot;Kubernetes pod template&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The Docker image url refers to &lt;a href=&quot;https://quay.io/repository/stuarth/docker-jnlp-clojure-slave&quot;&gt;this Quay.io repository&lt;/a&gt;, based on &lt;a href=&quot;https://github.com/stuarth/docker-jnlp-clojure-slave/blob/master/Dockerfile&quot;&gt;a Dockerfile on Github&lt;/a&gt; that adds lein to the base &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jenkinsci/jnlp-slave&lt;/code&gt; image.&lt;/p&gt;

&lt;p&gt;Configure your project to use the pod and you’re set.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/jenkins-project-config.png&quot; alt=&quot;Jenkins Project config&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Note that only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lein&lt;/code&gt; is supported currently – please submit a PR or open an issue if you’d like to see additional build tools supported!&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://stuarth.github.io/clojure/jenkins-docker-kubernetes-clojure/&quot;&gt;Building Clojure projects with the Jenkins Kubernetes Plugin&lt;/a&gt; was originally published by Stuart Hinson at &lt;a href=&quot;https://stuarth.github.io&quot;&gt;Stuart Hinson&lt;/a&gt; on November 05, 2015.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Understanding Pedestal Interceptors and Selectively Injecting a ClojureScript REPL]]></title>
  <link rel="alternate" type="text/html" href="https://stuarth.github.io/clojure/pedestal-browser-repl/" />
  <id>https://stuarth.github.io/clojure/pedestal-browser-repl</id>
  <published>2015-05-22T10:36:00+00:00</published>
  <updated>2015-05-22T10:36:00+00:00</updated>
  <author>
    <name>Stuart Hinson</name>
    <uri>https://stuarth.github.io</uri>
    
  </author>
  <content type="html">&lt;p&gt;Pedestal represents interceptors, its analog to Ring middleware, as data. Let’s look at how we can use that to conditionally inject a ClojureScript REPL into responses.&lt;/p&gt;

&lt;h3 id=&quot;pedestal-terminology&quot;&gt;Pedestal Terminology&lt;/h3&gt;

&lt;p&gt;Two working definitions as we start&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/pedestal/pedestal/blob/master/guides/documentation/service-interceptors.md&quot;&gt;Interceptor&lt;/a&gt; - a record containing keys corresponding functions for execution stages. Serves an analogous role to middleware in Ring.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/pedestal/pedestal/blob/master/guides/documentation/service-context-reference.md#reference&quot;&gt;context&lt;/a&gt; - a map with all data relating to processing a request. Contains Ring request and response maps along with additional data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;marking-routes-with-metadata&quot;&gt;Marking Routes with Metadata&lt;/h3&gt;

&lt;p&gt;We’ll start by adding metadata indicating that a browser REPL should be included in the response. We can either add it directly to an endpoint&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;io.pedestal.interceptor.helpers&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ring.util.response&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:refer&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content-type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hello-world&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;with-meta&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;h/handler&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;hello world!!&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
           &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content-type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/html&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:browser-repl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;or to an interceptor anywhere else in the chain&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;include-browser-repl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;with-meta&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;h/before&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:browser-repl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; in the route definition&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/foo&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:interceptors&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;include-browser-repl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:get&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo-handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;interceptor-application&quot;&gt;Interceptor Application&lt;/h2&gt;

&lt;p&gt;Interceptors serve a similar role as middlewares in Ring but the implementation is substantially different. See Pedestal’s docs for &lt;a href=&quot;https://github.com/pedestal/pedestal/blob/master/guides/documentation/service-interceptors.md#ring-request-processing&quot;&gt;a full discussion&lt;/a&gt;, but for now the important difference is in how middlewares and interceptors are combined. In Ring, middlewares compose functionally&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;middleware-ex&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transform-request&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transform-response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transform-request&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transform-response&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new-handler&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;some-handler&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;middleware-ex&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn-1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn-2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;middleware-ex&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn-3&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn-4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; new-handler is now a fn [request] that could be&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; composed with additional middleware&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Pedestal represents interceptors sequentially, adding them as a queue to the request / response &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context&lt;/code&gt; (under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:io.pedestal.impl.interceptor/queue&lt;/code&gt;). In broad strokes, requests are processed by taking an interceptor from the queue and applying its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:enter&lt;/code&gt; function to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context&lt;/code&gt;, producing a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context&lt;/code&gt; that the next interceptor in the queue will act on. As each interceptor is visited, it’s added to a stack in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context&lt;/code&gt; that will be traversed on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:leave&lt;/code&gt; stage. &lt;a href=&quot;https://github.com/pedestal/pedestal/blob/73b5854d4ba01a6cd2146ca8a37ae6a2b76e8995/service/src/io/pedestal/impl/interceptor.clj#L121-L146&quot;&gt;The code&lt;/a&gt; is well worth a read.&lt;/p&gt;

&lt;p&gt;Knowing that the other interceptors involved in processing a request are visible in the context’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:io.pedestal.impl.interceptor/queue&lt;/code&gt;, we can write an interceptor that scans the queue looking for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:browser-repl&lt;/code&gt; metadata and injects a repl into the response if it’s found&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;io.pedestal.interceptor.helpers&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:refer&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;around&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;browser-repl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;produces an interceptor that scans the context's queue on enter for
  brower-repl metadata, calls inject-repl on leave if found&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inject-repl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;around&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;::browser-repl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; fn to call on :enter&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cond-&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;some-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; scan the queue for :browser-repl metadata&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:io.pedestal.impl.interceptor/queue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:browser-repl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:include-browser-repl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; add a flag to inject the repl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:response&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; on :leave&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cond-&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:include-browser-repl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; did we find browser-repl metadata?&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:response&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inject-repl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; add a repl!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;around&lt;/code&gt; to implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;browser-repl&lt;/code&gt; so that we can examine the interceptor queue in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;before&lt;/code&gt; stage and set a flag in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context&lt;/code&gt; called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:include-browser-repl&lt;/code&gt; that we’ll read when a response is present in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;leave&lt;/code&gt; phase and decide whether to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inject-repl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inject-repl&lt;/code&gt; is a function that handles the mechanics of modifying the response, along the lines of&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inject-repl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:body&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string?&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
               &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
               &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;slurp&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;repl-template&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enlive/template&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enlive/html-snippet&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enlive/append&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;enlive/html&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:script&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;goog.require(\&quot;pedestal_browser_repl.dev\&quot;);&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])))]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repl-template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
         &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
         &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;Note&lt;/em&gt; &lt;a href=&quot;https://groups.google.com/d/msg/pedestal-users/Peoc1LheR8I/xFXalhQFJRcJ&quot;&gt;Brian Rowe and Alex Redington suggested&lt;/a&gt; a couple of very nice extensions to this idea that I’d recommend studying before implementing it.&lt;/p&gt;

&lt;p&gt;Kinda cool, right? Interceptors are data, and neat approaches fall out. We use a similar pattern for authorization.&lt;/p&gt;

&lt;p&gt;Also, big thanks to &lt;strong&gt;Brian Rowe&lt;/strong&gt; and &lt;strong&gt;Rick Hall&lt;/strong&gt; for a number of improvements to this post!&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://stuarth.github.io/clojure/pedestal-browser-repl/&quot;&gt;Understanding Pedestal Interceptors and Selectively Injecting a ClojureScript REPL&lt;/a&gt; was originally published by Stuart Hinson at &lt;a href=&quot;https://stuarth.github.io&quot;&gt;Stuart Hinson&lt;/a&gt; on May 22, 2015.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Pixie Pi]]></title>
  <link rel="alternate" type="text/html" href="https://stuarth.github.io/pixie/pixie-pi/" />
  <id>https://stuarth.github.io/pixie/pixie-pi</id>
  <published>2015-05-05T12:36:00+00:00</published>
  <updated>2015-05-05T12:36:00+00:00</updated>
  <author>
    <name>Stuart Hinson</name>
    <uri>https://stuarth.github.io</uri>
    
  </author>
  <content type="html">&lt;p&gt;&lt;a href=&quot;https://github.com/pixie-lang/pixie&quot;&gt;Pixie&lt;/a&gt; is a Clojure-inspired lisp that has a quick startup time and &lt;a href=&quot;https://github.com/pixie-lang/pixie/wiki/FFI-(interop-with-C)&quot;&gt;nice FFI support&lt;/a&gt; that allows it to make use of existing C libraries, making it a nice option for working with the Raspberry Pi.&lt;/p&gt;

&lt;h2 id=&quot;installing-pixie&quot;&gt;Installing Pixie&lt;/h2&gt;

&lt;h4 id=&quot;meeting-dependencies&quot;&gt;Meeting Dependencies&lt;/h4&gt;

&lt;p&gt;From a base Raspbian install, &lt;a href=&quot;https://github.com/pixie-lang/pixie#dependencies&quot;&gt;Pixie’s dependencies&lt;/a&gt; (as of eb5886ff95) except for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libuv-dev&lt;/code&gt; can be satisfied using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aptitude&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo apt-get install libffi-dev libedit-dev libboost-all-dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libuv-dev&lt;/code&gt; (and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libuv&lt;/code&gt;) are available from the &lt;a href=&quot;https://packages.debian.org/jessie/libuv0.10-dev&quot;&gt;Jesse packages&lt;/a&gt;. Use the armhf builds.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://packages.debian.org/jessie/armhf/libuv0.10/download&quot;&gt;libuv&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://packages.debian.org/jessie/armhf/libuv0.10-dev/download&quot;&gt;libuv-dev&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wget&lt;/code&gt; to grab the packages and install with&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dpkg &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; libuv&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;armhf.deb&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;building-the-pixie-vm&quot;&gt;Building the Pixie VM&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make build_no_jit&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It’ll run for about an hour. Enjoy the excellent ascii art the RPython build process produces.&lt;/p&gt;

&lt;p&gt;Cross compilation from a faster machine may be an option as well.&lt;/p&gt;

&lt;h2 id=&quot;interfacing-with-the-raspberry-pis-gpio&quot;&gt;Interfacing with the Raspberry Pi’s GPIO&lt;/h2&gt;

&lt;p&gt;Using Pixie’s FFI, I made a &lt;a href=&quot;https://github.com/stuarth/wiringPixie&quot;&gt;library called wiringPixie&lt;/a&gt; wrapping &lt;a href=&quot;http://wiringpi.com&quot;&gt;wiringPi&lt;/a&gt;. Follow the instructions on the README to install&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/stuarth/wiringPixie&quot;&gt;https://github.com/stuarth/wiringPixie&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and start hacking (or controlling LEDs :))&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wiring-pixie.gpio&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:refer&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pin&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;wiringPiSetup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; required first!&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pinMode&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pin&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OUTPUT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; pin to OUTPUT&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;digitalWrite&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pin&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HIGH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; set pin 7 to HIGH&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;


  &lt;p&gt;&lt;a href=&quot;https://stuarth.github.io/pixie/pixie-pi/&quot;&gt;Pixie Pi&lt;/a&gt; was originally published by Stuart Hinson at &lt;a href=&quot;https://stuarth.github.io&quot;&gt;Stuart Hinson&lt;/a&gt; on May 05, 2015.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Error handling in Pedestal 0.4.0]]></title>
  <link rel="alternate" type="text/html" href="https://stuarth.github.io/clojure/error-dispatch/" />
  <id>https://stuarth.github.io/clojure/error-dispatch</id>
  <published>2015-02-13T09:30:00+00:00</published>
  <updated>2015-02-13T09:30:00+00:00</updated>
  <author>
    <name>Stuart Hinson</name>
    <uri>https://stuarth.github.io</uri>
    
  </author>
  <content type="html">&lt;p&gt;Pedestal 0.4.0 includes &lt;a href=&quot;https://github.com/pedestal/pedestal/blob/88b940ca9c4b68de18f452f0e168400872f3c10e/service/src/io/pedestal/interceptor/error.clj#L5&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.pedestal.interceptor.error/error-dispatch&lt;/code&gt;&lt;/a&gt;, which uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.match&lt;/code&gt; to make error handling very tidy. For example&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my-error-handler&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;error-int/error-dispatch&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; match errors from body-params interceptor&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:interceptor&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:io.pedestal.http.body-params/body-params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ring.util.response/response&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Invalid data given&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:status&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:response&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; match FileNotFoundException in the :enter stage&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:exception-type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:java.io.FileNotFoundException&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:stage&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; respond to this error differently&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; pass along the error if we don't match&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:else&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;assoc&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:io.pedestal.impl.interceptor/error&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;creates an error handler that tries to matches any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Throwable&lt;/code&gt; from ,&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;error-dispatch&lt;/code&gt; macro splices its forms after the binding vector (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[context ex]&lt;/code&gt; above) into a &lt;a href=&quot;https://github.com/clojure/core.match/wiki/Basic-usage#map-patterns&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.match&lt;/code&gt; expression&lt;/a&gt; matching against the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ex-data&lt;/code&gt; of our exception, which is defined in &lt;a href=&quot;https://github.com/pedestal/pedestal/blob/88b940ca9c4b68de18f452f0e168400872f3c10e/service/src/io/pedestal/impl/interceptor.clj#L30&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.pedestal.impl.interceptor&lt;/code&gt;&lt;/a&gt;, and contains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:execution-id&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:stage&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:interceptor&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:exception-type&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:exception&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my-error-handler&lt;/code&gt; will respond with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;400&lt;/code&gt; for any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Throwable&lt;/code&gt; from the interceptor named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:io.pedestal.http.body-params/body-param&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;Giving a nice separation between the semantically-correct error for an interceptor to throw (e.g. a parser error for invalid JSON) and the response that’s generated (a status 400 for invalid input).&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://stuarth.github.io/clojure/error-dispatch/&quot;&gt;Error handling in Pedestal 0.4.0&lt;/a&gt; was originally published by Stuart Hinson at &lt;a href=&quot;https://stuarth.github.io&quot;&gt;Stuart Hinson&lt;/a&gt; on February 13, 2015.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Configuring CSRF protection in a simple Clojure / Pedestal App]]></title>
  <link rel="alternate" type="text/html" href="https://stuarth.github.io/clojure/csrf-pedestal/" />
  <id>https://stuarth.github.io/clojure/csrf-pedestal</id>
  <published>2015-01-25T10:30:00+00:00</published>
  <updated>2015-01-25T10:30:00+00:00</updated>
  <author>
    <name>Stuart Hinson</name>
    <uri>https://stuarth.github.io</uri>
    
  </author>
  <content type="html">&lt;p&gt;OWASP has an &lt;a href=&quot;https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29&quot;&gt;excellent description&lt;/a&gt; of CSRF attacks and why they’re a concern. &lt;em&gt;The tl;dr is, without safegaurds, an attacker can cause users to take unintended actions on your app&lt;/em&gt;. It’s well worth spending a few minutes on the link above if you’re not familiar.&lt;/p&gt;

&lt;h3 id=&quot;using-iopedestalhttpcsrf-to-prevent-attacks&quot;&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.pedestal.http.csrf&lt;/code&gt; to prevent attacks&lt;/h3&gt;

&lt;p&gt;Pedestal’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.pedestal.http.csrf&lt;/code&gt; namespace implements the &lt;a href=&quot;https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#General_Recommendation:_Synchronizer_Token_Pattern&quot;&gt;synchronizer token pattern&lt;/a&gt; that gives us the tools we need.&lt;/p&gt;

&lt;p&gt;We’ll start with a blank &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pedestal-service&lt;/code&gt; template&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;lein new pedestal-service csrf&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And add Pedestal’s CSRF namespace to our service&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;csrf.service&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:require&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;io.pedestal.http&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bootstrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;io.pedestal.http.route&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;io.pedestal.http.body-params&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body-params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;io.pedestal.http.route.definition&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:refer&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;defroutes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;io.pedestal.http.csrf&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;csrf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; add this&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ring.util.response&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ring-resp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The trick to using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;csrf/anti-forgery&lt;/code&gt; with a form parameter (as of 0.3.1) is to realize that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.pedestal.http.body-params/body-params&lt;/code&gt; interceptor, which is responsible for parsing parameters encoded in the request body, is &lt;em&gt;not&lt;/em&gt; included by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.pedestal.http/default-interceptors&lt;/code&gt;. That means naively enabling CSRF protection in your service map, e.g.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;::bootstrap/enable-csrf&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; doesn't work with form params!&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;won’t work because the anti-forgery interceptor will attempt to read from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;form-params&lt;/code&gt; that haven’t been parsed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;body-params&lt;/code&gt; yet. Resolving it is simple, we’ll update our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;service&lt;/code&gt; definition to include&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;::bootstrap/enable-session&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;and include our csrf middleware on the appropriate routes &lt;em&gt;after&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io.pedestal.http.body-params/body-params&lt;/code&gt; has been applied&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;defroutes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;routes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:interceptors&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;body-params/body-params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                     &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bootstrap/html-body&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;csrf/anti-forgery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
     &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/csrf-protected &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;:post&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;csrf-protected-handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]]]])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;All that’s left is to include the request’s anti-forgery token in our forms, something like&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;input type=\&quot;hidden\&quot; name=\&quot;__anti-forgery-token\&quot; value=\&quot;%s\&quot;/&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;::csrf/anti-forgery-token&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A full sample’s available &lt;a href=&quot;https://github.com/stuarth/pedestal-csrf&quot;&gt;on Github&lt;/a&gt;.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://stuarth.github.io/clojure/csrf-pedestal/&quot;&gt;Configuring CSRF protection in a simple Clojure / Pedestal App&lt;/a&gt; was originally published by Stuart Hinson at &lt;a href=&quot;https://stuarth.github.io&quot;&gt;Stuart Hinson&lt;/a&gt; on January 25, 2015.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Surprising timeout chan interactions in Clojure's core.async]]></title>
  <link rel="alternate" type="text/html" href="https://stuarth.github.io/clojure/timeout-interaction/" />
  <id>https://stuarth.github.io/clojure/timeout-interaction</id>
  <published>2014-09-14T08:56:00+00:00</published>
  <updated>2014-09-14T08:56:00+00:00</updated>
  <author>
    <name>Stuart Hinson</name>
    <uri>https://stuarth.github.io</uri>
    
  </author>
  <content type="html">&lt;p&gt;note that this behavior applies to core.async &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.1.338.0-5c5012-alpha&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-issue-distilled&quot;&gt;The issue distilled&lt;/h2&gt;

&lt;p&gt;Let’s measure the time it takes to create two timeout chans, close one, and read from the other.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;System/currentTimeMillis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;close!&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&amp;lt;!!&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;System/currentTimeMillis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; =&amp;gt; 0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;What happened? Why don’t we see a value ~100ms corresponding to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;’s timeout?&lt;/p&gt;

&lt;h2 id=&quot;whats-going-on&quot;&gt;What’s going on?&lt;/h2&gt;

&lt;p&gt;Let’s dive into the code! The relevant bit’s in &lt;a href=&quot;https://github.com/clojure/core.async/blob/53bf7866f195e6ba247ff7122b99784e66e9f1bb/src/main/clojure/clojure/core/async/impl/timers.clj#L43&quot;&gt;timers.clj&lt;/a&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;returns a channel that will close after msecs&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msecs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;System/currentTimeMillis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msecs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.ceilingEntry&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeouts-map&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.getKey&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TIMEOUT_RESOLUTION_MS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.channel&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TimeoutQueueEntry&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.getValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout-channel&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;channels/chan&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout-entry&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;TimeoutQueueEntry.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout-channel&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.put&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeouts-map&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout-entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.put&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeouts-queue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout-entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout-channel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Bells are probably going off when you see &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TIMEOUT_RESOLUTION_MS&lt;/code&gt; (defined above: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(def ^:const TIMEOUT_RESOLUTION_MS 10)&lt;/code&gt;). Let’s unpack the surrounding code. First in our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let&lt;/code&gt; block, we have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;timeout&lt;/code&gt;, which converts the relative &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msecs&lt;/code&gt; into a clock time to expire. We then set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;me&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(.ceilingEntry timeouts-map timeout)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;timeouts-map&lt;/code&gt; is a &lt;a href=&quot;http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentSkipListMap.html&quot;&gt;java.util.concurrent.ConcurrentSkipListMap&lt;/a&gt; and its method &lt;a href=&quot;http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentSkipListMap.html#ceilingEntry(K)&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ceilingEntry&lt;/code&gt;&lt;/a&gt; “Returns a key-value mapping associated with the least key greater than or equal to the given key, or null if there is no such entry”. So &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;me&lt;/code&gt; will be the entry (if present) in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;timeouts-map&lt;/code&gt; with the first value that’s greater than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;timeout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The unexpected behavior comes from the next line&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-clojure&quot; data-lang=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.getKey&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TIMEOUT_RESOLUTION_MS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.channel&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TimeoutQueueEntry&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.getValue&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So, if we found an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;me&lt;/code&gt;, and its key is within the tolerance of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TIMEOUT_RESOLUTION_MS&lt;/code&gt;, we return an existing channel rather than creating a new one! This explains the behavior at the top: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; share a channel, so closing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; immediately closed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;, allowing the entire block to evaluate almost instantly.&lt;/p&gt;

&lt;h3 id=&quot;thanks&quot;&gt;Thanks!&lt;/h3&gt;

&lt;p&gt;A huge thanks to &lt;a href=&quot;https://github.com/briprowe&quot;&gt;Brian Rowe&lt;/a&gt;&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://stuarth.github.io/clojure/timeout-interaction/&quot;&gt;Surprising timeout chan interactions in Clojure's core.async&lt;/a&gt; was originally published by Stuart Hinson at &lt;a href=&quot;https://stuarth.github.io&quot;&gt;Stuart Hinson&lt;/a&gt; on September 14, 2014.&lt;/p&gt;</content>
</entry>

</feed>
