<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

    <title>shtylman.com</title>
    <link href="http://shtylman.com/atom.xml" rel="self"/>
    <link href="http://shtylman.com/"/>
    <updated>2016-01-23T04:26:21+00:00</updated>
    <id>http://shtylman.com/</id>
    <author>
        <name>Roman Shtylman</name>
        <email>shtylman@gmail.com</email>
    </author>

    
    <entry>
        <title>node.js error logging</title>
        <link href="http://shtylman.com/post/node-error-logging"/>
        <updated>2013-03-16T00:00:00+00:00</updated>
        <id>http://shtylman.com/post/node-error-logging</id>
        <content type="html">&lt;p&gt;One of the first things you should do for any application you plan to deploy is make sure you have proper error logging in place. You should know when things are failing and should be able to act on failure information.&lt;/p&gt;

&lt;p&gt;Lets start with a basic node application that might have an error&lt;/p&gt;

&lt;h2&gt;inflexible error logging&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;will_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cb&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;foobar&amp;#39;&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;nx&quot;&gt;will_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&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;p&gt;It is clear that when we call &lt;code&gt;will_error&lt;/code&gt;, our app will get back an error that we should handle. By just using &lt;code&gt;console.log&lt;/code&gt; as we have done, we are losing valuable error information.&lt;/p&gt;

&lt;p&gt;Not only are we losing error information to help in debugging, but we are also not doing anything to alert ourselves to potential problems our app is having. The first step to better error information is to introduce a basic logging library.&lt;/p&gt;

&lt;h2&gt;basic logging layer&lt;/h2&gt;

&lt;p&gt;One step in the right direction is to use a simple logging library like &lt;a href=&quot;https://github.com/shtylman/node-book&quot;&gt;book&lt;/a&gt;. Book will become the point of capture for our log entries allowing us to make use of them in a more flexible manner.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;book&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;will_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cb&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;foobar&amp;#39;&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;nx&quot;&gt;will_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&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;p&gt;Now, instead of logging to console, we are logging through &lt;code&gt;book&lt;/code&gt; which provides a few log events and also logs to console for us. The application is identical to what we had before, except now we can leverage our logging library to get more information from our errors.&lt;/p&gt;

&lt;h2&gt;introduce an alerting solution&lt;/h2&gt;

&lt;p&gt;Lets say we want to leverage an alerting service like &lt;a href=&quot;http://getsentry.com/welcome/&quot;&gt;sentry&lt;/a&gt; to know when things are breaking. We can easily do this when we use a simple logging layer.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/shtylman/node-bookrc&quot;&gt;bookrc&lt;/a&gt; module allows us to educate our book logging layer without affecting application code.&lt;/p&gt;

