Jan 2, 2012

One Week on Node

Just want to write down some feelings on a small nodejs project I worked on last week.

* Fast. Everything is fast (attribute to Google v8 and node guys). REPL opened in a twinkle, tests finish before I grab my teacup. No more waiting for "warm up".

* NPM. It's so good. I like the idea to install all dependencies locally in project directory. Mentally, dependencies are part of your application, it make sense for them to live together. Physically, put dependencies in project directory will solve dependency conflicts between applications naturally; besides that, it enables you to jump into deeper (library) code more easily, if you use a decent editor like vim or textmate, because all files are in one place so a simple search will find them all.

* Library boom. Maybe a requirement to success, but it goes a little wild. In some area like testing, tons of immature tools are there, no one can tell a best practice. I have to examine all these tools to find a best fit to my project. I really miss something like rails guide or ruby-toolbox.com here.

* Asynchronization is still hard. It's hard for the same reason GOTO statement is hard, or lazy evaluation is hard. It messes up my tiny little brain easily by disrupts the execution order. The weird exception backtrace only make the situation worse (however this should be fixable). The little piece of asynchronous code is like virus, it gradually infects the rest parts of your application (IO monad: ah?). The co-routine tricks/tools people used to dress asynchronous code up to synchronous code still looks awkward (and here's another area suffers the library boom problem). I will be very careful if someone propose to write an entire application in node, it would be better if I can restrict asynchronous code on a small land. I bet node is better in polyglot paradigm, e.g. node as my ajax push server, rails to power most web pages.

Node is great! Be careful with asynchronous calls!

Sep 26, 2011

Running Rails 3.1.1 on Heroku

Heroku officially supports rails 3.1.1 on their Cedar stack now, unfortunately, you may still fail on deploy. The trouble maker is the assets:precompile rake task in rails 3.1. Heroku runs 'rake assets:precompile' for you when deploy, at a time many application dependencies, e.g. database server, redis, are NOT ready, so if there's any database/redis/any-other-not-ready-dependency use in your rails initialization process, assets:precompile will fail.

The tricky thing is, even you know the underlying theory, it's hard to find the exact place caused the problem, because heroku deployment do not use '--trace' flag when running precompile task, the limited error output is almost useless; and rails initialization process walks through so many files it's stupid to check them one by one.

For example, this is the error I got today when I deploy to heroku:

rake aborted!
bad URI(is not URI?):

Can you spot the broken code with so few information? I can't ... Fortunately, we can ask rake to give detail error stack without passing it '--trace' option, by adding this line in your Rakefile:

Rake.application.options.trace = true if %w(staging production).include?(Rails.env)

Then another problem pops up, I now found the broken code, how to fix it? Since the broken code uses something that is not ready when assets:precompile task running, an easy way would be:

# in Rakefile
if %w(staging production).include? Rails.env
$heroku_deploying = true if File.basename($0) == 'rake' && ARGV.include?('assets:precompile')

# in some initializers:
# reference to UsersController will trigger operation on database
provider :identity, :fields => [:name, :email, :nickname], :on_failed_registration => UsersController.action(:new) unless $heroku_deploying

With this duct tape kind fix, you may have $heroku_deploying scattered in your code .. it's ugly but works. Let me know if you have better idea :-)

Jun 17, 2011

[ANN] Rubytest.vim 1.1.0 Released!

There're two major changes in this release:

* Remember last run: <leader>l to run last run test (thanks John Weir!)
* Default support to rspec2. You need to customize g:rubytest_cmd_spec to work with rspec 1.*

Download [1][2] and copy/overwrite to install/upgrade!

May 30, 2011

Jan 26, 2011

Angry Terminal

Last night I got the idea that using different colors in shell prompt to tell the user about the result of last command executed, e.g. red for failed execution and green for success.

It's really easy to do that in the ultimate shell, all I need is a function and a prompt using it:

