Finagle with scala-bootstrapper

I've been fascinated by the concepts in finagle for some time, but being a scala noob, I never knew how to bootstrap a finagle project. Turns out twitter has a gem, scala-bootstrapper, that generates a simple thirft based key/value store for you. There's even a tutorial on how to extend the example project into a distributed search service.

This is a guide on setting it all up locally, it assumes you have Git, Homebrew, and OS X.

1) Install scala 2.8.1

2) Install sbt 0.7.4 (assumes you have a ~/bin in your $PATH)

3) Install scala-bootstrapper

4) Generate finagle project

5) Add a Client class

create newbird/src/main/scala/com/twitter/newbird/Client.scala with

6) Running the server

7) Playing with the client

Bonus

finagle exports a stats url you can curl:

 

 

Alfred Extension for creating Wunderlist tasks

While looking for a way to add wunderlist tasks via alfred, I came upon this: http://jdfwarrior.tumblr.com/post/13163220116/wunderlist-for-alfred

Looked cool, but I wanted to write my own that didn't depend on php.

I used lsof to figure out the location of the db, then used file to see what kind of db it was. Luckily, it was sqlite3, so I was able to poke around and figure out the sql to create a task.

Here's the alfred extenstion that ties it all together:

user=`whoami`
wunderdb="/Users/$user/Library/Wunderlist/wunderlist.db"
sqlite3 $wunderdb "insert into tasks (name, list_id) values ('{query}', 1)"

Download it here: http://dl.dropbox.com/u/42561/wunderlist-capotej.alfredextension

Render image links directly inside Adium

Last night I delightfully discovered that Adium Message Styles are just html, css, and javascript rendered inside a webview. The next natural step was to write something in it, so I wrote a Message Style that tries to render any image link directly inline the conversation (campfire style).

X

The code was written at midnight after a long day, so its not best. Basically, it's a setInterval that runs every 2.5 seconds that loops through all message elements, appending an img tag to the body of the message if an image link is detected. It also removes the processing class as to not reprocess the same messages.

Installation is simple, just download: 

http://dl.dropbox.com/u/42561/Stockholm.AdiumMessageStyle.zip

and extract into ~/Library/Adium 2.0/Message Styles (create if necessary). Then choose the TOP Stockholm theme (no idea why there are two entries), and close your chat window. It should be activated next time a chat window opens.

Y

Don't pee in the pool.

A rich man builds a pool containing only bottled water and invites a few friends over. He gathers everyone around and says, "Guys, I know it's tempting and convenient to pee in the pool, but this pool is 100% Evian, let's all try to use the bathroom next to the pool instead." So everyone listens and enjoys a urine-free, delicious pool for the rest of the day. Until, of course, one of them breaks the rule, ruining it for everyone.

That pool is your commit history and the merge commits are the pee in the pool. So please, keep your pee out of the pool and rebase instead.

Disclaimer: I don't really care if you do or do not pee in regular pools. This is all made up to illustrate a point.

My cloud experiment

Lately I've been thinking about the best way to store and backup large amounts of personal data. It irked me that I've never been able to keep a collection of photos past 2-3 years. Either it's a machine swap or a misplaced backup, something always happens. 

When the idea of storing or backing up everything offsite comes up, people usually throw out objections like "What if they lose all my stuff or go out of business?" or "I don't like the idea of my files on someone else's computers". However, based on my past performance, I concluded that any solution is better than my current one.

The ideal situation was to have my entire home directory on Dropbox. This is feasible only if you have about 50-100gbs you care about. For most people, including myself, this is not the case. So how do you reduce your total data footprint to 50gbs?

  • No more local mp3 storage. I went and uploaded my current mp3 collection (15 gbs or so) to Amazon Cloud Player. I also deleted anything rdio already had in its collection. 
  • I deleted the random assortment of movies and tv shows I've acrued over the years, since 98% of them they are already on Netflix and Hulu Plus.

  • Pictures were the last remaining swath of disk space. I wrote a script using the (awesome) smugmug api, and uploaded all my photos to smugmug.

After these changes I'm going to put my entire home directory up on Dropbox, since it will fit now. Admittedly, all these services cost money, but it's a small price to pay for never having to worry about backups or the location of your files (since they can be accessed anywhere).

Im curious as to how others have solved this problem or how Apple will solve it with their supposed "iCloud".

 

MigrationFor: Write migrations right from the command line!

As someone who mostly stays in the rails console, I’ve always hated forgetting a field, creating a migration, finding it among your other 500 migration files, then adding the one line you need to add, then running it. This is probably the most annoying part of the Rails experience. I’ve always wanted to write a better migration generator that could take a list of commands/fields and write the migration for you, since most of the time what you name a migration has all the info it needs (add_index_to_post_id). Thanks to the heavily refactored plugin/generator API in Rails 3, I was able to do just that.

Let’s take a look at how it works:

First, install it (only works for Rails 3)

rails plugin install git://github.com/capotej/migration_for.git

Then, you can create migrations like so:

rails g migration_for add_index:posts:posts_id

It would generate db/migrate/20110103182654_add_index_posts_posts_id.rb):

class AddIndexPostsPostsId < ActiveRecord::Migration

   def self.up

      add_index 'posts','posts_id'

   end

   def self.down
     #waiting for reversible migrations in rails 3.1!
   end

end

