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

  <title type="text">Sean Cribbs</title>

  <link rel="self" href="http://seancribbs.com/atom.xml" />
  <link rel="alternate" type="text/html" href="http://seancribbs.com/" />

  <id>http://seancribbs.com/</id>

  <generator uri="http://nanoc.stoneship.org/" 
    version="3.2.3">Nanoc3</generator>

  <author>
    <name>Sean Cribbs</name>
    <uri>http://seancribbs.com/</uri>
  </author>
  
  <updated>2012-01-16T15:00:00Z</updated>

  
    <entry>
      <author><name>Sean Cribbs</name></author>
      <published>2012-01-16T15:00:00Z</published>
      <title>Webmachine vs. Grape</title>
      <link rel="alternate" type="text/html" 
        href="http://seancribbs.com/tech/2012/01/16/webmachine-vs-grape/" />
      <id>http://seancribbs.com/tech/2012/01/16/webmachine-vs-grape/</id>
      <content type="html">&lt;p&gt;Back in December, I gave my &lt;a href='http://rubyconf-webmachine.heroku.com/'&gt;&lt;em&gt;Resources, For Real This Time&lt;/em&gt;&lt;/a&gt; talk for the third time, this time at NYC.rb. After the talk, I got into a very emphatic discussion with &lt;a href='http://code.dblock.org'&gt;Daniel Doubrovkine&lt;/a&gt; and &lt;a href='http://twitter.com/johnjoseph'&gt;John &amp;#8220;JJB&amp;#8221; Bachir&lt;/a&gt; about the differences between &lt;a href='https://github.com/seancribbs/webmachine-ruby'&gt;Webmachine&lt;/a&gt;&amp;#8217;s approach and &lt;a href='https://github.com/intridea/grape'&gt;Grape&lt;/a&gt;&amp;#8217;s approach and their relative strengths. Daniel followed it up with an interesting blog post titled &lt;a href='http://code.dblock.org/grape-vs-webmachine'&gt;Grape vs. Webmachine&lt;/a&gt;. I&amp;#8217;ve had some time to think it all over and so I figured it was about time I wrote a response.&lt;/p&gt;

&lt;p&gt;Daniel poses the question &amp;#8220;Should you build your next RESTful API with Grape or Webmachine?&amp;#8221; Before I address his question (and the inherent assumptions therein), I want to tell you a bit more about Webmachine and why it is fundamentally different from the prevailing approaches.&lt;/p&gt;

&lt;h3 id='protocols_are_contracts'&gt;Protocols are contracts&lt;/h3&gt;

&lt;p&gt;If you Google &amp;#8221;&lt;a href='http://www.google.com/search?q=define%3A+protocol'&gt;define: protocol&lt;/a&gt;&amp;#8221;, two definitions appear:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The official procedure governing affairs of state or diplomatic occasions.&lt;/li&gt;

&lt;li&gt;The established code of procedure or behavior in any group, organization, or situation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href='http://www.merriam-webster.com/dictionary/protocol'&gt;Merriam-Webster&lt;/a&gt; gives some additionally detailed definitions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;a code prescribing strict adherence to correct etiquette and precedence (as in diplomatic exchange and in the military services) &amp;#60;a breach of &lt;em&gt;protocol&lt;/em&gt;&amp;#62;&lt;/li&gt;

&lt;li&gt;a set of conventions governing the treatment and especially the formatting of data in an electronic communications system &amp;#60;network &lt;em&gt;protocols&lt;/em&gt;&amp;#62;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Another way of saying this is that &lt;em&gt;protocols are contracts&lt;/em&gt; or &lt;em&gt;conventional manners of speech and behavior&lt;/em&gt;. To violate that contract is to be misunderstood, worse, to offend or to cause unintended actions. Granted, computer protocols may have lesser social consequences than social protocols, but if we don&amp;#8217;t speak them properly, our programs won&amp;#8217;t work.&lt;/p&gt;

&lt;h3 id='protocols_are_fsms'&gt;Protocols are FSMs&lt;/h3&gt;

&lt;p&gt;The classical way to implement a protocol participant (that is, a client, server or peer) is a &lt;a href='http://en.wikipedia.org/wiki/Finite-state_machine'&gt;finite state machine&lt;/a&gt; (FSM). Why? Protocols are usually defined in terms of &amp;#8220;in this situation, do that&amp;#8221; or &amp;#8220;react to this condition by doing that&amp;#8221;. Many of those assertions are dependent on one another, meaning that they are not even relevant if other assertions have not been made previously. To illustrate this better, imagine the protocol of two heads of state meeting. Their meeting might go through these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Arrive at the same location.&lt;/li&gt;

&lt;li&gt;Shake hands and introduce other participants.&lt;/li&gt;