function prompt_base_color() {
if [[ $? == "0" ]]; then
echo $PR_GREEN
echo "$PR_RED"

PROMPT='$PR_SET_CHARSET$PR_STITLE${(e)PR_TITLEBAR}$(prompt_base_color)%D{%H:%M} $PR_GREEN%~ $PR_RED$(git_prompt_info)$PR_NO_COLOUR'
It make your terminal look like this:

Then I realized I can go one step further to help terminal express her feeling, I always feel she is angry with me.

So I changed the function a bit, like this:

function prompt_base_color() {
if [[ $? == "0" ]]; then
echo $PR_GREEN
txt=`cat ~/.zsh/my_ass.txt`
echo "$txt\n$PR_RED"
And put the feeling in a file by `cowsay My ASS > ~/.zsh/my_ass.txt`.

Now Miss Terminal can tell me what she thinks when I do something wrong!

Nov 26, 2010

QorCMS preview

Qor is the admin tool we build for rails. It's not public released yet but already used by some of our clients. It's like the Django one but only better!

Qor Enterprise CMS Demo from Felix Sun on Vimeo.

Nov 4, 2010

Compiling Google mod_pagespeed on Archlinux

Google released its awesome apache module mod_pagespeed recently. Unfortunately only .deb/.rpm packages are provided officially. For arch user, we have to compile it by ourselves.

Based on google's howto, we need depot_tools to compile mod_pagespeed. There is an aur package depot_tools-svn, but seems not work now because arch switched to python 3.

So I downloaded depot_tools myself and put it in my ~/scripts/depot_tools.

mkdir -p ~/scripts
cd ~/scripts
svn co http://src.chromium.org/svn/trunk/tools/depot_tools

To make depot_tools work, you need to switch to python2:

sudo rm /usr/bin/python
sudo ln -s /usr/bin/python2 /usr/bin/python
sudo rm /usr/bin/python-config
sudo ln -s /usr/bin/python2-config /usr/bin/python-config

Next step we download mod_pagespeed source code use depot_tools:

mkdir ~/mod_pagespeed # any directory is fine
cd ~/mod_pagespeed
gclient config http://modpagespeed.googlecode.com/svn/trunk/src
gclient sync --force # this will download all source code

You're ready to compile now.

cd ~/mod_pagespeed/src
make BUILDTYPE=Release # BUILDTYPE defaults to 'Debug'

I got an error when I compile it on my box:

In file included from /usr/lib/gcc/x86_64-unknown-linux-gnu/4.5.1/../../../../include/c++/4.5.1/utility:71:0,
from /usr/lib/gcc/x86_64-unknown-linux-gnu/4.5.1/../../../../include/c++/4.5.1/algorithm:61,
from ./net/instaweb/util/fetcher_test.h:24,
from ./net/instaweb/util/cache_fetcher_test.h:27,
from net/instaweb/util/cache_fetcher_test.cc:19:
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_map.h:87:5: instantiated from here
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.5.1/../../../../include/c++/4.5.1/bits/stl_pair.h:77:11: error: ?std::pair<_t1,>::second? has incomplete type
./net/instaweb/util/public/cache_interface.h:28:7: error: forward declaration of ?struct net_instaweb::SharedString?

After digging a while, I made this patch to fix the error:

Index: net/instaweb/util/public/cache_interface.h
--- net/instaweb/util/public/cache_interface.h (revision 137)
+++ net/instaweb/util/public/cache_interface.h (working copy)
@@ -21,6 +21,7 @@

#include <string>
#include "net/instaweb/util/public/string_util.h"
+#include "net/instaweb/util/public/shared_string.h"

namespace net_instaweb {

ps: I also deployed mod_pagespeed to our centos staging server, the whole process is very smooth. The result is also very impressive: gzip, cache-control, inline assets, etc. etc. all suddenly work like a charm. The only problem is with extend_cache filter: it modified asset name correctly, but when brower send request to those assets, the server reponds with 404 error. I have to disable rewrite_javascript and extend_cache filter to make our sites work correctly:

ModPagespeedDisableFilters rewrite_javascript
ModPagespeedDisableFilters extend_cache