Jul 31

Keeping SSH sessions alive with Mac OS X Terminal

Tech 27 Comments »

I am a big SecureSSH fan on Windows. I prefer it to Putty (apart from when on a public machine and I can just grab Putty :).

One of the options is to send a NOOP every now and then to keep the SSH session alive.

It is frustrating to get distracted and come back to your Terminal and to see it has timed out.

Back in the day I was a screen user, but these days I can’t be bothered with some of the issues that come along with screen.

When I switched to the mac, I found the ssh session problem in Terminal.app.

I then tweaked my ssh config (~/.ssh/config or /etc/ssh/ssh_config depending on your desired scope)

ServerAliveInterval 300
ServerAliveCountMax 3

All is well again.

Jul 27

/article/111 vs. /article/my-body-wont-let-me

Tech 266 Comments »

DHH has been talking CRUD recently, and although I like some of the ideas, there is one that I disagree with.

DHH seems to prefer using ids in URLs, and uses the logic that “we learnt our lesson from composite and business keys”.

URLs are precious. Ideally they should be carefully planned. As soon as you have a popular web property that is highly trafficed and linked too, you realise this.

“Oh man I wish I could just change X”

Of course, you can change URLs, but you end up with growing code to handle the old styles. For SEO purposes you probably want to make sure you 301 perm redirect to make sure Google and co are up to speed. You don’t want any juice to be lost via duplicate content.

I really want readable URLs that have meaning. URLs are the gateway to the content. If your users can guess things based on urls then you have won (or you may have lost if your usability is so bad that the user needs to guess urls ;).

If I have visited 100 articles on a site and I want to remember one of them.

I start to type: http://site.com/article/

and at this point I get a dropdown history. If the dropdown is just lots of /article/XXXXX that will not help me at all.

If the dropdown has /article/title-kinda-thing then it does.

If you go with this scheme then you do need to do the thinking about changing URLs. In this case you may want to NOT let anyone change the slug for the article once they have published it, else you need to redirecting old ones all over again.

In general I do like the exercise of seeing how CRUD like you can make your controllers. It can be really tough to have just a few of those methods :)

Jul 25

OS X Selection: Mail.app fix

Tech 31 Comments »

I have always hated the Mac OS X selection mode that means that if you select down down down and then up it takes the top item and selects one on top instead of undoing the last down.

Thank god I can at least fix it in Mail.app

Jul 24

Ringtone by Area Code

Tech 31 Comments »

Ringtones is a large industry. Instead of assigning ringtones based on people or groups on your phone, it would be interesting to be able to assign a ring to an area code or country code.

Then if I get a buzz from a mate in London I hear James Bond music.

From a friend in Oz, “I come from a land Down Under”

If someone calls from Down South you get the Dukes of Hazzard, etc etc.

(If anyone implements this Jim Halberg gets $1 per call)

Jul 21

IntelliR IDEA and Textmate Prototype

Tech 19 Comments »

Please and Thank you.

Jul 19

Subscriber.find_all.size

Ruby, Tech 42 Comments »

“Hmm, this action is taking 45 seconds”

Subscriber.count: entire action == 1 second

Jul 19

render :partial fun

Ruby, Tech 329 Comments »

“I am not getting the output that I expected”


<%=

render :partial => "most_recent_registrations", :locals => load_most_recent_registrations
render :partial => "summary_totals", :locals => load_summary_totals
%>

Jul 19

Rails HTML Caching Fun

Ruby, Tech 42 Comments »

I often talk about how much I like clustered caching for a certain set of large scale systems (Give your DB a break).

I recently had the pleasure to add some simple caching to a Rails app. This time it didn’t make sense to add memcached and friends (some interesting work there with ActiveRecord support) because the problem was simple:

One page in a stats package that would be hit by ~4 users, a couple of times a day was very slow (30 secs) to dynamically generate. The data is NOT time sensitive.

Since this piece didn’t need to scale to thousands of concurrent users, and stale data was fine, we thought it would be enough to add some HTML caching.

One of our requirements was that we didn’t want one poor sucker to have to wait 30 secs to fill the cache. We wanted the cache to fill itself. Again, we ended up with a simple solution to this rather than some killer cache work.

Here are some steps though:

1. Rails Page Caching

At first it seemed simple to just add page caching.

All you need to do here is:

  • Add “caches_page :action1, :action2″ to your controller
  • Have some way to expire the page. You can create a Cache Sweeper, or have an action that expire_page’s things, or simply have something that nukes the html file.