&lt;li&gt;Enter the meeting space.&lt;/li&gt;

&lt;li&gt;Negotiate an issue.&lt;/li&gt;

&lt;li&gt;Leave the meeting space.&lt;/li&gt;

&lt;li&gt;Arrive and speak at the press conference.&lt;/li&gt;

&lt;li&gt;Shake hands again.&lt;/li&gt;

&lt;li&gt;Depart the press conference.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;First, this is a discrete set of steps that must be followed in the order given. It wouldn&amp;#8217;t make much sense to negotiate the issue (which might have its own internal protocol) before you shake hands and enter the meeting space, or to discuss the negotiations at the press conference before you&amp;#8217;ve done any negotiation. Second, if one part of the protocol fails, other steps in the protocol may never occur! Imagine that upon arrival, the other head of state refuses to shake your hand or even look at you; you might abort the meeting altogether.&lt;/p&gt;

&lt;p&gt;Like protocols, in finite state machines, there are also discrete steps (states), and conditions that allow transition from one state to another. A transition may lead to another internal state, or an end state in which processing is terminated. Finite state machines are the essential way to implement protocols.&lt;/p&gt;

&lt;p&gt;And interesting side-effect of this coherence between protocol and FSM is that they are duals of each other. The FSM is an implementation of the protocol, and the protocol&amp;#8217;s states and assertions can be derived from the FSM. It&amp;#8217;s the kind of thing that researchers interested in provability and mathematical formulations of software get really excited about.&lt;/p&gt;

&lt;h3 id='so_what_does_this_have_to_do_with_webmachine_and_grape'&gt;So what does this have to do with Webmachine and Grape?&lt;/h3&gt;

&lt;p&gt;HTTP happens to be a protocol with a simple syntax but very rich semantic possibilities. If your application &amp;#8220;misspeaks&amp;#8221; HTTP, it might still be partially understood (the syntax may still be grasped), but the other party might miss out on some crucial subtlety your application wants to convey or might take an unexpected or undesirable action as a result.&lt;/p&gt;

&lt;p&gt;Despite HTTP&amp;#8217;s flexibility (laxness?), it&amp;#8217;s still important to speak the protocol as fluently as possible. Building a better Web is just as much about the brick and mortar (the HTTP protocol) as the paint and trim (&amp;#8220;Web Standards&amp;#8221; in the browser).&lt;/p&gt;

&lt;p&gt;Webmachine tries to do just that. Its core is an FSM of the server side of HTTP. The end states are response status codes (e.g. 200 OK or 404 Not Found). The transition conditions come from the &amp;#8220;MAY&amp;#8221;, &amp;#8220;MUST&amp;#8221;, &amp;#8220;SHOULD&amp;#8221; language in the &lt;a href='tools.ietf.org/html/rfc2616'&gt;HTTP/1.1 RFC 2616&lt;/a&gt; as well as the less formal aspects of the specification. The FSM determines which transitions to take based on facts about the request and facts about the resource being requested. Because the FSM is a dual of the HTTP protocol, we at Basho have taken to calling Webmachine &amp;#8220;an executable model of HTTP.&amp;#8221;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is where Webmachine fundamentally differs from Grape and other existing frameworks:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It implements an FSM that is a dual of the protocol, not an ever-varying stack of middleware.&lt;/li&gt;

&lt;li&gt;It focuses on determining facts about the resource, not performing actions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what I mean when I say that Webmachine is declarative (functional?) rather than imperative. By being declarative and focusing on the facts about your resource rather than &amp;#8220;what do I do when I get a request&amp;#8221;, a whole lot of complex and error-prone aspects of the protocol are hidden from the developer, and more importantly, done in a deterministic way every time.&lt;/p&gt;

&lt;p&gt;In contrast, Grape and most other Rack-based frameworks encourage you to (perhaps unwittingly) redefine HTTP semantics for every application. In my opinion, this is not just error-prone, it is wasteful. Why should you have to define what GET means everytime? You want to focus on the resources your application exposes, not implementing the protocol all over again. This is why Webmachine encapsulates those decisions (FSM!) and includes sensible defaults so that you only have to focus on the decisions and behaviors (transitions!) that your resources need to modify. You focus on what your resources &lt;em&gt;are&lt;/em&gt;, rather than what they &lt;em&gt;do&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id='rest_for_real_this_time'&gt;REST, For Real This Time&lt;/h3&gt;