&lt;p&gt;Simply alter the &lt;code&gt;require(&amp;#39;book&amp;#39;)&lt;/code&gt; line to &lt;code&gt;require(&amp;#39;bookrc&amp;#39;)&lt;/code&gt; and put the following file in the root of your project.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/5178667.js?file=bookrc.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Now when we run our application and an error happens, we will be alerted via the sentry web interface.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;
&lt;a href=&quot;https://app.getsentry.com/dummy/dummy/group/3885521/&quot;&gt;&lt;img src=&quot;/img/post/node-error-logging/sentry.png&quot; alt=&quot;sentry&quot;&gt;&lt;/a&gt;
&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;This provides us with a lot more information about the specific error.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;error level&lt;/li&gt;
&lt;li&gt;stacktrace with relevant code blocks&lt;/li&gt;
&lt;li&gt;location of logging statement&lt;/li&gt;
&lt;li&gt;git commit id&lt;/li&gt;
&lt;li&gt;loaded modules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of this information is valuable when tracking down errors in deployed applications and we got it all for free without having to change our application code!&lt;/p&gt;

&lt;h3&gt;how it works&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;bookrc&lt;/code&gt; module simply looks for a &lt;code&gt;bookrc.js&lt;/code&gt; file and loads that as itself. What we put into this &lt;code&gt;bookrc.js&lt;/code&gt; file is completely up to us. I could have easily added logging to a file, additional alerting or other filters to the &lt;code&gt;book&lt;/code&gt; logger we created. Book logging is very flexible and can easily be extended with many different plugins.&lt;/p&gt;

&lt;h2&gt;further reading&lt;/h2&gt;

&lt;p&gt;If you are using the &lt;a href=&quot;http://expressjs.com/&quot;&gt;express&lt;/a&gt; web framework. Check out the &lt;a href=&quot;https://github.com/shtylman/node-connect-raven&quot;&gt;connect-raven&lt;/a&gt; module which provides error middleware for sentry logging. Proper express/connect error logging is a post in itself.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;https://gist.github.com/shtylman/5178667&quot;&gt;gist/5178667&lt;/a&gt; for some additional examples&lt;/p&gt;

&lt;h2&gt;Now go and purge those useless console.logs!&lt;/h2&gt;
</content>
    </entry>
    
    <entry>
        <title>cron SHELL power</title>
        <link href="http://shtylman.com/post/cron-shell-power"/>
        <updated>2013-03-08T00:00:00+00:00</updated>
        <id>http://shtylman.com/post/cron-shell-power</id>
        <content type="html">&lt;p&gt;If you don&amp;#39;t know what &lt;a href=&quot;http://en.wikipedia.org/wiki/Cron&quot;&gt;cron&lt;/a&gt; is this post is not for you.&lt;/p&gt;

&lt;p&gt;Using the &lt;code&gt;SHELL&lt;/code&gt; variable in cron is more powerful than you may realize.&lt;/p&gt;

&lt;h2&gt;typical crontab&lt;/h2&gt;

&lt;p&gt;Most people will have this type of setup in their crontab.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;NODE_ENV=production
OTHER_VAR=foo

*/10 * * * * /path/to/node /path/to/my/script.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you don&amp;#39;t want to repeat &lt;code&gt;/path/to/node&lt;/code&gt; (or your runtime) over and over, you will add a &lt;code&gt;PATH&lt;/code&gt; variable to go with the other variables.&lt;/p&gt;

&lt;p&gt;But what happens if you want to use something like &lt;a href=&quot;https://github.com/creationix/nvm&quot;&gt;nvm&lt;/a&gt; or &lt;a href=&quot;https://rvm.io/&quot;&gt;rvm&lt;/a&gt; or &lt;a href=&quot;https://pypi.python.org/pypi/virtualenv&quot;&gt;virtualenv&lt;/a&gt;, etc? It is not uncommon to have the above change to something like the following&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;*/10 * * * * /path/to/my/launcher.sh
*/10 * * * * /path/to/my/launcher_another.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you have several shell scripts which invoke the required commands to setup the environment and then run whatever program.&lt;/p&gt;

&lt;h2&gt;enter SHELL&lt;/h2&gt;

&lt;p&gt;There is a little known special env variable for cron: &lt;code&gt;SHELL&lt;/code&gt;. Most people know this variable can be used to change the shell your scripts run run (i.e. &lt;code&gt;SHELL=/bin/bash&lt;/code&gt;), but it can actually run any file!&lt;/p&gt;

&lt;p&gt;So lets say I use nvm and want to setup my environment. Instead of making custom launchers for each command, I can simply do the following:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;SHELL=/path/to/setup/cron.bash

*/10 * * * * node $HOME/foo.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now lets look at what &lt;code&gt;cron.bash&lt;/code&gt; might look like&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/5112421.js?file=cron.bash&quot;&gt;&lt;/script&gt;

&lt;p&gt;For the most part it looks just like any other shell script. The important magical parts are the last 4 lines. These lines put back the SHELL variable to &lt;code&gt;/bin/bash&lt;/code&gt; and then execute a bash shell to run the cronline command (the stuff for the specific cronjob).&lt;/p&gt;

&lt;p&gt;Now our cron files have a consistent environment setup and we can simply run whatever commands we need without further PATH tricks or nonsense.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/5112421.js?file=cron&quot;&gt;&lt;/script&gt;

&lt;p&gt;Go forth and update your dirty crontabs!&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <title>expressjs re-routing</title>
        <link href="http://shtylman.com/post/expressjs-re-routing"/>
        <updated>2013-01-07T00:00:00+00:00</updated>
        <id>http://shtylman.com/post/expressjs-re-routing</id>
        <content type="html">&lt;p&gt;One of the most common questions I get asked when I talk about express is how I manage my routes. While I generally point out things like &lt;a href=&quot;http://expressjs.com/api.html#app.param&quot;&gt;app.param()&lt;/a&gt; and other middleware tricks, I am left just saying that I don&amp;#39;t have a great solution. Well, I am happy to say that as of &lt;strong&gt;express 3.0.6&lt;/strong&gt; I have a better answer; use the router!&lt;/p&gt;

&lt;h1&gt;Routes, why do I care?&lt;/h1&gt;

&lt;p&gt;Maybe you don&amp;#39;t like routers, but they do serve a purpose. If you are writing a web app or even a headless api, you can benefit from the simple separation and organization a nice router will provide. Just think of it as a URL &lt;em&gt;if&lt;/em&gt; statement on steroids!&lt;/p&gt;

&lt;p&gt;The typical express application looks something like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;/// top level routes&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;next&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;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;/// blog post routes&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/post/:post_id&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;next&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;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/post/:post_id/comment&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;next&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;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;del&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/post/:post_id/comment&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;next&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;span class=&quot;c1&quot;&gt;/// etc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As the number of routes you want your app to handle grows, you might find that this single file approach gets out of control (justifiably so) and move to a multi-file approach where you export handler functions.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;./routes/post&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/post/:post_id&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/post/:post_id/comment&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addComment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;del&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/post/:post_id/comment&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;removeComment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The problem is that your &lt;code&gt;routes/post&lt;/code&gt; file is now void of the actual route information. This can make it a bit more challenging to see what is going on and debug.&lt;/p&gt;

&lt;h1&gt;Router to the rescue!&lt;/h1&gt;

&lt;p&gt;Instead of exporting individual functions from your routes files. You can now use the express router without creating a whole new express app.&lt;/p&gt;

&lt;p&gt;Imagine we have the following routes.js file&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;express&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;express&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;router&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// we can use all of the HTTP verbs on the router&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/bar&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;next&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;span class=&quot;nx&quot;&gt;router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/baz&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;next&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;span class=&quot;c1&quot;&gt;// at the end we export this router as a single unit&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And in app.js&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// this is for the routes in this file&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// this creates /foo/bar and /foo/baz&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// /foo could be any prefix&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/foo&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;./routes&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;middleware&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// our typical app routes can still go here&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;next&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;p&gt;What we have done is left the relevant path information in the routes.js file and &amp;quot;mounted&amp;quot; those routes under the &lt;code&gt;/foo&lt;/code&gt; url. Now we have basic routes and handlers defined separately from where the parent application may be mounting them.&lt;/p&gt;

&lt;p&gt;Note: You could &lt;code&gt;app.use(require(&amp;#39;./routes&amp;#39;).middleware);&lt;/code&gt; if you wanted to host the routes from the site root.&lt;/p&gt;

&lt;h1&gt;Complete app example&lt;/h1&gt;

&lt;p&gt;I have created a &lt;a href=&quot;https://gist.github.com/4472280&quot;&gt;gist&lt;/a&gt; which you can clone or review below as a more complete example.&lt;/p&gt;

&lt;h2&gt;app.js&lt;/h2&gt;

&lt;p&gt;Our main app.js (server.js, index.js, whatever.js) file does not change much. The only major difference is that instead of using app.get for our &lt;code&gt;/user&lt;/code&gt; and &lt;code&gt;/post&lt;/code&gt; routes in the file, we use &lt;code&gt;app.use&lt;/code&gt; and inject them under their respective parent urls.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/4472280.js?file=app.js&quot;&gt;&lt;/script&gt;

&lt;h2&gt;routes/user.js&lt;/h2&gt;

&lt;p&gt;We now put all of the routes we want to contain as one unit in this file. Notice that this file does not know that it will be served under &lt;code&gt;/user&lt;/code&gt;. It could be served from any route by a parent file. Using this approach you could reuse sets of routes in multiple places (not suggesting this is what you want :)&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/4472280.js?file=routes/user.js&quot;&gt;&lt;/script&gt;

&lt;h2&gt;routes/post.js&lt;/h2&gt;

&lt;p&gt;Like the app, the router has a &lt;code&gt;.param()&lt;/code&gt; function which allows you to consolidate parameter handling. In this example, we see that since all of these routes will need a post, we use the &lt;code&gt;:post_id&lt;/code&gt; parameter from the url to make sure a post is loaded before any route is run.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/4472280.js?file=routes/post.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Now go forth and bring order to those routes! Remember that you will need express version &lt;code&gt;3.0.6&lt;/code&gt;.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <title>npm - git with the program</title>
        <link href="http://shtylman.com/post/npm-git-with-the-program"/>
        <updated>2012-12-26T00:00:00+00:00</updated>
        <id>http://shtylman.com/post/npm-git-with-the-program</id>
        <content type="html">&lt;p&gt;&lt;a href=&quot;https://npmjs.org&quot;&gt;npm&lt;/a&gt; is a simple package manager for javascript projects. All it takes to use npm for your project is a simple file called &lt;strong&gt;package.json&lt;/strong&gt;. This file contains some basic metadata about your project (similar to setup.py for pip, gemspec for ruby, etc).&lt;/p&gt;

&lt;p&gt;Example package.json file&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;awesome-package-name&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;version&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;0.0.0&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;description&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;the answer to life and the universe&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;main&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;./entry-file.js&amp;quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Thats all you need for a basic description of your project. If you have a public project and are hosting it publicly, I also suggest adding a repository field so others can find your code.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;repository&amp;quot;&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;s2&quot;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;git&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;url&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;git://github.com/shtylman/awesome-package-name.git&amp;quot;&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;p&gt;For versioning, I suggest you take a quick look at &lt;a href=&quot;https://github.com/mojombo/semver/blob/master/semver.md&quot;&gt;semver&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;dependencies&lt;/h2&gt;

&lt;p&gt;Now, if your module is awesome (and there is no reason for it not to be), then you will most likely use other modules. Fortunately, this is really easy and all you need to add is a &lt;strong&gt;dependencies&lt;/strong&gt; field.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;dependencies&amp;quot;&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;s2&quot;&gt;&amp;quot;mime&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1.2.7&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;yummy&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1.0.1&amp;quot;&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;p&gt;I recommend using &lt;a href=&quot;/post/pinning-your-hopes&quot;&gt;exact versions&lt;/a&gt; so when you revisit your code months later, you can easily identify what versions you had installed and the module worked with.&lt;/p&gt;

&lt;p&gt;Now you can just run &lt;strong&gt;npm install&lt;/strong&gt; and npm will fetch the exact versions of the dependencies specified.&lt;/p&gt;

&lt;p&gt;If you want to add more dependencies later, just edit the file. &lt;strong&gt;npm ls&lt;/strong&gt; can show you what you have installed but not added (extraneous).&lt;/p&gt;

&lt;h2&gt;where does git fit in?&lt;/h2&gt;

&lt;p&gt;The above dependency specification should look very familiar to anyone currently writing javascript modules and publishing them to npm. What many don&amp;#39;t realize is that you can also specify git repositories!&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;dependencies&amp;quot;&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;s2&quot;&gt;&amp;quot;dom&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;git://github.com/shtylman/dom.git&amp;quot;&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;p&gt;Now when you &lt;strong&gt;npm install&lt;/strong&gt;, npm will fetch the latest version of the master branch from the git repo you specified!&lt;/p&gt;

&lt;p&gt;If you want a specific tag or commit just specify a &lt;strong&gt;#&lt;/strong&gt; followed by the tag or commit id.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;dependencies&amp;quot;&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;s2&quot;&gt;&amp;quot;dom&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;git://github.com/shtylman/dom.git#v0.0.1&amp;quot;&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;p&gt;When specifying a commit sha1, you don&amp;#39;t have to specify the whole sha. I have found that using just the first 6 characters is good enough as it will most likely be unique in your repo.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;dependencies&amp;quot;&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;s2&quot;&gt;&amp;quot;dom&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;git://github.com/shtylman/dom.git#449852&amp;quot;&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;h2&gt;but wait! there&amp;#39;s more!&lt;/h2&gt;

&lt;p&gt;As of node v0.8.14, you can make your github urls even shorter!&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;dependencies&amp;quot;&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;s2&quot;&gt;&amp;quot;dom&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;shtylman/dom#v0.0.1&amp;quot;&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;p&gt;Note that just like the long form url, you can specify a &lt;strong&gt;#commit&lt;/strong&gt;. So if you can&amp;#39;t publish to npm, or have some other naming issue, you can easily reference code which lives on github.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Keep in mind that the shortform syntax does not work on npm &amp;lt; 1.1.64. So if you have an older version of node, you will need to make sure your npm is up to date with *&lt;/em&gt;npm install -g npm***&lt;/p&gt;

&lt;h2&gt;use cases and wrap-up&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;works with users or organizations! the format is simply &lt;strong&gt;owner/repo#commit&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;private repos work great with the git approach so long as the proper ssh keys are setup in github&lt;/li&gt;
&lt;li&gt;you don&amp;#39;t have to &lt;strong&gt;npm publish&lt;/strong&gt; to use a module&lt;/li&gt;
&lt;li&gt;if your module name is already taken and you are not creative enough to make a new one&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    
    <entry>
        <title>the copy &amp; paste virus</title>
        <link href="http://shtylman.com/post/the-copy-and-paste-virus"/>
        <updated>2012-12-13T00:00:00+00:00</updated>
        <id>http://shtylman.com/post/the-copy-and-paste-virus</id>
        <content type="html">&lt;blockquote&gt;
&lt;p&gt;If there is bad code, I will find it, and I will copy it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Years ago (long before the web 2.0 days) I wrote JavaScript. Then I stopped. These days, I again write a lot of JavaScript. Other people also write a lot of JavaScript and not a single day goes by that someone doesn&amp;#39;t write some new jQuery plugin or other interesting JavaScript client library. This is fantastic! All of these developers are solving their problems and sharing the solution with everyone else.&lt;/p&gt;

&lt;p&gt;However, when I look back on the JavaScript that I would see someone write years ago and the JavaScript I see being distributed today, I don&amp;#39;t see much difference. Sure, some styles and html technologies are better, but I still see everyone delivering JavaScript which all looks like a variation of the following.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&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;c1&quot;&gt;// or $ depending if it is a jQuery plugin&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;coconut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;tricycle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;bus&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;mi&quot;&gt;500&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;other&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;variables&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;potato&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;tomato&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;yarn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;flag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;hippo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;pencil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;pen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;something&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;span class=&quot;nx&quot;&gt;hundreds&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;some&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;functions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;classes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;who&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;knows&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;what&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;referencing&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;itself&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;global&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;foo&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;nx&quot;&gt;something&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;nx&quot;&gt;another&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;span class=&quot;p&quot;&gt;})(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// or jQuery again depending&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;#39;s it. One giant file full of code that self references, nests over and over and is contained within a closure just for fun! Why are we doing this? Do we (as developers) hate clarity? Do we enjoy writing a giant closure to do nothing?&lt;/p&gt;

&lt;p&gt;Think about how you write code and libraries in other languages. How often do you dump everything into a &amp;quot;mega&amp;quot; file. How often to do put all of it inside one single outer function &lt;em&gt;just cause&lt;/em&gt;? &lt;strong&gt;NEVER&lt;/strong&gt;, that is how often. In other languages you use &lt;em&gt;import&lt;/em&gt;, &lt;em&gt;require&lt;/em&gt;, &lt;em&gt;include&lt;/em&gt;, etc.. so why do we continue to allow our JavaScript to look like unmaintainable shit? No module system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WRONG!&lt;/strong&gt; There is &lt;strong&gt;NO&lt;/strong&gt; reason. JavaScript has a super simple module system and countless people are overlooking it! I am talking about the commonjs require system. Here is all you need to know about commonjs requires: They work, they require no language extensions, and they CAN do what you need. That&amp;#39;s it. Everything else is a tooling and education problem. Period.&lt;/p&gt;

&lt;h2&gt;commonjs intermission&lt;/h2&gt;

&lt;p&gt;Since not everyone is familiar with commonjs, let me do a super quick primer with the basics.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;every file is a module&lt;/li&gt;
&lt;li&gt;everything in a file is private to the file unless explicitly exported&lt;/li&gt;
&lt;li&gt;any valid JavaScript type can be exported through &lt;strong&gt;module.exports&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;require&lt;/strong&gt; function is used to load a module&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That&amp;#39;s it! Now all you have to do is move some of that code into a separate file and &lt;em&gt;require&lt;/em&gt; it from your main file. Lets say I am writing a basic client library to do some stuff.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// main file for our new client side lib&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;./parser&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;./tree&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// we don&amp;#39;t export this, so it is private to the file&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// modules can also just export a function&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;p&gt;Now we create a &lt;em&gt;parser.js&lt;/em&gt; and &lt;em&gt;tree.js&lt;/em&gt; files alongside out main entry file&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// parser.js&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parse&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;str&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 class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// tree.js&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Tree&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I have kept the above examples brief specifically to show the super simple nature of the commonjs module system. No complex dependency maps, no global closures, no spaghetti.&lt;/p&gt;

&lt;h2&gt;all nails and no hammer&lt;/h2&gt;

&lt;p&gt;So those of you who are still reading are certainly wondering how you are going to take the above code and make it work in a browser. No browser supports the &amp;quot;require&amp;quot; syntax and in the end you wanted to have one file in your &lt;em&gt;script&lt;/em&gt; tag. Well, I guess that&amp;#39;s that, end of that fun experiment. &lt;strong&gt;NO&lt;/strong&gt;. Stop thinking about it as if you don&amp;#39;t have a computer in front of you. As a developer, one of the best improvements to productivity can be gained from your tools. The same is true in the above examples. Instead of manually putting your code in a giant closure, wondering what syntax you need for AMD loaders, and what to close over, &lt;strong&gt;LET THE TOOL DO THE WORK&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I am going to say that one more time, since I don&amp;#39;t think enough people appreciate this.&lt;/p&gt;

&lt;h1&gt;&lt;center&gt;LET THE TOOL DO THE WORK&lt;/center&gt;&lt;/h1&gt;

&lt;h2&gt;the hammer&lt;/h2&gt;

&lt;p&gt;Today is the day you say &lt;strong&gt;NO MORE&lt;/strong&gt; to massive, unorganized repositories of JavaScript files and start using modules. You don&amp;#39;t have to add any extra metapackages or publish your code in any special place to do this. To get you started, I have provided a very very basic tool which will build your multi file JavaScript projects called &lt;a href=&quot;https://github.com/shtylman/reunion&quot;&gt;reunion&lt;/a&gt;. I have even provided a makefile snippet to use it when creating the final code bundle for others.&lt;/p&gt;

&lt;h4&gt;use &lt;a href=&quot;https://github.com/shtylman/reunion&quot;&gt;reunion&lt;/a&gt; in your codebase NOW with minimal effort on your part!&lt;/h4&gt;

&lt;p&gt;You don&amp;#39;t have to dive in 100% from day 1. If you have a jQuery plugin, you can still use that wonderful global $ &lt;strong&gt;var $ = window.jQuery&lt;/strong&gt; in your module works!. However, these first steps will make your code that much easier to follow and eventually you will be able to &lt;em&gt;require(&amp;#39;jQuery&amp;#39;);&lt;/em&gt; just like anything else!&lt;/p&gt;

&lt;h2&gt;no overhead&lt;/h2&gt;

&lt;p&gt;Reunion require functionality is &lt;strong&gt;TINY&lt;/strong&gt;. The minified require function comes in at ~140 bytes! Since reunion puts everything into a single closure for you, you still benefit from excellent minification. Even more, each module is put into a function which means it can be minified locally and allows for the minifier to reuse more of the shorter variable names.&lt;/p&gt;

&lt;p&gt;It wasn&amp;#39;t until I started writing node.js code and modules that I realized how stupid front end file organization and usage was and cotninues to be for so many people. As soon as I started writing modules and separating code, JavaScript got that much easier and maintainable. Tests are easier to localize and common components can be shared much easier. More importantly, given the right tool, I could package any module however I wanted!&lt;/p&gt;

&lt;p&gt;What about other loaders? We are back to a tooling issue. The great thing about commonjs requires is that they are super easy to tool around! If you want AMD output, just send me a pull request for and AMD target. That&amp;#39;s it! Now only one place has to worry about the right closure format. Everyone else just has simple and clean JavaScript!&lt;/p&gt;

&lt;h2&gt;the future&lt;/h2&gt;

&lt;p&gt;Reunion is a very simple tool. In the next post, I am going to talk about tools like &lt;a href=&quot;http://npmjs.org&quot;&gt;npm&lt;/a&gt;, &lt;a href=&quot;https://github.com/shtylman/node-script&quot;&gt;script&lt;/a&gt;, and &lt;a href=&quot;https://github.com/substack/node-browserify&quot;&gt;browserify&lt;/a&gt; and how they can completely revolutionize how you develop and share JavaScript.&lt;/p&gt;

&lt;p&gt;And remember! &lt;strong&gt;LET THE TOOL DO THE WORK!&lt;/strong&gt;&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <title>fraud is not a merchant problem</title>
        <link href="http://shtylman.com/post/fraud-is-not-a-merchant-problem"/>
        <updated>2012-04-27T00:00:00+00:00</updated>
        <id>http://shtylman.com/post/fraud-is-not-a-merchant-problem</id>
        <content type="html">&lt;p&gt;I recently had the distinct pleasure of being hit with some chargebacks through my USD payment processor Dwolla. After talking to their head of fraud detection and prevention it became clear they they did not understand their own business.&lt;/p&gt;

&lt;p&gt;One of the choice phrases that kept being repeated was that fraud was a risk and a part of doing business for the merchant (me). I argue that it is not a part of doing business for the merchant if they are using a service such as Dwolla and here is why: information asymmetry.&lt;/p&gt;

&lt;p&gt;Before I get into what that means here is a quick example that was covered in the telephone conversation. Lets say my company sells widgets (something physical). A customer comes in and wishes to pay for a widget with Dwolla and since we are a Dwolla merchant we allow them to do so. Dwolla handles the transaction (debiting the customer&amp;#39;s Dwolla account and crediting our Dwolla account). We give the customer their widget (we trust Dwolla that those funds were accounted for, more on that later). Days later, Dwolla takes the funds from our account because the customer claimed (to their bank) that the funds were not authorized to Dwolla. I, as the merchant, am now out a widget and the money I was paid for the widget because Dwolla was not able to properly detect the fraudulent user.&lt;/p&gt;

&lt;p&gt;The reasoning Dwolla gives for the above is that fraud detection and customer identification is the responsibility of the merchant. What they don&amp;#39;t seem to understand is that the merchant does not have the information to do such detection or identification. Dwolla is acting as the intermediary between the customer&amp;#39;s bank accounts and personal information and the merchant. From the standpoint of the merchant, the USD transfered between the customer and merchant are &amp;quot;dwolla dollars&amp;quot; since the merchant trusts Dwolla that the transfer actually happened. The merchant has no way to query Dwolla for the customer&amp;#39;s information or their credentials to verify that the bank account owner and customer are the same person. Dwolla hides this from the merchant (claiming to protect the customer) and by doing this prevents the merchant from having the information needed to tie accounts together and detect fraud the way Dwolla thinks we can. Even if the merchant identified the customer, they would not be able to verify anything about the linked bank accounts and where the funds come from. Fundamentally, Dwolla is trying to create &amp;quot;dwolla dollars&amp;quot; or virtual money based on the trust that they are backed by real dollars from real accounts without taking the accountability of doing so.&lt;/p&gt;

&lt;p&gt;Since there is information that Dwolla has (and the merchant does not) and Dwolla is putting themselves between the customer and merchant, they are responsible for the funds they credit the merchant. If the merchant had to do the fraud detection and deal with customer bank accounts directly, they would not need Dwolla! Dwolla needs to be much more upfront about the &amp;quot;true&amp;quot; cost of doing business with them and that they will not worth with you to detect fraud or help you prevent it (since they can&amp;#39;t prevent it themselves).&lt;/p&gt;

&lt;p&gt;I understand that the USD banking system has chargebacks and that they are a reality of dealing with customer bank accounts. However, if you want to claim that fraud is the responsibility of the merchants, you must work with the merchants in linking customer accounts and verification otherwise your service is deceiving the very merchants you operate for. If you are a payment processor and are not absorbing the fraud, you don&amp;#39;t understand your function properly and will just cost the merchant time and money. Eventually they will stop using you for a better alternative that does understand the risks and how to manage them. Maybe it won&amp;#39;t be at $0.25 per transaction, and that might be the reality of the US banking system.&lt;/p&gt;

&lt;p&gt;Many people don&amp;#39;t understand why Bitcoins could be useful (beyond the realm of &amp;quot;pseudo anonymous&amp;quot; and &amp;quot;secretive&amp;quot;) but the above is as clear cut example as any. Bitcoins allow merchants to not worry about fraud and create an entire payment system around the idea that once you are paid, the funds are yours! There is no period of uncertainty and thus you don&amp;#39;t have to price in fraud into every part of the system.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <title>pinning your hopes</title>
        <link href="http://shtylman.com/post/pinning-your-hopes"/>
        <updated>2012-02-27T00:00:00+00:00</updated>
        <id>http://shtylman.com/post/pinning-your-hopes</id>
        <content type="html">&lt;p&gt;This is a post about the &lt;a href=&quot;https://npmjs.org&quot;&gt;npm&lt;/a&gt; (node package management) and how I think it got versioning wrong in the package.json file. If you don&amp;#39;t care about node there are still relevant items in this post about dependencies in development and deployment.&lt;/p&gt;

&lt;p&gt;At first I was going to write a blog post about how the fuzzy versions are the wrong way to do it, but found &lt;a href=&quot;http://debuggable.com/posts/npm-an-intervention:4f44dd25-a114-4361-ada1-6cefcbdd56cb&quot;&gt;this post&lt;/a&gt; that covered the topic. However I think this post, and others that talk about the fuzzy version issue are missing the core fundamentals behind WHY fuzzy versions are bad for development and deployment.&lt;/p&gt;

&lt;p&gt;My argument stems from a few statements which I treat as axioms. I will try to address how each one relates to fuzzy versioning and why it matters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any change no matter how small is a &amp;quot;risk&amp;quot; to a deployed system&lt;/li&gt;
&lt;li&gt;Consistency matters even for development&lt;/li&gt;
&lt;li&gt;Deployment failures are better than runtime failures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Often when I hear about fuzzy versions in the node community it goes hand in hand with talk of &lt;a href=&quot;https://github.com/mojombo/semver&quot;&gt;semver&lt;/a&gt;. The idea of semver is good and can be used regardless of how you handle dependencies, but what semver does not expose is that even a change to version 0.0.x of a package can introduce a bug. For a dynamic language it could be as simple as a typo or a missing &amp;#39;var&amp;#39; keyword. The point is not about the bug but that it has been introduced even in a version that is considered a &amp;quot;safe&amp;quot; point release. Now, if your library has not pinned its dependencies, this bug now becomes your bug. More critically (and as the referenced npm post states) running &amp;#39;npm install&amp;#39; at two different times will yield two different codebases. The bottom line here is that semver is not a static analysis or a test tool but a way to communicate to another *person *about what types of changes they should expect and check for. It is not a substitute for a developer actually checking the changelog and doing testing. Maybe you don&amp;#39;t care about this &amp;quot;risk&amp;quot; in production, but when you are writing a library, these risks are not for you to access.&lt;/p&gt;

&lt;p&gt;When npm was first introduced it was touted as a tool for &amp;quot;development&amp;quot; versus &amp;quot;deployment&amp;quot;. An argument developers make is that the fuzzy versions help them iterate quicker. I have yet to see &amp;quot;proof&amp;quot; of this but that is not the point. Fuzzy versions hurt development groups as well and for the same reasons as listed above. If I pull down your clean codebase and the versions are fuzzy, I may be getting versions which the original developer tested with. Now when I begin developing I am working with new &amp;quot;quirks&amp;quot; and more importantly wasting time debugging problems that no one else will be able to reproduce on their codebase until they wipe their dependencies and reinstall. I have not only wasted my time but other developer time simply because of a &amp;quot;harmless&amp;quot; point release. If you want to iterate quickly you can still do it, pinned versions in the package.json file do not stop you. Npm already has &amp;#39;npm link&amp;#39; for local development. One of the less used features of npm versions is the ability to specify a tarball url or git repo to install from. THIS is how your team can iterate quickly on branches if it so chooses, but these should never be published to npm as such.&lt;/p&gt;

&lt;p&gt;The final bullet point has to do with the generic idea of deployment failure. Another argument I have heard against using npm for deployment is that it is flaky, my firm has better (read different) ways, or that binaries are annoying. I am not trying to say your ways are worse or that the npm website can&amp;#39;t go offline (which can be protected against), but what I am going to argue is that a failure during deployment is better than during runtime. In the case of binaries and compiled code, you will know right away if your deployment worked or did not. If it failed, you can take action immediately without the error being deferred to runtime. There is no &amp;quot;partial&amp;quot; deployment with npm, it worked or it didn&amp;#39;t. If you use fuzzy versioning, the deployment can work just fine yet defer the error to runtime.&lt;/p&gt;

&lt;p&gt;Npm is addressing some of these issues with the new &lt;a href=&quot;http://blog.nodejs.org/2012/02/27/managing-node-js-dependencies-with-shrinkwrap/&quot;&gt;npm shrinkwrap&lt;/a&gt; command. This creates yet another .json file in your repo. To me, this is just a &amp;quot;patch&amp;quot; on top of the real problem. Yes, it does &amp;quot;solve&amp;quot; the issue of pinned packages, but it does so in a poor way. Instead of keeping the packaging process simple with just the package.json file, another command and file are introduced. This seems like an admission that the versions should have been pinned from the start but instead of fixing that (which is probly impossible at this point) a new file is created. Nasty but arguably pragmatic.&lt;/p&gt;

&lt;p&gt;This is not a post to hate on npm, in fact I think npm has many great features. I use npm daily for deployments and they always go smoothly (yes I use pinned versions). One last note about what makes package pinning great with npm: dependencies are localized! Each package maintainer can depend on their own desired package versions and test with those versions. The prominent people in the node community often develop many packages and don&amp;#39;t want to update every single one when things change, however, they are in the nice position of being the maintainers and know what they are doing. When you are the consumer of a package, you don&amp;#39;t always have such luxuries or trust and opening a communication channel is not the way to solve the problem. You cannot just tell someone they must vet changes by you or stick to semver (which I have shown isn&amp;#39;t foolproof).&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <title>scraping broken SSL pages with node.js</title>
        <link href="http://shtylman.com/post/scraping-broken-ssl-pages-with-node-js"/>
        <updated>2011-11-21T00:00:00+00:00</updated>
        <id>http://shtylman.com/post/scraping-broken-ssl-pages-with-node-js</id>
        <content type="html">&lt;p&gt;To collect the data for &lt;a href=&quot;https://courseoff.com&quot;&gt;courseoff.com&lt;/a&gt; I scrape university websites on demand. This means that I have to perform http queries to the sites and then parse the resulting pages. Usually, this is not a problem as node.js has very simple APIs for performing both http and https requests. However, some schools have old webservers which make this task trickier.&lt;/p&gt;

&lt;p&gt;Scraping a normal, up to date website, over SSL is not a problem; however, when you encounter a site with a broken web browser ssl implementation things go downhill fast.&lt;/p&gt;

&lt;p&gt;You might see an error such as the following when trying to curl the url.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;curl: (35) error:14077417:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert illegal parameter&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This was strange to me as my browser loaded the page just fine. Chrome does however give a hint as to something being wrong. When I click on the green lock icon, I get the usual certificate notice as well as an additional piece of information:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The connection had to be retried using SSL 3.0. This typically means that the server is using very old software and may have other security issues.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Clearly something is not right with the webserver here and that is what is causing curl, and subsequently my nodejs requests, to fail.&lt;/p&gt;

&lt;p&gt;Doing some basic digging, I was able to find this nice little tidbit in the openssl documentation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Allow legacy insecure renegotiation between OpenSSL and unpatched clients or servers. See the &lt;strong&gt;SECURE RENEGOTIATION&lt;/strong&gt; section for more details.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that I had this option to try, I had to figure out a way to make node.js use it. Reading some code led me to understand that the &amp;#39;Agent&amp;#39; is the object which handles the options for http(s) requests which are ultimately passed to the SSL context. When creating the agent, you pass in an options object, this object contains two fields which need to be used for this case: secureProtocol and secureOptions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;secureProtocol&lt;/strong&gt; specifies which negotiation method to use&lt;br&gt;
&lt;strong&gt;secureOptions&lt;/strong&gt; are the flags passed to the context to change the behavior&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My final agent object had the following form:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;agent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;secureProtocol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;SSLv3_method&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;secureOptions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;constants&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;My https request options object just need to include the &amp;#39;agent&amp;#39; key and have it set to the agent object I created. This filtered down to the underlying ssl context and set the context options. The request was a success!&lt;/p&gt;

&lt;p&gt;This will only work with node.js &amp;gt;= 0.6.3 because the constants are only available after that. Other constants from the bug workaround section of the openssl documentation are also available for your needs.&lt;/p&gt;

&lt;h2&gt;References&lt;/h2&gt;

&lt;h3&gt;ssl docs&lt;/h3&gt;

&lt;p&gt;http://www.openssl.org/docs/ssl/SSL_CTX_set_options.html&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <title>the tail of MongoDB</title>
        <link href="http://shtylman.com/post/the-tail-of-mongodb"/>
        <updated>2011-06-12T00:00:00+00:00</updated>
        <id>http://shtylman.com/post/the-tail-of-mongodb</id>
        <content type="html">&lt;p&gt;I recently gave a talk at MongoNYC 2011 about using MongoDB as a messaging layer. The rationale behind doing something like this would be to maintain a log of all the messages passed between two clients. While there are many different IPC schemes available, I thought it would be interesting to build something simple on top of MongoDB using the tailable cursor feature. After giving the talk, I wanted to explore the performance characteristics of such a setup.&lt;/p&gt;

&lt;p&gt;Before jumping into my benchmarking details, there are two important concepts to understand behind using MongoDB for message passing.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://www.mongodb.org/display/DOCS/Tailable+Cursors&quot; title=&quot;tailable cursor&quot;&gt;tailable cursor&lt;/a&gt; gets its inspiration from the &lt;em&gt;tail -f&lt;/em&gt; command in unix systems. For those unfamiliar with what that does, the idea is to open a file, listen for new additions to the end of the file, and print those. The program does not terminate when it reaches the end of the file, instead, it waits for more data. Using this approach, a simple message queue can be created with MongoDB. A producer creates messages and inserts them into MongoDB and then a consumer(s) is able to read those messages. While this can be simulated by keeping track of document IDs (in MongoDB and other database systems), in MongoDB the tailable cursor is actually supported server side and tracks the last returned document. This is much cheaper than having to constantly requery.&lt;/p&gt;

&lt;p&gt;In MongoDB tailable cursors can only be opened on &lt;a href=&quot;http://www.mongodb.org/display/DOCS/Capped+Collections&quot; title=&quot;capped collections&quot;&gt;capped collections&lt;/a&gt;. This is because a capped collection is a fixed size and only allows insertions. This means that once the number of documents exhausts the collection size, newly written documents will start overwriting the first inserted documents. An important note about capped collections is that insertion order is the natural sort order. This means that when the tail cursor fetches documents, it will get them back in the order they were inserted. If you have more than one producer and insertion order matters, then you will need to either use separate collections or do your own reordering consumer side. For my examples, there is only one producer and thus natural (insertion) order is acceptable.&lt;/p&gt;

&lt;p&gt;Now that we have some background on tailable cursors and capped collections, we can cover the benchmark setup. To perform the benchmark, I will have one producer and one consumer. The producer will get create a document of the format (Where the current time will have microsecond precision):&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;{ time: &amp;lt;current time in seconds&amp;gt; }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The producer will generate 100,000 of these messages and insert them into the collection. To avoid dealing with a slow consumer, the collection will be made big enough to hold all of the possible messages:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createCollection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;messages&amp;quot;&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;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;capped&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The producer is a simple python application:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/python&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pymongo&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Connection&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;queues&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;coll&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100000&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;coll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;time&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()})&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;#This generates messages at a rate of about 3,900 msg/s&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.0001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;total: &amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;msg/s: &amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&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;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The consumer is a c++ client modeled after the default c++ tailable cursor example on the MongoDB page. It gets the system time upon reading a document and computes the latency between insert and read. The consumer is started before the producer:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;sys/time.h&amp;gt;&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;mongo/client/dbclient.h&amp;gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mongo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argv&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;n&quot;&gt;DBClientConnection&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;localhost&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// minKey is smaller than any other possible value&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;BSONElement&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;firstElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// { $natural : 1 } means in forward capped collection insertion order&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Query&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;$natural&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;loc,val&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeval&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&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;n&quot;&gt;auto_ptr&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;queues.messages&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;QueryOption_CursorTailable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&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;k&quot;&gt;if&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;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;more&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;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isDead&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;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;sleepsecs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// we will try more() again&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BSONObj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;lastId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;_id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;time&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

            &lt;span class=&quot;n&quot;&gt;gettimeofday&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;tv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tv_sec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tv_usec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1000000.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;, &amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&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;c1&quot;&gt;// prepare to requery from where we left off&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QUERY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;_id&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastId&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;$natural&amp;quot;&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&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;p&gt;Running the consumer/producer pair generated the following latency graph:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/post/the-tail-of-mongodb/simple_cpp1.png&quot; alt=&quot;&quot; title=&quot;Default c++ consumer&quot;&gt;&lt;/p&gt;

&lt;p&gt;The graph is not lines, but actually 100,000 points that represent the &lt;em&gt;N-th&lt;/em&gt; packet versus the latency (&lt;em&gt;read time - write time&lt;/em&gt;). The above graph has a standard deviation of: &lt;em&gt;0.29693s&lt;/em&gt;. While these results are not horrible, the sawtooth nature of the graph would indicate that there is something strange going on and that ideally, we can do much better and decrease the latency. I ran a simple consumer (without clearing the producer data) to see if the bottleneck was in the write side or read side:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/post/the-tail-of-mongodb/pure_read1.png&quot; alt=&quot;&quot; title=&quot;Default c++ consumer - Read Only&quot;&gt;&lt;/p&gt;

&lt;p&gt;Because the read only graph is essentially linear, it means that the consumer has no problem in reading all of the data if it is available and likewise, the producer did not have problems inserting the data. (The latency is irrelevant here as the data was inserted before the consumer had to read it). So given the above graph, we know the consumer can handle reading the data consistently if it is available, so the sawtooth pattern must emerge from what happens when new data is being inserted.&lt;/p&gt;

&lt;p&gt;Taking another look at the Default C++ consumer graph, I noted that the consumer only goes back to ~1s latency when the previous latency was almost 0. This information, along with the c++ code which contains a sleep for 1 second was the &lt;em&gt;aha!&lt;/em&gt; moment. When there are no more documents to read, the client waits for new documents to show up. Unfortunately, instead of being woken up when new documents are available, the default example uses a simple poll. This is expensive if our goal is to minimize latency. To test my theory I removed the sleep statement from the code and ran the consumer/producer pair again:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/post/the-tail-of-mongodb/no_sleep.png&quot; alt=&quot;&quot; title=&quot;No Sleep&quot;&gt;&lt;/p&gt;

&lt;p&gt;This method produced a standard deviation of &lt;em&gt;0.000739s&lt;/em&gt;. However, this is not the end solution as it has one major problem; it uses a tight loop which causes high CPU load locally and worse yet, thrashes the mongo server. Looking over the c++ driver API I found an interesting query option: &lt;strong&gt;AwaitData&lt;/strong&gt; defined to: &lt;em&gt;&amp;quot;If we are at the end of the data, block for a while rather than returning no data. After a timeout period, we do return as normal.&amp;quot;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The AwaitData option sounded like just the thing I needed. I modified the query code to the following:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;auto_ptr&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;queues.messages&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QueryOption_CursorTailable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QueryOption_AwaitData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It is important to note that this causes the &amp;quot;more&amp;quot; cursor method call to block for a short time. If you cannot afford to block, this will not be a solution for you (see conclusion about some thoughts about evented systems)&lt;/p&gt;

&lt;p&gt;And sure enough, when there were no more records to read, the local CPU would not spin. Yet I still noticed a problem. Since I start my consumer before the producer, I found that a bunch of re-querying was happening until the first record was inserted. This is due to a &amp;quot;dead&amp;quot; cursor. When the capped collection is empty, MongoDB does not keep a cursor open server side and thus the whole &amp;quot;tail&amp;quot; process never starts until at least one record is available. Given that I did not want to spin the local CPU or thrash the server, I inserted a sleep before the &amp;quot;break&amp;quot; when the cursor was &amp;quot;dead&amp;quot;. This would cause a requery every 1 second until a cursor could be created (at least 1 record was inserted). While this did solve the spinning CPU problem, I found this solution caused a high initial latencies because of the sleep before the query:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/post/the-tail-of-mongodb/sleep_on_dead.png&quot; alt=&quot;&quot; title=&quot;Sleep before re-query&quot;&gt;&lt;/p&gt;

&lt;p&gt;Once the initial query happened, and a valid cursor obtained, then further queries were not needed and the latency remained very low. However the start up latencies were poor because we could be anywhere in the 1 second sleep before we are able to re-query.&lt;/p&gt;

&lt;p&gt;To solve this problem, I used a dummy document to prime the collection and cursor. Given that even with a single document, a cursor would be created server side and the client would no longer have to query waiting for a valid cursor. While this solution is also not optimal, it does avoid having to keep querying the database in hopes of obtaining a valid cursor. So here with all the pieces in place (AwaitData, dummy document, and sleep before query):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/post/the-tail-of-mongodb/final.png&quot; alt=&quot;&quot; title=&quot;Using dummy document&quot;&gt;&lt;/p&gt;

&lt;p&gt;This produced a standard deviation of &lt;em&gt;0.000662s&lt;/em&gt;, and never spun the CPU. The final c++ client code to produce this result (just the outer while loop):&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&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;n&quot;&gt;auto_ptr&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;queues.messages&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
             &lt;span class=&quot;n&quot;&gt;QueryOption_CursorTailable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QueryOption_AwaitData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&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;k&quot;&gt;if&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;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;more&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;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isDead&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;c1&quot;&gt;// this sleep is important for collections that start out with no data&lt;/span&gt;
                 &lt;span class=&quot;n&quot;&gt;sleepsecs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                 &lt;span class=&quot;k&quot;&gt;break&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;k&quot;&gt;continue&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;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BSONObj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;lastId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;_id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;time&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

         &lt;span class=&quot;c1&quot;&gt;// handle the dummy document {time: 0.0}&lt;/span&gt;
         &lt;span class=&quot;c1&quot;&gt;// yes, not a great comparison for doubles, just an example&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

         &lt;span class=&quot;n&quot;&gt;gettimeofday&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;tv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tv_sec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tv_usec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1000000.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;, &amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&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;c1&quot;&gt;// prepare to requery from where we left off&lt;/span&gt;
     &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QUERY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;_id&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastId&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;$natural&amp;quot;&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;p&gt;You can see how I bypass the dummy document used to prime the cursor as an example. I ran a similar consumer/producer test with no time delay on the producer (producing ~24,000 msg/s) and also obtained similar results with a standard deviation of &lt;em&gt;0.000753s&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;Conclusions&lt;/h3&gt;

&lt;p&gt;Given the above latency measurements, I found that MongoDB tail cursors and capped collections performed much better than I expected. I was hoping for latencies in the 10 to 100 millisecond range but instead often got sub millisecond latencies for standard deviation with peaks of 5 milliseconds for the last run. Depending on your definition of &amp;quot;low latency&amp;quot; using MongoDB for basic message passing is quite viable and gives the added benefit of logging all of the passed messages for things like replay or catch up (if you have sequence numbers).&lt;/p&gt;

&lt;p&gt;In performing this benchmark I encountered some pain points. The biggest one that may lead users astray is the incomplete example on the mongodb.org page (as of this writing). It does not mention the very necessary AwaitData flag, and also incurs a high latency due to the use of sleep.&lt;/p&gt;

&lt;p&gt;Another problem (and something I consider a bug) is the behavior when there are no items in the collection. Depending on your use case and consumer/producer startup times, this may be a hidden issue that is hogging CPU time until a valid cursor is created. From my point of view, a valid cursor should be created immediately (even with no documents) that can then behave properly under the AwaitData condition.&lt;/p&gt;

&lt;p&gt;And finally, it would be nice to expose an API that allows the c++ client to epoll (or some other notification scheme) when new documents are available. Since with the AwaitData call the &amp;quot;more&amp;quot; cursor method blocks for a bit, this becomes very unsafe in event driven systems which should not be blocking (or any system that should not block). Since there is a socket underlying the connection to the DB, this seems like a reasonable addition that would solve such a problem.&lt;/p&gt;

&lt;h3&gt;Additional Notes&lt;/h3&gt;

&lt;p&gt;All testing was done on a Core i7 920 running Ubuntu 10.10 using an SSD as the storage medium. I used the &lt;a href=&quot;https://github.com/mongodb/mongo/commit/3d909045d30dcd6af39bf21dd62a379275262ccd&quot;&gt;latest&lt;/a&gt; of the MongoDB master github branch as of June 9th.&lt;/p&gt;

&lt;p&gt;Initially, I tested a simple python consumer, but it too suffered from the sleep problems and did not expose query options in the same way the c++ driver did. I stuck with the c++ driver as an example given the clarity in demonstrating the various gotchas in doing the benchmark.&lt;/p&gt;

&lt;p&gt;I toyed around with the node-mongodb-native driver and think that the &amp;quot;streaming&amp;quot; aspects could make the callback API work a bit better but would need to be flushed out more with how the GET_MORE operation to the server is handled. I found that I could lock up the server if I was not careful with how many GET_MORE ops were being sent for the cursor.&lt;/p&gt;
</content>
    </entry>
    

</feed>