Sounds great! However, all that is happening here is the caches_page will make sure that an after_filter is applied that saved the response content out to the file system. By default, a .html file is created in the public directory so apache can just slurp it right up and serve it. Very fast.

The sweeping is where you have to write some code, but it is simple to do, so you can’t totally complain (although it could actually be even simpler: I would love to see a system where you have a cache config so you put in expiration info in there and rails auto handles expiry).

The problem is that this full page caching only works if you CAN actually cache the entire page. Erm, surely that is most of the time right? Well, not really. If you have any user-specific work on the page it will not work. This could be as simple as showing a login/register area for non-logged in people, to a ‘Welcome Dion’ link to the users account if they are logged in. If you have special UI changes for admin users it will not work (e.g. add ‘Edit’ links next to content to give your admin users a simple interface).

This all means that you often can NOT use full page caching (and this was the case for us).

2. Action Caching

Another option here is to cache an action rather than the full page. The only difference is that: “unlike page caching, every request still goes through the Action Pack. The key benefit of this is that filters are run before the cache is served, which allows for authentication and other restrictions on whether someone is allowed to see the cache.”

So, it lets you still do filters (which we would need to do as we wouldn’t want the stats to be viewed by anyone), but still has the full page limitations.

3. Fragment Caching

The first two items sit on top of Fragment Caching.

Fragment caching is used for caching various blocks within templates without caching the entire action as a whole. This is useful when certain elements of an action change frequently or depend on complicated state while other parts rarely change or can be shared amongst multiple parties.

So, we could simply wrap the content that took a long time to load with:

<% cache do %>
... all of the long running pieces ...
<% end %>

And we can tweak keys via:

<% cache(:action => "list", :action_suffix => "all_topics") do %>

Now we finally have just a piece of content cached, so the full UI is still dynamic (get the logged in features) and all of the filters will of course run.

By why out of the box does this version still take a long time to load?

  • If you are testing in development, caching will not happen for you because config/environments/development.rb will probably have:
    config.action_controller.perform_caching = false
    

    You are used to thinking of this in the form of “in dev mode Rails reloads files that I have changed”. In this case it is the HTML caching too. To test, change this setting to true in dev mode, and remember to change it back later ;)

  • Where are you DOING the long running task? Just because you have a cache() wrapping the VIEW doesn’t mean that the controller isn’t running the action. If your action has @data = long_running_method that the view then uses, the caching will do nothing for you. Make sure that the action doesn’t do the long running thing, but that is kicked off from within the cache block itself. E.g. literally by calling the long_running_method, or by doing a render passing in the long running piece (which is inside the cache)

Ok, done right? Not quite. This has just created the cache file. Unless you want this to happen once and have that same version used for the rest of time you need to clean up.

We simply put something in cron to expire that fragment every X minutes (as it was simple). When working on an app that does more of this caching, then we create a cache config object that knows more about expiration and does the deed for you.

Also, remember the requirement not to screw the first user after expiry? The cron script does this in a hacky way. After it nukes the fragment it accesses the url of the page immediately to kick off a new cache page. This isn’t totally trivial as in our case the page is behind authentication and some filters that can trip the script.

To solve this we have a cookie that the process uses to get through the auth piece (security worry) and we turn off one of the filters (cookies_required) for this beast.

Conclusion

Rails has a bunch of built-in page caching mechanisms, but they aren’t THAT useful out of the box. You need to tweak and play around to get what you need, and most of the time you will NOT use the simple solutions.

For our large scale sites we still love the event-driven memcached approaches.

What have you done?

Jul 18

Another anecdote on how whitespace can be evil

Tech 2 Comments »

In the entry from a Python fan Ruby Style Adding Methods to Existing Classes in Python? you look into the comments to see the following code:

class Foo:

def __init__(self):
self.x =

Jul 17

Top cities to live? or top suburbs?

Personal 3 Comments »

CNN Money has released their Top 100 Cities to Live.

These lists always make me laugh. It seems that every place I have lived in has claimed that it has won the “top place to live in FOOBAR magazine”.

However, the lists show me the statistical view of things. It shows that it is better to live in a suburb than an actual city.

For example, I think that it is a lot nicer to live in Boulder, CO than Westminster, CO. However, the “price” amount of the equation will knock Westminster up in the rankings.

How can great cities such as NYC and San Fran not be anywhere to be seen on these lists? They may not be for everyone, but they have a lot going for them and I think I would prefer them to: Olathe, KS, West Bloomfield , MI, Richardson, TX, or Gilbert, AZ for examples (no offense to those cities).