&lt;p&gt;Daniel is by no means the only or greatest offender, but I take strong objection to his use of &amp;#8220;REST&amp;#8221;. He says,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Grape is a DSL for RESTful APIs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Simply exposing your service over HTTP and not treating it like RPC is not sufficient to be called &amp;#8220;RESTful&amp;#8221;, you must satisfy the &amp;#8220;Hypermedia Constraint&amp;#8221;. Daniel admits&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;#8230;you have to be disciplined about those API methods - they should represent resources, not RPC service endpoints.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&amp;#8230;but does not address Hypermedia. I could go into great detail about why the typical HTTP-based API is not REST, but that has been done by some really great people who have said it much better, &lt;a href='http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven'&gt;Roy Fielding&lt;/a&gt;, &lt;a href='http://oredev.org/2010/sessions/hypermedia-apis'&gt;Jon Moore&lt;/a&gt; and &lt;a href='http://nicksda.apotomo.de/'&gt;Nick Sutterer&lt;/a&gt;. Do check out their presentations and blogs.&lt;/p&gt;

&lt;h3 id='a_note_on_dsls'&gt;A note on &amp;#8220;DSLs&amp;#8221;&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Rubyists, we have a fetish for so-called &amp;#8220;DSLs&amp;#8221;.&lt;/strong&gt; It&amp;#8217;s time for an intervention.&lt;/p&gt;