Which you can then run normally with rake db:migrate

Let’s look at a more complex example:

rails g migration_for create_table:posts add_column:posts:title:string add_column:posts:user_id:integer add_index:posts:user_id

Would generate:

class CreateTablePostsaddColumnPostsTitleStringaddColumnPostsUserIdIntegeraddIndexPostsUserId < ActiveRecord::Migration

   def self.up

      create_table 'posts'

      add_column 'posts','title','string'

      add_column 'posts','user_id','integer'

      add_index 'posts','user_id'

   end

   def self.down
     #waiting for reversible migrations in rails 3.1!
   end

end

It uses a lookup table with all the activerecord transformations and will only insert an expression into a migration if the method name is valid and it has the right number of arguments, so botched commands wont mess up the migration. Hope you enjoy it as much as I have!

Source available here: https://github.com/capotej/migration_for

What I released in 2010

Here’s a recap of what I’ve worked on and released in 2010:

Youtube Fraiche: I couldn’t find a youtube downloader that worked on github, so I wrote my own one evening https://github.com/capotej/youtube_fraiche

Uploadd and paperclip_uploadd: I wanted to upload and store images off-site (using paperclip/rails) on an server which has cheaper bandwidth rates than S3. Using rainbows, this tiny rack script has handled over a 1.5 million uploads at a peak of 10-15 uploads/sec. Also, it’s been running for about 6 months now without a single crash. Thank you Eric Wong! https://github.com/capotej/uploadd There is also a plugin for the popular paperclip gem to use uploadd as a storage backend transparently. https://github.com/capotej/paperclip_uploadd

mrskinner: Tiny javascript for making the site gutters clickable based on a fixed width layout: https://github.com/capotej/mrskinner/blob/master/mrskinner.js

existential: Completely inspired by Nick Kallen’s post on authorization, I wanted to extract that pattern into a rails plugin that I could use for all my projects. I use devise/existential for all my projects now. https://github.com/capotej/existential

has_opengraph: Easy way to participate in opengraph and draw facebook like buttons. Just annotate your models with meta data, and draw it in your view easily. https://github.com/capotej/has_opengraph

chewbacca: I kinda feel bad that I took a cool name for such a lame script. Anyway it’s a set of rake tasks that provide a hair of abstraction above scp. Useful when you have a set of files locally that map to a different set of files remotely. https://github.com/capotej/chewbacca

I already have tons of stuff in the works for 2011!

On Google Buzz

Summary: In this post I attempt to rationalize the creation of Google Buzz.

How I see it
Google Buzz is a subset of email, optimized for sharing information and discussing said information amongst a network of followers. I’m sure Google noticed that a large number of users send short messages, occasionally accompanied by a link or an attached image, to the same people over and over. I know I do; Regardless of Twitter or Facebook, Email is still my preferred medium for propagating content to my close friends. In fact, the first browser add-on I install is the “send via gmail” to automate this process. So upon seeing Google Buzz, instead of seeing it as “another social network”, I saw it as a streamlining of my current link sharing workflow.

Sharing
Sharing things on Google Buzz is pretty easy (although I’m still waiting for my chrome extension). It’s faster than sending out an email because you can create groups of those you would normally CC and you don’t have to think about a subject line.

Private Groups
I believe that this is Google Buzz’s killer feature. As our social graphs increase and intersect/overlap, the importance of segregating information increases. For instance, your Mom/Boss/Girlfriend(s) seeing pictures of you at that raunchy party the other night. This is a common problem that anyone with a Facebook/Myspace can attest to having (at least once). Not just for privacy’s sake but for the sake of your followers. I used to have every tweet posted to my Facebook but people complained that they didn’t understand 99.9% of the things I posted (programming links/info usually). And inversely if I started posting non technical/silly things to Twitter, I’ll lose the technical audience there (this is why this app rules). Google Buzz allows me to share content with just the people I want (and discuss with the people I want).

Discussion
Let’s face it, trying to have a deep discussion is next to impossible on Twitter (not that this is bad). Meanwhile, Google Buzz inherits gmail’s threaded conversation feature (one of it’s best features) which makes discussing buzzed items a breeze. Also the “Like” concept is not to be underestimated, how many times have you seen email replies with “+1” in them? Or, if a discussion you don’t care about keeps showing up on your stream you can simply Mute it. Crazy Speculation: This may be what’s coming next for Google Groups.

Pain Points
Nothing is perfect, and Google Buzz is surely is not. For one, it’s, some say, intrusive, arrival rubbed a lot of people the wrong way. You’ll find all kinds of posts on the internet about how they feel betrayed by Google for forcing a social network down their throat. Others felt that their gmail was their “work area” and didn’t want to bothered with such folly (understandably so). That’s why I feel it should’ve been deployed like this: Wave style invites and if you buzz someone that doesn’t have an invite, they just get it like a regular email with a link on the bottom to join. The early adopters will bring in those they feel will like the service and use it with them. The other point is that you can’t filter out buzzed tweets (when you tweet, Google Buzz will buzz it automatically) so you end seeing tweets twice.

Conclusion
So in conclusion, will Buzz replace Twitter for me? No. But it will definitely replace those quickie emails I fire off to the same group of people over and over. I feel like they are trying to market Google Wave to a bigger, more mainstream audience. If that’s the case, I look forward to see what else Google Buzz will bring to the table in the future.