Aaron Blohowiak http://aaronblohowiak.com Stochastik, Redis, Node.js, JRuby, Ruby on Rails posterous.com Fri, 24 Feb 2012 14:50:00 -0800 Stochastik Drum Machine for iPad Now Available! http://aaronblohowiak.com/stochastik-drum-machine-for-ipad-now-availabl http://aaronblohowiak.com/stochastik-drum-machine-for-ipad-now-availabl

Woot!  After 6 days, Apple gave me the nod! http://itunes.apple.com/us/app/stochastik-drum-machine/id504084052?mt=8

http://stochastik.xitive.com

http://youtube.com/XitiveInc

So far, the critics like it =D

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Tue, 21 Feb 2012 00:21:00 -0800 Slides for iOS music apps meetup http://aaronblohowiak.com/slides-for-ios-music-apps-meetup http://aaronblohowiak.com/slides-for-ios-music-apps-meetup

Just in case you came here looking for the slides, they are located here: http://bit.ly/apb-slides

The site for my app is http://stochastik.xitive.com and the youtube videos are up at http://youtube.com/xitiveinc 

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Thu, 16 Feb 2012 10:34:00 -0800 Principle of Least Surprise, Bathroom Edition http://aaronblohowiak.com/a-reminder-about-principle-of-least-surprise http://aaronblohowiak.com/a-reminder-about-principle-of-least-surprise

In the office building of a client the bathrooms are single occupancy and each has a lock.  That's not surprising.  When you enter the bathroom and push in the button on the handle to lock the door, the door is locked.  Still sane.  However, whenever the door closes, it unlocks!  So, if you enter the bathroom and lock the door behind you, it will unlock itself when it finishes closing.

The only way to have a locked door is to wait until the door is fully closed before pushing in the button.  The only affordance that the door has unlocked is a barely-audible "click", and there is nothing special about this door or locking mechanism that will tell you it is going to unlock automatically -- it looks exactly like thousands of other doors with push-button locks.

The defense of this design is that you don't want people to be locked out of the bathroom, and this design prevents that from happening.  However, which is worse:  unlocking the bathroom while someone is inside and thinks it is locked, or risking the possibility that someone could lock themselves out of the bathroom?

If you chose "someone locking themselves out of the bathroom", then you should not be in charge of designing anything, ever.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Mon, 13 Feb 2012 22:46:00 -0800 Implementing Korg WIST in an iOS Music App http://aaronblohowiak.com/implementing-korg-wist-in-an-ios-music-app http://aaronblohowiak.com/implementing-korg-wist-in-an-ios-music-app

This is for the lawyers: WIST is a trademark and software of KORG INC.  All other trademarks are property of their respective owners.  I am not an alien invader.

This post details my experiences implementing WIST for my amazing ipad drum machine, which will hopefully be out soon (one more feature...) I am going to refer to WIST as wist from here on out, apologies in advance.

What is wist?

From a user's perspective, wist is a way to get two iOS music apps playing in sync.

From a developer's perspective, wist is an iOS library you can use get your app playing in sync with other apps and brag about on your features list.  It is BSD (3-clause) licensed and available for download here: http://code.google.com/p/korg-wist-sdk/

Architecturally, wist is 3 things:

  1. An abstraction over GameCenter for making BlueTooth connections and negotiating the latency between them
  2. A User Interface
  3. A source and destination for start and stop events

Thankfully, you don't have to worry about numbers 1 and 2, Korg has taken care of things for you. For number 3, You just tell the library when you are going to start and stop if you are the master and implement the callbacks for when you are the slave.

How to add WIST to your iOS Music App

  1. Add the code to your project
  2. Instantiate the wist object
  3. Delegate and Control
  4. Establish a connection to another device

1. Adding the code to your project