&lt;p&gt;In reality, what we call DSLs in Ruby tend to be thin wrappers around the fluent-builder pattern with a dash of &lt;code&gt;instance_eval&lt;/code&gt; and &lt;code&gt;class_eval&lt;/code&gt; to remove block arguments and necessary uses of &lt;code&gt;self&lt;/code&gt;. (One lightning talk at RubyConf humorously called gratuitous use of the pattern &amp;#8220;Playskool MyFirstDSL&amp;#8221;.) Grape, and its elder cousin Sinatra, follow this pattern. On the surface, it seems to promote clean, concise, readable code. But at what cost? What complexity is hidden? Does it actually help you write better code, faster and more reliably, or are you in the end working around the DSL to do what you want?&lt;/p&gt;

&lt;p&gt;So this is where I take big issue with Daniel&amp;#8217;s argument:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I would grant Grape an advantage over favoring the API consumer, since it focuses on the expressiveness of the API.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That warm fuzzy the developer gets when writing an application with Grape is not correlated to the experience of the consumer of the API. It is indeed a strength that Grape can generate API consumer documentation from the code, but as Moore and Sutterer demonstrate, a truly RESTful service is mostly self-documenting.&lt;/p&gt;

&lt;p&gt;Maybe it&amp;#8217;s the fact that Webmachine(-Ruby) is a fairly faithful port of the original Erlang version, but when authoring it I felt disillusioned with metaprogramming magic. Instead of including a module and executing some class methods to decorate your Resource class, you use simple inheritance and override methods. Internally, modules only exist as namespaces and to separate functional concerns of the same class (see &lt;code&gt;Webmachine::Decision::Conneg&lt;/code&gt; or &lt;code&gt;Webmachine::Resource::Callbacks&lt;/code&gt;), they are never used to decorate or modify the behavior of the class they are included in. &lt;code&gt;Webmachine::Decision::FSM&lt;/code&gt; uses a loop to walk the decision graph, where individual state methods either return a &lt;code&gt;Symbol&lt;/code&gt; for the next state or a &lt;code&gt;Fixnum&lt;/code&gt; that is the response status code.&lt;/p&gt;

&lt;p&gt;That said, others have been working on higher level abstractions on top of Webmachine, ones that include &amp;#8220;DSLs&amp;#8221;. Whether they will provide more value or simplicity over the existing abstractions Webmachine provides has yet to shake out.&lt;/p&gt;

&lt;h3 id='so_which_should_you_use'&gt;So which should you use?&lt;/h3&gt;

&lt;p&gt;I think if I were still doing web APIs via Rails or Sinatra, Grape would be an extremely attractive alternative to those, having a lower barrier to entry than Webmachine. It&amp;#8217;s a great library and very well written. For an application that exposes very simple semantics, the amount of code you need to write in Grape is small, and you don&amp;#8217;t need to have any awareness or understanding of Webmachine&amp;#8217;s decision flow, and you can get consumer documentation nearly for free.&lt;/p&gt;

&lt;p&gt;On the other hand, I have been just as productive in Webmachine (both Ruby and Erlang) and now that I think more in terms of resources instead of actions, it feels more natural. I want to be able to add those extra semantics just by declaring a few methods, without worrying as much about whether I did it right. I want to avoid the cross-cutting, double-blind mentality of the middleware pattern promoted by Rack.&lt;/p&gt;

&lt;h3 id='what_next'&gt;What next?&lt;/h3&gt;

&lt;p&gt;Like Webmachine has done for the server side, I think we can also do for the client side and for intermediaries (which act as both clients and servers). We can encapsulate the client side of HTTP into an FSM and expose its decisions in a clean way to applications. We can build client and server-side libraries that make working with Hypermedia APIs simpler (Nick&amp;#8217;s &lt;a href='https://github.com/apotonick/roar'&gt;Roar&lt;/a&gt; project is a good start).&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <author><name>Sean Cribbs</name></author>
      <published>2011-11-07T18:41:35Z</published>
      <title>MongoDB and Riak, In Context (and an apology)</title>
      <link rel="alternate" type="text/html" 
        href="http://seancribbs.com/tech/2011/11/07/mongodb-and-riak-in-context-and-an-apology/" />
      <id>http://seancribbs.com/tech/2011/11/07/mongodb-and-riak-in-context-and-an-apology/</id>
      <content type="html">&lt;p&gt;There has been quite a bit of &lt;a href='http://news.ycombinator.com/item?id=3207203'&gt;furor&lt;/a&gt; and &lt;a href='http://blog.schmichael.com/2011/11/05/failing-with-mongodb/'&gt;excitement&lt;/a&gt; on the Internet this week regarding some very public criticisms (and defenses) of MongoDB and its creators, &lt;a href='http://10gen.com'&gt;10gen&lt;/a&gt;. Unfortunately, a &lt;a href='http://luigimontanez.com/2011/mongodb-2.0-should-have-been-1.0/'&gt;ghost from my recent past also resurfaced&lt;/a&gt; as a result. Let me begin by apologizing to 10gen and its engineers for &lt;a href='https://twitter.com/#!/sintaxi/status/65550206825005057'&gt;what I said at JSConf&lt;/a&gt;, and then I will reframe my comments in a more constructive form.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Mea culpa&lt;/em&gt;. It&amp;#8217;s way too easy in our industry to set up and knock down strawmen, as I did, than to convey messages of objective and constructive criticism. It&amp;#8217;s also too easy, when you are passionate about what you believe in, to ignore the feelings and efforts of others, which I did. I have great respect for the engineers I have met from 10gen, Mathias Stern and Kyle Banker. They are friendly, approachable, helpful and fun to socialize with at conferences. Thanks for being stand-up guys.&lt;/p&gt;

&lt;p&gt;Also, whether we like it or not, these kinds of public embarrassments have rippling effects across the whole NoSQL ecosystem. While Basho has tried to distance itself from other players in the NoSQL field, we cannot deny our origins, and the ecosystem as a &amp;#8220;thing&amp;#8221; is only about 3 years old. Are developers, technical managers and CTOs more wary of new database technologies as a result of these embarrassments? Probably. Should we continue to work hard to develop and promote alternative data-storage solutions? Absolutely.&lt;/p&gt;

&lt;h2 id='making_it_constructive'&gt;Making it constructive&lt;/h2&gt;

&lt;p&gt;For better or worse, many people consider MongoDB and Riak to be competitors. In reality, there are very few similarities between the products. &lt;em&gt;Then why are they in competition?&lt;/em&gt; I personally believe this is because we have largely targeted our products at the same group of developers, those who work on web applications. So let&amp;#8217;s take a moment and clarify the primary differences &amp;#8212; both for understanding the technologies themselves and for unmuddying the current hoopla.&lt;/p&gt;

&lt;p&gt;If I were asked why someone would use MongoDB, there are two clear reasons in my mind:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;MongoDB is &lt;em&gt;fast&lt;/em&gt;. Say what you will about its durability (the context of my comment from JSConf) and the global write-lock (a consequence of its design, unfortunately), both writes and reads tend to be of low latency. Why? They are mostly in memory (via mmap).&lt;/li&gt;

&lt;li&gt;MongoDB has very friendly APIs for developers. This is its biggest strength in my mind. Despite other things you would want to address before going to production, developers love to think of their data as lightly-structured documents. &lt;em&gt;It just makes sense&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In contrast, Riak&amp;#8217;s strengths appeal more to operations folk, and developers who are cognizant or experienced in production operations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Riak is distributed and replicated &lt;em&gt;at its core&lt;/em&gt;. There are no special nodes or services to run to scale out, every node you start and join acts equally among the cluster.&lt;/li&gt;

&lt;li&gt;Riak has a strong focus on availability and durability in the face of failure. It will gladly sacrifice raw speed and consistency for the sake of staying available to your write load and making sure your writes get to disk.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These differences are fundamental design decisions and have associated trade-offs. Because MongoDB&amp;#8217;s design focus is to be a fast single-system database, other elements of its scale-out story are necessarily more complex &amp;#8212; sharding, replica sets, etc. Because Riak&amp;#8217;s focus is on distributed fault-tolerance and reliability, it necessarily sacrifices raw single-system performance. That&amp;#8217;s not to say that MongoDB can&amp;#8217;t scale out to large clusters well, or that Riak performs poorly in production, it is simply a recognition of the sacrifices necessary when designing a database system that addresses specific needs.&lt;/p&gt;

&lt;p&gt;Could Urban Airship have used Riak instead of MongoDB for their bounded, in-memory dataset? Maybe. Would it have worked better for them than MongoDB? That is really difficult to tell.&lt;/p&gt;

&lt;h1 id='bringing_it_back_around'&gt;Bringing it back around&lt;/h1&gt;

&lt;p&gt;Now, if I&amp;#8217;m so buddy-buddy with the 10gen guys, why did I say such an inflammatory thing in the first place? At Basho, we spend a decent amount of time evaluating and comparing other technologies so that we can understand where we stand in the market, to learn from others&amp;#8217; perspectives, and to address the concerns and demands of potential customers. Naturally, this means we have examined MongoDB closely. MongoDB&amp;#8217;s visibility, popularity, and developer-friendliness are things to be respected, even if we criticize the engineering decisions made by 10gen.&lt;/p&gt;

&lt;p&gt;Shortly before JSConf, I had personally spent some time finding out ways to demonstrate that MongoDB will lose writes in the face of failure, to be used in a competitive comparison. Let&amp;#8217;s just say that I was successful in doing so, despite recent improvements that 10gen has made. Unfortunately, I am not at liberty to share the results, nor do I think it would be constructive to this discussion. I&amp;#8217;m sure 10gen has its own collection of competitive comparisons that are designed to shed a positive light on their product in contrast to Riak, it&amp;#8217;s just how business works.&lt;/p&gt;

&lt;p&gt;We also both know our system&amp;#8217;s weaknesses and are working hard to fix them. 10gen&amp;#8217;s most recent releases have demonstrated this fact, as I believe Basho&amp;#8217;s recent releases have as well. (Have you tried out Riak 1.0? It&amp;#8217;s awesome.)&lt;/p&gt;

&lt;h1 id='so_what_now'&gt;So what now?&lt;/h1&gt;

&lt;p&gt;The honeymoon phase of NoSQL is over. Will 10gen make the hard decisions it needs to make MongoDB is easier to scale out and have greater durability, while maintain its reputation for snappy performance? I believe they will. Will Basho improve Riak&amp;#8217;s developer-friendliness and raw performance, while maintaining its reputation for simplicity and reliability in operations? I have no doubt.&lt;/p&gt;

&lt;p&gt;So instead of gloating over each others&amp;#8217; failures, let&amp;#8217;s toast to the challenges and all become stronger, more proficient, and more successful as a result.&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <author><name>Sean Cribbs</name></author>
      <published>2011-07-14T15:21:24Z</published>
      <title>Ripple Hackathon - Day 3</title>
      <link rel="alternate" type="text/html" 
        href="http://seancribbs.com/tech/2011/07/14/ripple-hackathon---day-3/" />
      <id>http://seancribbs.com/tech/2011/07/14/ripple-hackathon---day-3/</id>
      <content type="html">&lt;p&gt;&lt;em&gt;I started writing this last night, but just got time to publish it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Ripple Hackathon has finished! Today felt even more on-focus than yesterday, but also less frantic/stressed. We were in &amp;#8220;the zone&amp;#8221; for sure. Here&amp;#8217;s what we accomplished today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://twitter.com/duffomelia'&gt;Duff&lt;/a&gt; finished off the &amp;#8220;stored key&amp;#8221; associations, including incorporating conflict resolution on them! (I&amp;#8217;ll be writing up a discussion of the new conflict resolution API later.) He also fixed a small inconsistency in an internal API around associations.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://twitter.com/ntalbott'&gt;Nathaniel&lt;/a&gt; teased apart some specs that were invoking &lt;code&gt;save&lt;/code&gt; or &lt;code&gt;create&lt;/code&gt; on Document models but weren&amp;#8217;t in the integration suite, and he also lent me a lot of help on improving the build on &lt;a href='http://travis-ci.org/seancribbs/ripple'&gt;Travis&lt;/a&gt;.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://twitter.com/myronmarston'&gt;Myron&lt;/a&gt; implemented an awesome decoupled serialization API for &lt;code&gt;Riak::RObject&lt;/code&gt;. You can now register your own serializers for Ruby objects that you assign to the &lt;code&gt;data&lt;/code&gt; on a &lt;code&gt;RObject&lt;/code&gt;. So if you want to implement a custom serialization routine for &lt;code&gt;application/x-my-content-type&lt;/code&gt;, you can do it now.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://twitter.com/aphyr'&gt;Kyle&lt;/a&gt; continued work on refactoring the &lt;code&gt;Riak::Client&lt;/code&gt; code so that you can specify multiple hosts among which to multiplex requests at runtime. This will include configurable load-balancing strategies (starting with a default round-robin strategy).&lt;/li&gt;

&lt;li&gt;I reviewed a number of works-in-progress from the other developers but spent most of my time bringing our Travis build toward green. There are still some outstanding runtime/build environment/worker-related issues on Travis, but in the last few builds we&amp;#8217;ve had at least one Ruby version passing in the build.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='retrospective'&gt;Retrospective&lt;/h3&gt;

&lt;p&gt;This was a phenomenal week; I can tell because we kept a kanban on one of the whiteboards and the list in the &amp;#8220;Done&amp;#8221; column grew quite long in the three days (or you can just look at the &lt;a href='https://github.com/seancribbs/ripple/compare/66bf4f7b2d9e1bbeb55e...59cf2624524a87ce45c4'&gt;commit list and changes&lt;/a&gt;). More than just the things completed, I believe we developed a rapport and understanding that can only be done in-person. We also have a clearer way forward, and some momentum behind key features that have been waiting to be started.&lt;/p&gt;

&lt;p&gt;Thanks to all the committers who attended, and a very special thanks to the people at Basho who helped make this happen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://twitter.com/pharkmillups'&gt;Mark&lt;/a&gt; wrote the proposal and finances for the event, handled ordering lunch each day, and took notes and pictures of the event.&lt;/li&gt;

&lt;li&gt;Maureen, our office manager, handled booking hotels and other necessary logistics on very short notice.&lt;/li&gt;

&lt;li&gt;Marisa, our VP Finance, ran the numbers faster than should be humanly possible to meet accelerated timeframe.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://twitter.com/hornbeck'&gt;John&lt;/a&gt; and &lt;a href='http://twitter.com/jpease'&gt;Justin&lt;/a&gt; let me take 3 days off the normal schedule to come to San Francisco and run this.&lt;/li&gt;

&lt;li&gt;&lt;a href='http://twitter.com/antonyfalco'&gt;Tony&lt;/a&gt; made everyone feel welcome and arranged an awesome dinner on Tuesday.&lt;/li&gt;
&lt;/ul&gt;</content>
    </entry>
  
    <entry>
      <author><name>Sean Cribbs</name></author>
      <published>2011-07-13T05:39:41Z</published>
      <title>Ripple Hackathon - Day 2</title>
      <link rel="alternate" type="text/html" 
        href="http://seancribbs.com/tech/2011/07/13/ripple-hackathon---day-2/" />
      <id>http://seancribbs.com/tech/2011/07/13/ripple-hackathon---day-2/</id>
      <content type="html">&lt;p&gt;It&amp;#8217;s the end of day 2 of the &lt;a href='http://blog.basho.com/2011/07/07/Ripple-Hackathon-Happening-Next-Week-at-Basho-West/'&gt;Ripple Hackathon&lt;/a&gt;. Today was shaped a lot differently than &lt;a href='/tech/2011/07/12/ripple-hackathon---day-1/'&gt;day 1&lt;/a&gt; &amp;#8212; we did a lot more heads-down hacking and a lot less discussion and planning. Luckily, this means there were a lot of bugs fixed and features added.&lt;/p&gt;

&lt;h3 id='todays_progress'&gt;Today&amp;#8217;s progress&lt;/h3&gt;

&lt;p&gt;&lt;a href='http://twitter.com/myronmarston'&gt;Myron&lt;/a&gt; hacked through a lot of smaller issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Undefined (&amp;#8220;phantom&amp;#8221; or &amp;#8220;ghost&amp;#8221;) attributes are now better accessible and saved along with the &lt;code&gt;Ripple::Document&lt;/code&gt; instance. This might occur if you&amp;#8217;ve removed attributes from the document class that still exist inside the Riak object and you want to still get to them.&lt;/li&gt;

&lt;li&gt;You can now use the &lt;code&gt;guard&lt;/code&gt; tool to automatically run the specs in &lt;code&gt;riak-client&lt;/code&gt; or &lt;code&gt;ripple&lt;/code&gt;. It works much better than &lt;code&gt;autotest&lt;/code&gt; so we&amp;#8217;re pretty happy with it.&lt;/li&gt;

&lt;li&gt;There was an error stemming from &lt;code&gt;beefcake&lt;/code&gt; that exists on the latest release version but not an earlier version. It was locked to the proper version until we can resolve the issue in the &lt;code&gt;beefcake&lt;/code&gt; library itself.&lt;/li&gt;

&lt;li&gt;There were a few incompatibilities with Ruby 1.8.7 that were resolved, specifically in the way &lt;code&gt;super&lt;/code&gt; was called, and neither &lt;code&gt;singleton_method&lt;/code&gt; nor &lt;code&gt;Symbol#intern&lt;/code&gt; exist in 1.8.&lt;/li&gt;

&lt;li&gt;Spec files now &lt;code&gt;require &amp;#39;spec_helper&amp;#39;&lt;/code&gt; instead of using a relative path to the &lt;code&gt;spec_helper&lt;/code&gt; or a call to &lt;code&gt;File.expand_path&lt;/code&gt; to get an absolute path. We didn&amp;#8217;t need to have the relative requires because RSpec puts the &lt;code&gt;spec&lt;/code&gt; directory on the load path automatically.&lt;/li&gt;

&lt;li&gt;There&amp;#8217;s now a rake task that will clean trailing whitespace from all Ruby source files.&lt;/li&gt;

&lt;li&gt;There was an incompatibility with the way &lt;code&gt;Set&lt;/code&gt; instances were encoded to JSON when called from inside ActiveSupport.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href='http://twitter.com/ntalbott'&gt;Nathaniel&lt;/a&gt; continued working on associations where the target is found using Riak Search. In the course of his investigation, we discovered &lt;a href='https://issues.basho.com/show_bug.cgi?id=867'&gt;bug #867&lt;/a&gt;, namely that sorting is applied at the wrong time. This put a halt on moving forward with the pattern.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://twitter.com/duffomelia'&gt;Duff&lt;/a&gt; made headway on the &amp;#8220;many&amp;#8221; association of a similar type to the &amp;#8220;one&amp;#8221; using a stored key that was completed yesterday.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://twitter.com/aphyr'&gt;Kyle&lt;/a&gt; added some awesome conflict resolution logic to Risky and started on a refactoring of the &lt;code&gt;Riak::Client&lt;/code&gt; class to support multiple hosts.&lt;/p&gt;

&lt;p&gt;I completed some logic for encapsulating the retrying of failed requests automatically and helped Myron with some of the JSON issues. I also discussed with Kyle the plan for splitting the host configuration from the &lt;code&gt;Client&lt;/code&gt; object, and how we might implement various strategies for deciding how to multiplex and failover connections.&lt;/p&gt;

&lt;h3 id='the_larger_picture'&gt;The larger picture&lt;/h3&gt;

&lt;p&gt;The items we worked on today contribute toward two of the major goals for Ripple 1.0, stability and usability. Naturally, fixing existing bugs is important work, but we also want to improve the internal semantics of the client so it is more resilient to temporary failures and doesn&amp;#8217;t hammer a single node with all of its requests. We want to make the Document modeling have stronger and more diverse patterns so that you can express relationships that have higher cardinalities and less surprising results in production. I believe we made headway on those goals today, and tomorrow has lots of promise as well.&lt;/p&gt;</content>
    </entry>
  
    <entry>
      <author><name>Sean Cribbs</name></author>
      <published>2011-07-12T05:47:27Z</published>
      <title>Ripple Hackathon - Day 1</title>
      <link rel="alternate" type="text/html" 
        href="http://seancribbs.com/tech/2011/07/12/ripple-hackathon---day-1/" />
      <id>http://seancribbs.com/tech/2011/07/12/ripple-hackathon---day-1/</id>
      <content type="html">&lt;p&gt;So you may have heard about &lt;a href='http://blog.basho.com/2011/07/07/Ripple-Hackathon-Happening-Next-Week-at-Basho-West/'&gt;this event&lt;/a&gt; going on around Ripple this week. Basically, we have committers and interested parties gathering in the offices of Basho&amp;#8217;s SF office to hack on Ripple and move it toward 1.0. Today was the first day of the hackathon/sprint/thing. Here&amp;#8217;s a quick rundown on what happened:&lt;/p&gt;

&lt;h3 id='planning__priorities'&gt;Planning &amp;amp; Priorities&lt;/h3&gt;

&lt;p&gt;Because our committers are volunteers and are taking time out of their regular work to be here and to contribute, I wanted to make it worth their while &amp;#8211; to let them work on what would make the most impact for them. So we started with a discussion that consumed most of the morning, dropping our personal priorities into either the &amp;#8220;Gripes&amp;#8221; (actual problems encountered) or &amp;#8220;Wants&amp;#8221; (desired features that would make things easier) columns. &lt;a href='http://twitter.com/pharkmillups'&gt;Mark&lt;/a&gt; took a picture of this discussion in-progress:&lt;/p&gt;
&lt;a href='http://twitpic.com/5oo780' title='- @seancribbs and the ripple committers plotting 1.0 at the h... on Twitpic'&gt;&lt;img alt='- @seancribbs and the ripple committers plotting 1.0 at the h... on Twitpic' src='http://twitpic.com/show/full/5oo780.jpg' /&gt;&lt;/a&gt;
&lt;p&gt;Some of these were things that can be directly addressed by the library, some will need to be done in Riak itself. The list, roughly as it went up on the board, is below:&lt;/p&gt;

&lt;h4 id='wants'&gt;Wants&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Count things (e.g. keys in bucket)&lt;/li&gt;

&lt;li&gt;Indexes (Risky does this)&lt;/li&gt;

&lt;li&gt;Separate Repos for subprojects&lt;/li&gt;

&lt;li&gt;Migrations framework&lt;/li&gt;

&lt;li&gt;Rake tasks - db:*&lt;/li&gt;

&lt;li&gt;Riak as a gem (node generation, install)&lt;/li&gt;

&lt;li&gt;Instrumentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id='gripes'&gt;Gripes&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&amp;#8220;Many&amp;#8221; should be &amp;#8220;few&amp;#8221; (too many links)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Principle of Least Surprise&lt;/li&gt;

&lt;li&gt;double-storage (backlinks)&lt;/li&gt;

&lt;li&gt;Assigning inverses&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;list-keys (list a small bucket should not be expensive) * key-filters suck too&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Connection resiliency&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retries&lt;/li&gt;

&lt;li&gt;PBC problems&lt;/li&gt;

&lt;li&gt;multiple hosts&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Associations&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;embedded docs by key&lt;/li&gt;

&lt;li&gt;module scope for class names&lt;/li&gt;

&lt;li&gt;SBI is problematic&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;JSON problems&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Test Server&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We all then took some things that we wanted to work on and sat down to work on them. I also fielded a lot of questions about certain aspects of the things others were working on.&lt;/p&gt;

&lt;h3 id='wrapup__demos'&gt;Wrap-up &amp;amp; Demos&lt;/h3&gt;

&lt;p&gt;One thing I wanted to do with each day was to prevent it from fizzling out, so we all discussed one thing we had accomplished (or decided on) and talked about it or showed off code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href='http://twitter.com/ntalbott'&gt;Nathaniel&lt;/a&gt; and &lt;a href='http://twitter.com/duffomelia'&gt;Duff&lt;/a&gt; worked on a new kind of association for documents where the key of the other document(s) is stored in the body rather than with links (in a header). This starts to address the first bullet point under the &amp;#8220;Gripes&amp;#8221; above (&lt;a href='https://github.com/seancribbs/ripple/issues/136'&gt;aka issue #136&lt;/a&gt;) has a neat related feature - the &amp;#8220;many&amp;#8221; side can look up related objects using Riak Search. Their work-in-progress is on the &lt;a href='https://github.com/seancribbs/ripple/tree/stored_key'&gt;&amp;#8220;stored_key&amp;#8221; branch&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;a href='http://twitter.com/myronmarston'&gt;Myron&lt;/a&gt; worked tirelessly with the guys from &lt;a href='http://travis-ci.org'&gt;travis-ci&lt;/a&gt; to get a continuous integration server running. This involved getting Riak 0.14.2 installed on their worker boxes and then figuring out the idiosyncracies of why our tests fail! All in all, an awesome effort that is &lt;a href='http://travis-ci.org/#!/seancribbs/ripple'&gt;already bearing fruit&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;a href='http://twitter.com/aphyr'&gt;Kyle&lt;/a&gt; discussed lots of strategies for both teasing out HTTP response validation logic from the individual client library adapters, as well has how to do request retries efficiently. The syntax we&amp;#8217;re going to go with will be a simple block that wraps the lower-level request invocation so we implement the retry logic separately. This should land early tomorrown now that we have a solid plan.&lt;/p&gt;

&lt;p&gt;Kyle also created an interesting conflict resolution DSL for &lt;a href='http://github.com/aphyr/risky'&gt;Risky&lt;/a&gt; which encapsulates various resolution strategies at a fine granularity (at the property level, actually). We discussed borrowing that syntax to build on Myron&amp;#8217;s existing conflict-resolution code.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was a very exhilirating day (if a bit distracted at times), and I trust tomorrow will be really productive as well.&lt;/p&gt;

&lt;h3 id='come_on_by'&gt;Come on by&lt;/h3&gt;

&lt;p&gt;As the original announcement mentions, if you&amp;#8217;re in the San Francisco Bay area and want to talk about Ripple, Riak, or contribute to the library, feel free to drop by the Basho office (929 Market, Suite 500) anytime during business hours tomorrow or Wednesday. We also have formal &amp;#8220;Riak Office Hours&amp;#8221; on Wednesday too, if your questions are more general.&lt;/p&gt;</content>
    </entry>
  
</feed>

