<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><description>twitter.com/jhorman</description><title>Jason Horman</title><generator>Tumblr (3.0; @jhorman)</generator><link>http://blog.jhorman.org/</link><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/jhorman" /><feedburner:info uri="jhorman" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://tumblr.superfeedr.com/" /><item><title>Created this User CSS to make reddit look more like Hacker...</title><description>&lt;img src="http://24.media.tumblr.com/tumblr_lvvegi6NGw1qz4i0io1_500.png"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Created this &lt;a href="http://code.grid.in.th/" target="_blank"&gt;User CSS&lt;/a&gt; to make reddit look more like Hacker News.&lt;/p&gt;
&lt;script src="https://gist.github.com/1446209.js?file=reddit_userstyle.css"&gt;&lt;/script&gt;&lt;img src="http://feeds.feedburner.com/~r/jhorman/~4/CWw2CbuV9vI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jhorman/~3/CWw2CbuV9vI/13910989368</link><guid isPermaLink="false">http://blog.jhorman.org/post/13910989368</guid><pubDate>Thu, 08 Dec 2011 00:41:06 -0500</pubDate><feedburner:origLink>http://blog.jhorman.org/post/13910989368</feedburner:origLink></item><item><title>Android StrictMode</title><description>&lt;p&gt;I didn&amp;#8217;t know &lt;a href="http://developer.android.com/reference/android/os/StrictMode.html" title="Android Strict Mode"&gt;about this&lt;/a&gt;. Going to turn it on in Springpad&amp;#8217;s Android build and see what happens.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;
&lt;pre class="prettyprint"&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;StrictMode&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;setThreadPolicy&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;code&gt;&lt;a href="http://developer.android.com/reference/android/os/StrictMode.ThreadPolicy.Builder.html"&gt;&lt;span class="typ"&gt;StrictMode&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="typ"&gt;ThreadPolicy&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="typ"&gt;Builder&lt;/span&gt;&lt;/a&gt;&lt;/code&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt;&lt;br/&gt;                 &lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;detectDiskReads&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt;&lt;br/&gt;                 &lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;detectDiskWrites&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt;&lt;br/&gt;                 &lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;detectNetwork&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt;   &lt;/span&gt;&lt;span class="com"&gt;// or .detectAll() for all detectable problems&lt;/span&gt;&lt;span class="pln"&gt;&lt;br/&gt;                 &lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;penaltyLog&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt;&lt;br/&gt;                 &lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;build&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;/pre&gt;
&lt;/span&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jhorman/~4/041GhbV54z0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jhorman/~3/041GhbV54z0/13907256239</link><guid isPermaLink="false">http://blog.jhorman.org/post/13907256239</guid><pubDate>Wed, 07 Dec 2011 23:04:31 -0500</pubDate><feedburner:origLink>http://blog.jhorman.org/post/13907256239</feedburner:origLink></item><item><title>VirtualBox for dev teams</title><description>&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_llbkfqqCh01qz4i0i.png"/&gt;&lt;/p&gt;
&lt;p&gt;At Springpad the development team has spent a lot of time setting up our local environments. The setup includes:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;MySQL for Quartz job scheduling and random other lookups&lt;/li&gt;
&lt;li&gt;Liquibase for creating and updating MySQL schemas&lt;/li&gt;
&lt;li&gt;Cassandra instances for storing block data&lt;/li&gt;
&lt;li&gt;SOLR instances for faceting and full text search&lt;/li&gt;
&lt;li&gt;Zookeeper for atomic counters and distributed locks&lt;/li&gt;
&lt;li&gt;Memcached&lt;/li&gt;
&lt;li&gt;Redis (for some new development we are doing)&lt;/li&gt;
&lt;li&gt;And more&amp;#8230;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;We documented the ever changing setup. We wrote shell scripts to automate the process. For Python we switched from shell scripts to &lt;a href="http://fabfile.org"&gt;Fabric&lt;/a&gt;. In the end though it still felt cumbersome to get a new environment setup for development.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;VirtualBox&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We realized just a few months back (we are probably late to the game) that we could setup the entire stack in a &lt;a href="http://www.virtualbox.org/"&gt;VirtualBox&lt;/a&gt; instance. Not only that, but we could locally run our services exactly as they run in production, on a Debian distribution. We are now setting developers up with:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;VirtualBox running a snapshot of a &lt;a href="http://www.debian.org/distrib/netinst#smallercd"&gt;minimal Debian installation&lt;/a&gt;. &lt;em&gt;(This instance runs in about 163MB of memory)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;The instance is set to &lt;a href="http://www.virtualbox.org/manual/ch06.html"&gt;Bridged Adapter&lt;/a&gt; network mode so that the machine is directly addressable.&lt;/li&gt;
&lt;li&gt;Then we install all of the services listed above, and snapshot again calling this &amp;#8220;Initial Springpad&amp;#8221;. &lt;em&gt;(This instance runs in about 352MB of memory)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;We then can copy this setup to the various development machines.&lt;/li&gt;
&lt;li&gt;From there the developer can start the &amp;#8220;Initial Springpad&amp;#8221; instance and connect to it directly from their local OSX development environment.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;Nice Benefits&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Fast start/stop:&lt;/strong&gt; To conserve memory, or at the end of the day, you can simply tell VirtualBox to &amp;#8220;Save machine state&amp;#8221;. VirtualBox will pause the VM and shutdown. This takes about 5 seconds. When you want to restart development, VirtualBox will unpause the VM, also in about 5 seconds. Contrast that with starting and stopping the 10 or so services we had running on OSX before.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Snapshots: &lt;/strong&gt;Whenever you feel like it you can &lt;a href="http://www.virtualbox.org/manual/ch01.html#snapshots"&gt;take additional snapshots&lt;/a&gt;. Before testing that bulk delete operation from Cassandra, take a snapshot. Test, throw the snapshot away and revert to the original instance of Cassandra. Very powerful.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clean Mac: &lt;/strong&gt;Using VirtualBox moved all of the configuration, log, and installation files of all of these services out of our personal Mac OSX /usr/local, /var/log, /etc directories. They are now neatly tucked away in the VirtualBox instance.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;So I definitely would recommend checking out VirtualBox if you want to simplify your local development environment.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jhorman/~4/x21c7MdwCRo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jhorman/~3/x21c7MdwCRo/5565765467</link><guid isPermaLink="false">http://blog.jhorman.org/post/5565765467</guid><pubDate>Mon, 16 May 2011 23:03:43 -0400</pubDate><feedburner:origLink>http://blog.jhorman.org/post/5565765467</feedburner:origLink></item><item><title>Picture from the back.</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_lkhykuJc4V1qz4i0io1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Picture from the back.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jhorman/~4/2KtvqQKG_jI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jhorman/~3/2KtvqQKG_jI/5089571835</link><guid isPermaLink="false">http://blog.jhorman.org/post/5089571835</guid><pubDate>Sat, 30 Apr 2011 23:19:41 -0400</pubDate><feedburner:origLink>http://blog.jhorman.org/post/5089571835</feedburner:origLink></item><item><title>Really liking the new monitor arm for the LCD. It swivels,...</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_lkhyfcl0oG1qz4i0io1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Really liking the &lt;a href="http://www.ergotron.com/Products/tabid/65/PRDID/56/Default.aspx"&gt;new monitor arm&lt;/a&gt; for the LCD. It swivels, extends/retracts, rotates, and has a really nice look.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jhorman/~4/2yg0nzMDrfM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jhorman/~3/2yg0nzMDrfM/5089527483</link><guid isPermaLink="false">http://blog.jhorman.org/post/5089527483</guid><pubDate>Sat, 30 Apr 2011 23:18:13 -0400</pubDate><feedburner:origLink>http://blog.jhorman.org/post/5089527483</feedburner:origLink></item><item><title>Pycharm OSX install graphic</title><description>&lt;img src="http://24.media.tumblr.com/tumblr_lizkfjMTY11qz4i0io1_400.png"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Pycharm OSX install graphic&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jhorman/~4/VjBdoByOYuM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jhorman/~3/VjBdoByOYuM/4262313410</link><guid isPermaLink="false">http://blog.jhorman.org/post/4262313410</guid><pubDate>Fri, 01 Apr 2011 14:24:25 -0400</pubDate><feedburner:origLink>http://blog.jhorman.org/post/4262313410</feedburner:origLink></item><item><title>Servers are only as good as their clients</title><description>&lt;p&gt;When we started working with Cassandra we experimented with different Java and Python clients. While they all supported the required APIs, and they each added their own sugar on top, not all of them had thought through how to architect a client in a way that matched the power of Cassandra itself. A backend service, whether it is SOLR, memcached, Redis, or Cassandra, is only as good as the client libraries available.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Connection management&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Connection pooling.&lt;/li&gt;
&lt;li&gt;+1 for &amp;#8220;smart&amp;#8221; pooling that picks the least loaded backend.&lt;/li&gt;
&lt;li&gt;Auto reconnect&lt;/li&gt;
&lt;li&gt;Auto removal of bad connections from the pool. Auto recovery on server recovery.&lt;/li&gt;
&lt;li&gt;Connect/read timeouts.&lt;/li&gt;
&lt;li&gt;+1 for auto discovery of available hosts. (Zookeeper, Cassandra)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Logging/Operations&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Configurable logging for monitoring.&lt;/li&gt;
&lt;li&gt;Some way of getting performance metrics, error rates, current configuration.&lt;/li&gt;
&lt;li&gt;In Java, JMX config, stats, cluster management.&lt;/li&gt;
&lt;li&gt;+1 for a simple Rest/JSON based management API, stats, config, cluster management, etc.&lt;/li&gt;
&lt;li&gt;API for explicit overrides. Ops generally wants the ability to say sorry $CLIENT_LIB, I don&amp;#8217;t trust you, and I know that node 11 is down right now.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;It is actually pretty hard to get all of this right. Why start from scratch though. Take a look at &lt;a href="https://github.com/rantav/hector"&gt;Hector&lt;/a&gt; or &lt;a href="https://github.com/driftx/Telephus"&gt;Telephus&lt;/a&gt; for Cassandra, or &lt;a href="https://github.com/dustin/java-memcached-client"&gt;java-memcached-client&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jhorman/~4/LMM3K-1CTBo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jhorman/~3/LMM3K-1CTBo/4187762971</link><guid isPermaLink="false">http://blog.jhorman.org/post/4187762971</guid><pubDate>Tue, 29 Mar 2011 14:00:07 -0400</pubDate><feedburner:origLink>http://blog.jhorman.org/post/4187762971</feedburner:origLink></item><item><title>Twisted timeouts</title><description>&lt;p&gt;Here is a useful snippet we use when working with twisted. It is nice to be able to just decorate a method with a timeout.&lt;/p&gt;
&lt;script src="https://gist.github.com/891714.js"&gt; &lt;/script&gt;&lt;img src="http://feeds.feedburner.com/~r/jhorman/~4/db3mF-wrp_A" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jhorman/~3/db3mF-wrp_A/4175927232</link><guid isPermaLink="false">http://blog.jhorman.org/post/4175927232</guid><pubDate>Mon, 28 Mar 2011 23:05:00 -0400</pubDate><category>twisted</category><category>python</category><feedburner:origLink>http://blog.jhorman.org/post/4175927232</feedburner:origLink></item><item><title>Async IO</title><description>&lt;p&gt;Some of the backend systems that springpad uses are being written in Python and use &lt;a href="http://twistedmatrix.com/trac/"&gt;Twisted&lt;/a&gt;. Twisted, &lt;a href="http://www.tornadoweb.org/"&gt;tornado&lt;/a&gt;, &lt;a href="http://rubyeventmachine.com/"&gt;eventmachine&lt;/a&gt;, &lt;a href="http://www.jboss.org/netty"&gt;netty&lt;/a&gt;, are frameworks that ease development of services that want to take advantage of non-blocking IO. Instead of scaling via more threads, or more processes, that are IO bound, the frameworks make use various techniques to enable asynchronous notifications when IO is available.&lt;/p&gt;
&lt;p&gt;For Springpad, this makes a ton of sense. We connect to a large number of 3rd party services. Amazon, Yelp, Google, Pricegrabber, Netflix, and more. We can&amp;#8217;t control the response time of these services, and dedicating threads to just wait for responses can be expensive.&lt;/p&gt;
&lt;p&gt;When I read online about these frameworks, I generally find information about how they can scale to thousands of connections, can be used to implement real time services, how one is better than the other because it can handle yet another couple of hundred connections, how threads can actually outperform async IO under certain conditions. What I don&amp;#8217;t generally see people talking about -&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Async IO can remove the need for threads&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In many cases async IO can remove the need for threads in your application. Thread programming can be difficult. Many libraries are not thread safe (Java SimpleDateFormat, many python libs) and so you have to be very defensive. &lt;a href="http://gee.cs.oswego.edu/dl/index.html"&gt;Some people&lt;/a&gt; are very good at it, but there is plenty of evidence to suggest that getting multithreaded programming right is hard. I personally have been enjoying switching my mindset to single threaded. That said, async IO is still concurrent. You still have to be careful when dealing with shared state.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Many web 2.0 services are IO bound&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Many services spend a great deal of time talking to APIs outside of their control. Threads can be expensive, and hard to work with, when all you are trying to do is fetch some data from a web service. Internal queries to databases, nosql stores, memcached, all generally end up being IO bound. Springpad has code that fetches &amp;gt;100 items at a time from memcached and/or Cassandra.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Debate&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So sometimes I think that the debates about the need for, or the performance of, async IO frameworks, are missing a key part of the positive argument. There is inherent value in them in that the can lead to cleaner code with fewer bugs, while at the same time probably increasing scalability quite a bit.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jhorman/~4/r98n5Qzp0x8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jhorman/~3/r98n5Qzp0x8/4170212104</link><guid isPermaLink="false">http://blog.jhorman.org/post/4170212104</guid><pubDate>Mon, 28 Mar 2011 19:22:00 -0400</pubDate><feedburner:origLink>http://blog.jhorman.org/post/4170212104</feedburner:origLink></item><item><title>Tools and tech at springpadit.com</title><description>&lt;p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Yammer&lt;/strong&gt; - We use &lt;a href="http://yammer.com"&gt;Yammer&lt;/a&gt; to communicate internally. This includes project updates, build status, basketball bracket updates, and general shit giving.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Java &lt;/strong&gt;- Much of the original springpad backend is built in Java. Some of the front end is as well (GWT).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Python&lt;/strong&gt; - Some of the newer services are being built in Python. Specifically on top of &lt;a href="http://twistedmatrix.com/trac/"&gt;Twisted&lt;/a&gt; &lt;a href="https://github.com/fiorix/cyclone"&gt;Cyclone&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Intellij/Pycharm&lt;/strong&gt; - We are big fans of &lt;a href="http://www.jetbrains.com/"&gt;jetbrains&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JIRA&lt;/strong&gt; - We/I have looked for alternatives many times. You just can&amp;#8217;t beat the flexibility of JIRA though.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Confluence&lt;/strong&gt; - Again, a very flexible tool. In addition to holding documentation we have automated processes that add reporting, build information, user feedback, all to confluence.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SOLR&lt;/strong&gt; - Our full text index, though we are investigating switching to &lt;a href="http://www.elasticsearch.org/"&gt;elastic search&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cassandra&lt;/strong&gt; - The main data store springpad uses. Replicated, self healing, scalable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GTalk&lt;/strong&gt; - For rapid un-yammerable things.&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jhorman/~4/iOwMBnyL0F8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/jhorman/~3/iOwMBnyL0F8/4168977197</link><guid isPermaLink="false">http://blog.jhorman.org/post/4168977197</guid><pubDate>Mon, 28 Mar 2011 18:36:00 -0400</pubDate><category>springpad</category><feedburner:origLink>http://blog.jhorman.org/post/4168977197</feedburner:origLink></item></channel></rss>