Get the code ( http://code.google.com/p/korg-wist-sdk/ ), extract it and copy the files KorgWirelessSyncStart.h and KorgWirelessSyncStart.m to your project (Add Files...)

If you are using ARC, you will get a bunch of errors. =/ To rememdy, go to "Build Phases" and where it says "Compile Sources (37 Items)" find the KorgWirelessSyncStart.m in the list and double click the area to the right, to add a compiler flag.  Use the flags "-fno-objc-arc -w", without the quotes.  This should compile just fine.

2. Instantiating the wist object

You're going to need to get a handle to the wist object whenever you start or stop your sequencer, and it will need to have your sequencer (or a proxy) as a delegate.  import the header file and alloc/init a new KorgWirelessSyncStart object, and keep a reference to it handy.  Add your class as its delegate.  For that to work, you'll need to implement the KorgWirelessSyncStartDelegate protocol...

3. Delegate and Control

The trickiest thing about wist is getting your sequencer to start at the right time.  You don't start it as soon as you get the callback nor as soon as you tell wist to notify the slave.  It is a two step process: first, notify wist of your intentions and then go ahead and follow through.

As a slave, the wist object calls:

- (void)wistStartCommandReceived:(uint64_t)hostTime withTempo:(float)tempo

tempo is the bpm as a float, which is pretty straightforward -- set this as the current tempo for your sequencer.  hostTime is the time your sequencer should start.  That time is in the future!  If you start immediately you will be way too early; kind of like starting to play the song when the drummer starts counting off instead of when the drummer starts playing.

In your non-audio code, you can get the current time using:

#import <mach/mach_time.h>...mach_absolute_time();

And from in your audio callback, you can get the current time using:

 UInt64 nowTime = inTimeStamp->mHostTime;

So, you get the wistStartCommandReceived and then you start playing once the current time is the same as the requested hostTime.  Since I am using an extremely small audio buffer (256 samples,) I cheated and just check to see if the current time is greater than the hostTime and if so, start playing immediately.  I was planning on calculating the latency and having a sample-precise start time, but it was extremely tight sync with just this simple technique so I didn't bother.

As a slave, the other method that wist calls is to let you know that a stop command was received.  It is pretty straightforward; you can go ahead and just stop immediately whenever you get that.

Things are slightly more tricky as a master.

When a user goes to hit the play button, you check (wist_.isConnected && wist_.isMaster) to see if you are connected and master, then you grab the current time as above (mach_absolute_time()) and call sendStartCommand with the current time.  You also delay your own sequencer until the time returned by estimatedLocalHostTime, which will be a time in the future.

So, just to be clear, you always delay your sequencer start until the time wist tells you.

All that's left now is establishing the connection, and everything should "just work".

4. Establish a connection to another device

call searchPeer and wist will create a new view that mimics an alert box, blocking out the rest of the UI while trying to negotiate a connection.  When the connection is established or the user hits cancel, the UI goes away.  Everything is handled for you.  When the connection drops, a dialogue will tell the user that happened, automatically.

5. Buy Stochastik!

That's all I have for now.  I hope you liked this overview and tutorial.  My app ( http://stochastik.xitive.com ) should be in the app store soon.  In the meantime, you can follow me at @aaronblohowiak or @xitiveinc on Twitter.

 

I have some contract availability starting in may for iOS, RoR or Node.js work.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Fri, 11 Nov 2011 10:58:00 -0800 Nginx, Passenger and Rails -- a high-level overview http://aaronblohowiak.com/nginx-passenger-and-rails-a-high-level-overvi http://aaronblohowiak.com/nginx-passenger-and-rails-a-high-level-overvi

One of my friends is somewhat new to Rails, and certainly new to rails deployment.  He was a bit unclear about what role the different parts of the rails deployment stack (Nginx, passenger and rails)  were in serving the request, so I wrote up the following and figured it might help other netizens, soI posted it here.  Please drop me a line or leave a comment if something is unclear.

---

Sometimes, we use the terms "web server" or "application server" interchangeably, but for the purposes of this email, we mean distinctly different things.

NGINX or Apache are web/http servers -- that is, they bind to ports and accept incoming http requests from clients.  They are the "front line"  when it comes to client machines talking with your server (unless you have a load balancer or caching proxy, like haproxy or Varnish, but that is a discussion for another time.)

So, they accept the incoming connection from the user's computer and then they decide how to "handle" the request.  With NGINX or Apache, you can do things like having different "Virtual Hosts", which is where you can set up a different strategy for different requests depending on things like the domain being requested, certain cookies or even if the url matches a certain pattern.  Additionally, since NGINX or Apache sit at the front of the connection between the client and the server, it is common to handle things like GZIP encoding here (so your pages are compressed for browsers that support it.)

So: the job of the HTTP server is to handle lots of connections and figure out what "handler" to use.  Most HTTP servers include a default filesystem handler that is able to serve static assets off the disk (images, css files, et cetera.)

Because the HTTP server handles raw client connections and is available to the internet, it is a big "attack surface" for malicious code, so it should run with very low permissions and do as little as possible.  Even though you use root to start apache, it will change its user to "nobody" once it has opened the ports so hackers can't pwn your box even if they can crack apache remotely.  

So, if your HTTP server is nice and small, how do you connect this to your web app's code?  Well, that is where an application server comes in.  Passenger is an application server (similar to PHP-FPM,)  and its job is to connect to an http server and handle requests.  The http server says to the application server "here is a bunch of details about the request, like the headers and the body, give me the response" and the application server gives it the response.

Passenger handles the connection between the HTTP server and your application code.  When nginx starts up, it starts up passenger which starts your application in a few processes.  When a request comes in, it goes to nginx, which gives it to passenger, which gives it to one of your application processes, which handles the request and then responds with the headers and html that are sent to the browser.

This http server and application server distinction can be tricky if you are talking to people whose development stacks combine them -- for instance, you can run Java apps or Node.js apps with a BUILT-IN http server.  You could do this with ruby using something like webrick, but that is very slow compared to nginx or apache.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Mon, 10 Oct 2011 14:32:00 -0700 How to Kill the process listening on a specific port http://aaronblohowiak.com/how-to-kill-the-process-listening-on-a-specif http://aaronblohowiak.com/how-to-kill-the-process-listening-on-a-specif

When developing a service-oriented architecture, we may run into a situation where we want to kill the process that is listening on a given port.

Sometimes, you can accomplish this with the wonderful pkill utility, for instance if there is only one process with that name.  Otherwise, you will have to figure out which pid represents the running service and then use that to kill the service.

It can be annoying to remember where the pidfiles are stored for each service, and sometimes you just want to use a sledghammer to whack the process.

We can easily list the processes listening on a given port with:

sudo lsof -n -P -i :22

(using sudo because lsof may only have visibility to processes owned by the current user, depending on its compile settings.)

So now, the trick is to turn the output, which looks like this:

~/bin/ #>lsof -n -P -i :1337
COMMAND     PID           USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
redis-ser 86099 aaronblohowiak    4u  IPv4 0x0e83c748      0t0  TCP *:1337 (LISTEN)

into something that we can easily kill -9. (sledgehammer!)

To do that, I just created a little bash script in my path named 'killport' and made sure to chmod +x it.

#!/usr/bin/env bash

kill -9 `lsof -n -P -i :$1 | (read; awk '{print $2}')`

To use it, you just sudo killport 1337 and it will whack whatever is listening on that port.

what is the read; awk stuff?

the (read; awk ...) will discard the first line of the lsof output and then awk will select the second field. Note that since the $2 is within single quotes, it will NOT get substituted with the second argument to our script. However, since $1 isn't in single quotes, it WILL be substituted, which is how we "pass in" the port number to lsof from the command line.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Thu, 06 Oct 2011 20:57:00 -0700 Setting up SSL, HSTS and an http -> https redirect with node. http://aaronblohowiak.com/setting-up-ssl-hsts-and-an-http-https-redirec http://aaronblohowiak.com/setting-up-ssl-hsts-and-an-http-https-redirec

Step 1: Generate your SSL key and certificate signing request:

Note: you'll have to put the domain name in as the "common name".

openssl req -new -newkey rsa:2048 -nodes -keyout example.com.key -out example.com.csr

Step 2: Get your certificate

Log into GoDaddy or your friendly neighborhood certificate provider and go through their workflow. If you go with GoDaddy, you will get a zip file to download that contains an example.com.crt and a gd_bundle.crt

Step 3: Set up your node app and HSTS

require("https").createServer(function(req, res){
     res.writeHead(200, {    'Content-Type': 'text/plain', 
     "Strict-Transport-Security": "max-age=604800"});
     res.end('Hello from SSL!\n');
   },{     
     key: fs.readFileSync('ssl/example.com.key'),
     cert: fs.readFileSync('ssl/example.com.crt'),
     ca: fs.readFileSync('ssl/gd_bundle.crt') 
   }).listen(443);

This will get your server responding to SSL requests, and will require that future requests use SSL with  HSTS and the "Strict-Transport-Security" header. Sweet.

The HSTS header in the example above is set to last for 604800 seconds, or about a week.  This means that if anyone types in a link to http://example.com, the browser will automatically change it to https://example.com *without* going to http://example.com first! Change 604800 seconds to whatever duration you feel comfortable with.

Unfortunately, we can only specify HSTS from an HTTPS site.  But how do we force SSL if someone comes to our site with plain HTTP ?

Step 4: Setting up redirect 

To set up the redirect, you just call another function to create another server listening on the default www port 80, that includes the redirection status code and 'Location' headers:

require("http").createServer(function(req, res){
     res.writeHead(301, {
       'Content-Type': 'text/plain', 
       'Location':'https://'+req.headers.host+req.url
     res.end('Redirecting to SSL\n');
  }).listen(80);

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Thu, 06 Oct 2011 00:34:00 -0700 Meta-Programming in JavaScript http://aaronblohowiak.com/meta-programming-in-javascript http://aaronblohowiak.com/meta-programming-in-javascript

tl;dr: meta-programming in javascript is just called “programming” because the methods used are familiar and used for non-meta-programming tasks, unlike ruby which requires a large set of specialized knowledge that is only used within the task of meta-programming.

 

Background:

On the node.js mailing list, it was asked “why do we not hear about meta-programming in JavaScript?”, and the answers varied from “ruby rots people’s brains” to “People in the JS community don’t care that much about being super DRY code.” to more reasoned discourse like “JavaScript is a functional language, so you don’t really need it even if you knew what it meant.”

Finally, I would be remiss if I left out this delightful quip from Marak Squires:

I use to say, “I can bend space and time with .toString() and eval()”.

I’ve come to realize that it’s generally better to not bend space and time in JavaScript.

— Marak

As is my habit, I have a slightly more nuanced approach.

 

First things first.

Many nerd-rage-fests convolve towards a petty squabble over definitions. For now, wikipedia says:

Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves) as their data

sure, good enough for me.

In practice, rubyists are used to flavors of eval, define_method and the venerable method_missing.

 

Meta-Programming in JavaScript

I submit that we don’t talk about meta-programming in javascript because we just call it “programming” in javascript.

In ruby, there are special tools (instance_eval, class_eval, .send, define_method, &etc.) that you have to learn in order to have your code dynamically define the behavior of new objects and classes. Because of this special vocabulary that is not part of the day-to-day vernacular of the rubyist, the application of these techniques are given a special consideration and status.

In JavaScript, all you need are functions and objects for the vast majority of things that require the “meta-programming” arcana in ruby.

To make things a little more concrete: In ruby, extending an object or class by attaching behavior to an identifier (and binding that behavior to the object) is a special operation, that must be handled differently depending on how the behavior is defined and the kind of object being extended. In JavaScript, you just assign a variable to a property and you’re done. Since dot notation and [] property access work just about the same, there is no special knowledge required of the javascript programmer to write code that defines behavior.

To make things a little more abstract: most meta-programming is actually an application of currying or rebinding behavior to a different context. Currying is trivial in JavaScript, rebinding is a little tricky: assign to a property of the context or use call or apply. Since the javascript programmer frequently uses call in their day-to-day work, it is not “arcana” like Module#instance_method is within ruby-land.

 

But JavaScript doesn’t have method_missing!

Unfortunately, it may be coming in future versions. However, this is a moot point because method_missing is just dynamic dispatch. This is trivially accomplished in javascript, but it requires collusion between the caller and callee.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Sat, 01 Oct 2011 10:35:00 -0700 Create a new git repo from a subdirectory http://aaronblohowiak.com/create-a-new-git-repo-from-a-subdirectory http://aaronblohowiak.com/create-a-new-git-repo-from-a-subdirectory

I started a project (repo/) with a number of subdirectories:

repo/

web/

ingester/

bulkendpoint/

doc/

...

This worked fine in the beginning, but then I wanted to be able to branch, merge and deploy just the "web" subdirectory.

It took a good 10 minutes of man pages and googling to put the pieces together, but here is what worked for me:

#copy the whole repo.
cp -r repo newrepo
cd newrepo/

#remove reference to the old remote from the new repo.
git remote rm origin

#delete everything that isn't in the repo (including stuff in the .gitignore)
# this is optional, but nice to start clean!
git clean -f -d -x .

#this does most of the magic. will re-write your history!
git filter-branch --subdirectory-filter web/ -- --all

#the contents of web/ are now in the root of newrepo/
ls

#now, let's clean up all the references to old stuff in the newrepo/.git/ folder
rm -Rf .git/refs/original
rm -Rf .git/logs/
git reflog expire --expire=now --all
git gc --aggressive --prune=now

Now all you have to do is set up your new remote and push!

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Wed, 21 Sep 2011 20:41:00 -0700 Git, OpenSSL, Node.js and npm on Slicehost and Ubuntu 10.04 http://aaronblohowiak.com/git-openssl-nodejs-and-npm-on-slicehost-and-u http://aaronblohowiak.com/git-openssl-nodejs-and-npm-on-slicehost-and-u

Copy and paste the following into your terminal:

sudo su
apt-get install -y gcc g++ git-core libssl-dev
curl -lO https://raw.github.com/isaacs/nave/master/nave.sh
chmod +x nave.sh
./nave.sh usemain 0.4.11
curl http://npmjs.org/install.sh | sh

After you authenticate with your password, go get a cup of your beverage of choice, this is going to take a while :-)

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Sat, 20 Aug 2011 17:27:00 -0700 How to save breakpoints and display expressions in ruby-debug http://aaronblohowiak.com/how-to-save-breakpoints-and-display-expressio http://aaronblohowiak.com/how-to-save-breakpoints-and-display-expressio

Use ruby-debug 0.10.3; the newer 0.10.4 has a bug that breaks this
gem install ruby-debug -v=0.10.3
Someone on the SF Ruby mailing list asked about how to save breakpoints with ruby-debug, so I made a quick video on how to do it. No editing, one take..

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Mon, 20 Jun 2011 14:40:00 -0700 Rails Maintainability Metric http://aaronblohowiak.com/rails-maintainability-metric http://aaronblohowiak.com/rails-maintainability-metric
grep -ir "eval\|method_missing\|define_method\|instance_variable_set" app lib/  | wc -l

 

A score in the double digits should give pause, the tripple digits are scary and quadruple digits? run for the hills.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Wed, 25 May 2011 13:15:00 -0700 Amazon EC2 Cost per GB of RAM http://aaronblohowiak.com/amazon-ec2-cost-per-gb-of-ram http://aaronblohowiak.com/amazon-ec2-cost-per-gb-of-ram

Working on a project for a client, I wanted to know what the most $-efficient way to keep stuff in ram on EC2-east. These boxes will only have traffic within the AZ, so there were no bandwidth costs.  I compared On-Demand prices with Reserved prices (assuming 1 year commitment for reserved.)

For High-Memory instances:
  On-Demand:
    about $21 per GB per month

  Reserved (1yr commitment):
    about  $14 per GB per month

non-high-mem instances are about 50% more expensive when looking at the cost as $ per GB.

Here's the google doc:  http://bit.ly/kK9qbj

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Sat, 14 May 2011 17:06:00 -0700 TNetstrings http://aaronblohowiak.com/tnetstrings http://aaronblohowiak.com/tnetstrings

TNetstrings (http://tnetstrings.org/) could be awesome.  Its simplicity kicks the ass of BSON (http://bsonspec.org/), another JSON-inspired serialization format. Additionally, it is *very* easy to parse.  Unfortunately, it requires a schema if you want to serialize JavaScript Numbers.  This is entirely fixable with only a very minor addition.

I propose TNetstrings adds a "." FP64 type.

Add IEEE 754 Number Type so it is isomorphic with JSON.

The most important reason to do this is because TNetstrings is currently failing in its stated objective to "allow for the same data structures as JSON". JSON only specifies 7 data types. One of those is the IEEE 754 double precision floating point Currently, TNetstrings has an "INT" type that is an ASCII-encoded integer, but it has no representation of a float.

Now, there are problems with serializing floats: they are large, and different languages may support many float types with varying precision.   At 8 bytes, it is rather large, so TNetstrings should not remove the INT type as it would make for a fast and small presentation of numbers between 0 and 9999999.  The remaining issue is then precision. The TNetstrings site says they would add a float type "if we can find the specification for that which doesn't determine accuracy." This is directly at odds with the stated goal to provide the same data structures as JSON.

Zed Shaw says 

We'd add floats if we could come with a "reliable" spec. So far all we've found it "it's a fucking %f output, deal."

The IEEE 754 double precision floating point number is very well specified and widely supported.  It is also the JS number type. TNetstrings could provide for arbitrary serialization of JSON objects if and only if it supports the humble double.

The current suggested solution is:  

Send it as a string, have the receiver know it's a float. That's all we got for now.

There are two problems with this: requiring schema, and being an incomplete standard.

Requiring Schema

Requiring that the receiver know the structure of the object ahead of time means that any *deserializer* has to be able to accept some kind of schema in order to know which strings are actually floats in disguise.  Alternatively, you could structure your code such that your application code walks the deserialized object and performs the string to float type conversion. Either way, it means that any infrastructure that would use deserialized objects has know the schema ahead of time.

In CS lingo, it means that TNetstrings is not isomorphic -- TNetstrings.deserialize(TNetstrings.serialize(object)).deepEqual(object) is false if any of your numbers have a fractional component (nonzero digits to the right of the decimal, like 1.2.)  A serialization format that is self-describing with a type system is retarded if it is inconsistently isomorphic depending on the value of the data being serialized.

Requiring a schema complicates the interface and introduces an unnecessary burden on the programmer -- the type information is available at runtime, why require it at code time?

If TNetstrings had a float type, then it would be a viable "drop in" JSON replacement with no additional work.  The difference between a drop-in replacement and a replacement that breaks unless you specify every place where a Number might be a Float is huge.  It means that framework designers and library providers could use TNetstrings instead of JSON with no additional work for their consumers.

You are going to want floats if you are tracking averages, doing anything with lat/long, or modeling speed and direction in a game.  Currently, I use JSON for IPC and for persistence.  I'd *much* rather be able to use a faster standard if there was a drop-in replacement.  However, I don't want to rework my code to include schemas if I can avoid it.

Incomplete Standard

Since TNetstrings does not specify a floating point type, it means that you also must have a standard for specifying the schema of the messages and a standard for a representation of the double type (though 8:, is the only sane one.)  Since TNetstrings doesn't standardize the number-description schema, it means that application authors must provide their own -- which reduces interoperability and code-reuse.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Thu, 21 Apr 2011 21:38:00 -0700 Using Amazon S3 and Cloudfront to host a static website. http://aaronblohowiak.com/using-amazon-s3-and-cloudfront-to-host-a-stat http://aaronblohowiak.com/using-amazon-s3-and-cloudfront-to-host-a-stat

The good

Once it is all set up, maintaining things is easy. It is also super cheap.

The bad

Configuring dns, s3 and cloudfront to all play well together was a challenge, requiring research from multiple blogs. The error messages weren’t useful.

The ugly

Amazon’s cloud management web ui lacks a key feature that makes this all work, so you have to dip to the command line.

In detail.

Here is the play-by-play of how I got a static site served on a root domain from Amazon’s CloudFront CDN.

I was complaining to my girlfriend about time zones and I got a little passionate about the subject, which she found amusing. So, instead of realizing that this was a total nerd-rage moment, I decided to take it to the next level and make a website to share my righteous fury with the world (as I am wont to do.) I had an Amazon AWS account, had heard about Amazon’s S3 / Cloudfront CNAME support and decided to give that a try instead of fiddling with nginx configs on one of my other servers. Long story short: an nginx config would have been a lot easier.

After developing the site locally, I find a good domain name that’s available — EndOfTimeZones.com. Since this isn’t going to be a subdomain, I have to figure out how to CNAME the root-level domain to Cloudfront. According to some guy on Stack Overflow and the RFC, there is a way to get a CNAME entry for a root record. Unfortunately, I couldn’t get my usual DNS host to accept the configuration without having an A record for the root record. Eventually, I found a post where someone mentioned that you can use GoDaddy’s domain parking feature to 301 your root level to your subdomain dns entry, which would be a CNAME for CloudFront. Latency much?

This seemed reasonable enough at the time, so I created an endoftimezones.com s3 bucket http://endoftimezones.com.s3.amazonaws.com/ and a cloudfront distribution http://dia2yse4ocdlb.cloudfront.net/. I then clicked on the cloudfront distribution and edited its properties to add the domains I wanted to use to the CNAME records and verified that it was a “Download” and not “Streaming” distribution (only use the latter when serving flash media files.)

Figuring out GoDaddy’s configuration is a chore. You turn on “web parking” in a different screen from the usual DNS management screen. I had to go to the domain list screen https://mya.godaddy.com/products/domains/default.aspx?ci=13029 and then click on “Manage Domain” from the box that expands. Note that if you click on “Domain Manager” on the left navigation column, that is something else entirely. q-(v.v)-p (two thumbs down.)

So now when I was at the page called “Domain Details” (which should start with “https://dcc.godaddy.com/domaindetails.aspx?domain=…”) I saw the option on the left that says “Forwarding: off” and clicked the little manage button. go ahead and enter the SUBDOMAIN you want to redirect to from the root domain here, usually www.example.com. For endoftimezones.com, I used the.endoftimezones.com because I am clever. If you click the advanced options you will want to ensure that “Update my DNS settings to support this change” is checked and that you have selected a “permanently forwarding” redirect type — this will 301. Whew. Most of the way through DNS configuration. When you hit “ok”, the lightbox will close and you’ll be back at the Domain Details page.

On the left it now said “Forwarding: On” and had a bunch of details. At the bottom of the middle column, there was a link to launch the DNS Manager (how many managers are there? reminds me of an Enterprise job I once had…) Launching that, you should see one “A” record that points to 64.202.189.170. That is GoDaddy’s server which gives the 301. Leave it alone. The next step is to clear out all of the CNAMEs that godaddy creates by default, so i just checked their boxes and then scrolled up to “delete” and then saved the zone file (the config.) Once my act of brutal destruction was done, I then created the CNAME for www.endoftimezones.com and the.endoftimezones.com.

I wish I could tell you that I made the CNAME point to cloudfront. But, I was tired and frustrated and accidently configured it to point at s3 instead. This was really frustrating. When checking the work (after the dns change propagated) I kept seeing NoSuchBucket errors for www.endoftimezones.com. This really upset me because I didn’t know what was going wrong — I double checked the permissions of the files in s3 and the distribution CNAMEs. Eventually, I checked and fixed the CNAME configuration in GoDaddy. Waiting two hours for the changes to propagate and I started seeing an AccessDenied error. Well, this was progress.

Going back into the Amazon web console, I looked at the S3 bucket properties and saw the Default Object option, set it to index.html, saved and tried again. Same issue. Then, to check the work, I went to the website url that was linked in the properties pane http://endoftimezones.com.s3-website-us-east-1.amazonaws.com/ — note that this is different from the other s3 urls for the bucket. Finally, the web site came up. Checking CloudFront, I didn’t see any DefaultObject settings, so I thought maybe there was an issue and created another distribution (thinking that maybe the s3 bucket default object had to be set up before creating the cloudfront distribution.) Anyway, that didn’t work either. Searching for answers eventually led me to the CloudFront documentation, which suggests that there is also a DefaultObject setting on the CloudFront distribution configuration! Checking their management console, there was no way to edit the DefaultObject nor to easily hack an XML configuration file right then and there. Oy.

Fortunately, open-source is the best thing ever.

The aws-cloudfront gem https://github.com/iltempo/aws-cloudfront has examples in the README for setting the default object on the cloudfront distribution. Then I had to scrounge around Amazon for my API key and secret — you go to the amazon AWS pages and then click Account; in the blue box that drops down there is a link to Security Credentials on the middle column. click that and then scroll down the page that loads. Whew. After gem installing aws-cloudfront, I was able to run cloudfront_cmd.rb ... set_default_root_object "index.html" with my security credentials. Then i checked in the browser, and nothing changed. Well, it turns out it takes several minutes for the changes to propagate through the CloudFront. In the AWS management console, you can watch the distribution’s status go from “In Progress” to “Deployed”. Note that CloudFront distributions have both a “status” and a “state”. Naming things is hard.

Checking the.endoftimezones.com and finally it was working — but there was some copy that I wanted to change. So, I changed the html file, uploaded it to s3 and then refreshed. The difference wasn’t apparent. CloudFront caches all of your content pretty heavily. I didn’t want to wait for the timeout, so I looked for a way to expire the cache in the management console. No dice. Once again, the aws-cloudfront gem came to the rescue and had a great example in its README for invalidating the cache. Running the command and waiting for the propagation and then refreshing and my changes were live. Whew!

In conclusion

At the end of the day it was a nice refresher to get back into the S3 / CloudFront way of thinking. While I use EC2 all the time, the nitty gritty details of S3 and CloudFront are easy to get wrong — especially when the management console is incomplete. I did spend more time on figuring out the DNS and Amazon’s stuff than making endoftimezones.com, but in the end it all seems pretty straightforward and there were no huge WTFs, which is always a good sign. The advantage of CloudFront is that it is cheap, can handle crazy traffic and I don’t have to worry about some disk filling up with log entries.

I will host more static sites with CloudFront especially now that I understand the whole process.

 

Update: according to @bucketexplorer, their product makes setting the Default Object for s3 and cloudfront if you don't want to use the command line:

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Thu, 21 Apr 2011 14:52:00 -0700 The End of Time Zones http://aaronblohowiak.com/the-end-of-time-zones http://aaronblohowiak.com/the-end-of-time-zones

I am officially politically active -- calling for an immediate and unqualified elimination of all time zones henceforth.  Unite people through shared experience (and make programmer's lives easier!)  It is time.. for The End of Time Zones!

http://www.endoftimezones.com/

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Tue, 22 Mar 2011 16:16:00 -0700 Red vs Green: The Musical, A Startup Odyssey http://aaronblohowiak.com/red-vs-green-the-musical-a-startup-odyssey http://aaronblohowiak.com/red-vs-green-the-musical-a-startup-odyssey

Since Spider-Man got $65M to flop on Broadway, I figure it makes sense to leak some information about Red To Green: The Musical, A Startup Odyssey.

Here are some notes from the Playbill:

  • Overture
  • Act I: Greenfields
    • To Shave A Yak
    • Ship-It (How I learned to stop worrying and love `cap deploy`)
    • Balance
  • Act II: Product/Market Fit
    • Churn, Baby, Churn
    • One More Line
    • Tomorrow (we'll fix the tests)
  • Act III: Re-Factor
    • Velocity: Running to stand still
    • Offshore? You Whore!
    • Big Bang 2
  • Act IV: Acquisition
    • Due Dilligence
    • The Offer
    • Retrospective & Refrain (Serial Entrepreneur)

    Sample Lyrics:

    "We'll all feel better, with a geo-social sweater" -- To Shave A Yak 

    "`I'd rather be successful than well-rested`, an attitude that's battle-tested..." -- Balance

    "I think my eyes are getting bleary, maybe it's from all this jQuery" -- One More Line

    "The bugs wake me up at night, I try to re-factor, but I'm losing that fight.  Just one more batch, fuck-it, I'll monkey-patch." -- Velocity: Running to stand still

    "This is our Cap Sheet?  It's more like a crap sheet!" - The Offer

    Early Reviews:

    "This is just another reminder that Angles can be Demons, too." - Jason Fried

    "Their technology is impressive, I'm just not sure how large of a market there is for this." - Fred Wilson

    "No wireless. Less songs than a Nomad. Lame." - CmdrTaco

    "Don't Dilute Me, Bro!" - Dave McClure

     

    (Our test suite takes a while to run, and this post was written while waiting for the little green dots to show up.)

     

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Sat, 29 Jan 2011 20:15:36 -0800 New Node.js package: shared-views http://aaronblohowiak.com/new-nodejs-package-shared-views http://aaronblohowiak.com/new-nodejs-package-shared-views So, you render a page and give it to the browser.  Then, you want to update parts of it as a result of changing data model.

Do you:

  1. Have your jQuery update just the relevant divs, coupling your ui update code to your template layout?
  2. Re-write your views again in a js-friendly template language, duplicating effort and leading to subtle incompatibilities?
  3. Have the server return html snippets, leading to issues down the road when you want to update multiple parts of the page as a result of the request?
  4. Just render the same template client-side, because you're using the new shared-views package?
If you want to use the sample templates on the client and the server, my new shared-views package ( https://github.com/aaronblohowiak/shared-views ) will help you to build out the infrastructure that lets you do just that.  It isn't quite "batteries-included" -- you'll have to bring your own template language -- but I have written a simple example that shows it in use with haml-js.

This is one step closer to being able to render a page for delivery to the user and then let the user's browser just talk JSON with the server from there on out, updating the page with the same templates that were used in the initial page rendering.

Let me know if you have any questions - aaron.blohowiak@gmail.com

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Fri, 28 Jan 2011 11:21:00 -0800 Thoughts on embedding JRuby http://aaronblohowiak.com/thoughts-on-embedding-jruby http://aaronblohowiak.com/thoughts-on-embedding-jruby

I covered the initial JRuby-Lift integration on the LiftJR blog.

When trying to get this running, we did a bit of research.  The blogs and wiki posts were high-level or had too many options, so we ended up figuring things out using JRuby's excellent JavaDoc.  However, a "working man's guide" to embedding JRuby would have been useful.  I hope that you find this helpful:

  1. Import the right packages (org.jruby.*, org.jruby.embed.*, org.jruby.runtime.builtin.* )
  2. Instantiate your "Scripting Container". Pass in LocalContextScope.THREADSAFE as the ScriptingContainer constructor's parameter if you want thread safety (you probably do.)
  3. Use the scriptingContainer to eval the contents of an input stream (like a file with a class definition): scriptingContainer.parse(inputStream, filename).run()
  4. Get a handle to the jruby runtime: jrubyScriptingContainer.getProvider().getRuntime() and the thread context: runtime.getCurrentContext()
  5. Use the 'runtime' for getting a class by name, creating a new symbol and other global operations. Calling runtime.fastNewSymbol("pants") from java/scala will return a handle to :pants in your ruby environment. runtime.fastGetClass("ActiveRecord::Base") would return a handle to the relevant class.
  6. You use the thread context when actually invoking methods on objects. myRubyClass.callMethod(threadContext, methodName, Array(arg1, arg2...) )
  7. The JRuby has done an awesome job with getting the java interfaces right with the JRuby objects.  However, sometimes you just want a plain old java object.  Every RubyObject has a .toJava method; use it to get back the java equivalent of your ruby structure: .toJava(classOf[Boolean])

That should be enough to get you started.  Let me know if you have any questions.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak
Wed, 19 Jan 2011 10:32:00 -0800 I'm beaming with Honor http://aaronblohowiak.com/im-beaming-with-honor http://aaronblohowiak.com/im-beaming-with-honor

Screen_shot_2011-01-19_at_10

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/1477488/mee.jpg http://posterous.com/users/5BhyI5Ga3dGV Aaron Blohowiak aaronblohowiak Aaron Blohowiak