Sanjayby Sanjay

Many young companies — especially “web 2.0″ ones — bemoan the network effect. When their userbase is small, their value to each user is limited.  This is a dangerous place to be because it appears you’ll never get pass the critical mass necessary to make your service useful.

There are some obvious ways to get past this point, the most common one being to jumpstart your user base or to focus on a user base that is already highly internally connected, or to start with a small collection of very interesting nodes.  All of these increase the value of the network to your users within the confines of Metcalfe’s law.

Here’s another thought: To avoid being beholden to the network effect, build something that is useful with for a single user, but better for a thousand users.

It sounds pithy, but we’re putting that notion into play here at LuckyCal.

LuckyCal provides immediate value by mining your own data; it does not require all of your friends to use LuckyCal in order to be immediately useful. Even if your friends aren’t using LuckyCal, as long as their addresses are in a Google Account or an Outlook contact list, LuckyCal can use them. This leads to a new concept, which we’ve termed half-duplex relationships.

Social networks define a connection as being full-duplex: you know me, I know you; we’re friends. For most individuals, their number of friends is somewhere around 200-300, the fabled Dunbar Number.

However, we all have a much larger set of people, organizations or businesses that we keep track of that aren’t “friendships” in a bilateral manner. Instead, we care about them even though they don’t know who we are. This is the “half-duplex” relationship; archetypical examples include the relationship between a salesperson and a customer or between a fan and a band.

Similarly, by looking at the set of things you might be interested in which have some sort of public calendars or events, LuckyCal can create one-sided relationships to track them. By providing LuckyCal with access to your interests, you can know when every band you care about is playing anywhere nearby.

Typically, the valuation of a social network doesn’t recognize these relationships because there has been no way to capture their potential value. In fact, half-duplex relationships could be modeled/valued based on Sarnoff’s law.

That such relationships have value is beyond dispute: Springsteen doesn’t have to know who you are for you to enjoy his music. Similarly, knowing where someone lives is information that you own—it resides in your address book—and mining it for opportunities is valuable.

By taking advantage of half-duplex relationships, you can avoid becoming hostage to the network effect where having too few friends in a the system results in too little value.

Philby Phil

OAuth 1.0a draft 3 can be found here: http://oauth.googlecode.com/svn/spec/core/1.0a/drafts/3/oauth-core-1_0a.html.

Moving from OAuth 1.0 to OAuth 1.0a is not difficult if you pay close attention to URL-encoding. I missed a subtle issue and it took many hours to track down the problem. To summarize the solution: make sure that URL escaping is symmetrical when the signature is built and when the Authorization headers are constructed. And don’t forget to use Google’s playground, http://googlecodesamples.com/oauth_playground/ to understand the process.

If your code works in OAuth 1.0 and fails in OAuth 1.0a look at your URL escaping code. This is probably the first time that a parameter is actually escaped by your code.

In OAuth 1.0, the oauth_callback parameter is a (escaped) query parameter when obtaining the access token (using the Google Authentication service at https://www.google.com/accounts/OAuthAuthorizeToken). In OAuth 1.0a, the oauth_callback parameter is included when obtaining a request token. When the request token is retrieved, the oauth_callback_confirmed parameter is set to ‘true’ to indicate that OAuth 1.0a is supported.

Another improvement in OAuth 1.0a occurs when the request token is authorized by the user. When oauth_token is retrieved after the callback URL is called, a new parameter, oauth_verifier, must also be read. oauth_verifier is needed when the request token is exchanged for an access token (oauth_token and oauth_token_secret).

Our original OAuth 1.0 code did the following

  • URL escape the values in the Authorization headers.
  • URL escape the oauth_callback query parameter when calling
    https://www.google.com/accounts/OAuthAuthorizeToken to obtain the access token.

It turns out we had a subtle bug in this code. In OAuth 1.0 we did not have any parameters that needed to be escaped. However, in OAuth 1.0a, the oauth_callback parameter is used to build the signature and included in the Authorization headers. oauth_callback is a url and must be escaped. Our code was escaping the url in the Authorization headers, but was not escaping the url when the signature was built.

To solve the problem I URL escaped the oauth_callback value when it was added to an array. This array is used to build both the oauth_signature and the Authorization headers. When I did this, instead of receiving a request token I got an error,

Bad Request [400]: signature_invalid

My mistake was to URL escape the oauth_callback parameter used to build oauth_signature, but I was double escaping the oauth_callback parameter in the Authorization header.

When I fixed this issue everything worked as advertised. We’re now running OAuth 1.0a in production!

Tags: , , ,

Sanjayby Sanjay

Recently, as part of a new project within LuckyCal, I needed the ability to kick off a lightweight task within a controller.  I thought that this’d be a pain, but RunLater came to the rescue!

As a bit of background, you can simple hand a block into run_later and it will run it in a separate thread immediately, thereby not blocking your method.  An example from its README


class AccountController < ApplicationController
  def signup
    @user = User.new(params[:user])
    if @user.save
      run_later do
        AccountMailer.deliver_signup(@user)
      end
    end
  end

Now here’s where it gets weird:

If I use curl (or wget some other commandline tool) RunLater works exactly as expected, spawning off the separate thread and allowing my controller to finish and render the page.  I see the response get rendered by the controller and immediately sent out and the HTML appear as the output of curl.  Later I see the rest of the processing finish up.  Perfect.

However, if I use an actual browser (Safari 4.x, FF 3.x, IE 7.x), the rendering of the page blocks until the processing of the run_later block finishes!  What’s odd is that the web server (Webrick, Lighttpd, Passenger) all appear to believe that they’re finished.  I event get a comforting “Completed in 88ms” message in my console.

But the actual render is blocked!

Is there something about browsers that works differently?  Are they waiting for a connection to close/drop/disconnect?  Shouldn’t they be progressive rendering anyhow?  Is Rails non-compliant here?

Any pointers would be most appreciated!