debuggable

 
Contact Us
 
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11

node.js

Posted on 24/9/09 by Felix Geisendörfer

What happens if you take an insanely fast JavaScript engine and build an asynchronous I/O library around it? You get node.js, an up and coming project that brings you bloat-free server-side JavaScript.

This enables you to write any kind of "backend" service with just a few lines of JavaScript. But don't take my word for it, here is how a "Hello World" example looks in node.js:

node.http.createServer(function (req, res) {
  setTimeout(function () {
    res.sendHeader(200, {"Content-Type": "text/plain"});
    res.sendBody("Hello World");
    res.finish();
  }, 2000);
}).listen(8000);
puts("Server running at http://127.0.0.1:8000/");

This code creates a new http server and tells it to listen on port 8000. Whenever a request comes in, the closure function passed to createServer is fired. In this example we are waiting 2 seconds before sending a "Hello World" response back to the client.

However, during those 2 seconds the server will continue to accept new connections. That gives you a very scalable hello world server. Talking about performance: Ryan (the awesome guy behind node.js) has done some initial benchmarks which show how fast of a beast we are talking about here. To me the most notable aspect is the extremely low response times you can achieve with node.js (pretty much 0-1ms).

Here is another chart from a req/sec benchmark among various server-side JS libs:

Now you may think this is all very nice and stuff, but what do you actually need it for? Well, it depends. There are a few people writing web frameworks for node.js, but at this point it would be rather adventurous to build a full blown web application on top of node. However, node has incredible potential if you want to develop chat applications, check out this one for example. We are using node.js to run the backend for transload.it which we'll share more details about in the future. One could also easily write his own key-value store in node.js - let's say you'd like to have something like Memcached but with a REST interface.

Trying out node.js requires you to have a Linux/Unix machine but it's pretty much as simple as downloading the code and running:

./configure
make
make install

The documentation is pretty excellent and there are lots of friendly people on the mailing list to help if you have any problems.

To me the most exciting thing about node.js is its incredible potential to reunite. You can have long debates about using Python, Ruby, PHP, Java, ASP or Perl for a web project, but nobody will debate that JavaScript is *the* language of the web. Now imagine the smartest people from all those communities creating code in a single language that works on your browser as well as your server ...

I'd love to hear your thoughts on node.js and any questions you might have. Just leave comment!

-- Felix Geisendörfer aka the_undefined

 

Fixing non-atomic commits in git

Posted on 15/9/09 by Felix Geisendörfer

Let's say somebody else made a commit that mixes a bug fix and a new feature together. This sucks if you only want to take the bugfix to merge it into your stable branch (using git cherry-pick).

If you were using SVN you'd be screwed now. However, if you are using git you can actually clean this mess in an elegant and transparent fashion:

git revert --no-edit 
git revert --no-edit HEAD
git reset HEAD^
git add -p # or other commands to partially stage stuff from the current tree
git commit -m "Commit A"
git add -p
git commit -m "Commit B"

Let's look at this step by step:

git revert --no-edit 

This command creates a new commit that reverts the bad commit.

git revert --no-edit HEAD

The second 'revert' creates a new commit that basically redoes the bad commit. Why? Because now you have a "clone" of the bad commit sitting cleanly on top of your HEAD, waiting for you to be messed with. This is much better than using git reset to go back to it, because you are not deleting history (which is very likely to give you merge conflicts).

git reset HEAD^

By using git revert you can now go back to the moment before the "clone" commit was created, but still have all of its changes in your tree (=local file system). This essentially takes you back in time to the moment before your evil teammate hit the commit button and gives you the ability to yell "Nooooooo! Let me tell you about atomic commits buddy".

Now you can use 'git add' or 'git add -p' to stage all your changes for the first atomic change and commit it. Repeat the process until you've split the bad commit into nice atomic pieces.

All that is left to do now is to explain to your teammate that next time he accidentally makes a bad commit, he should use 'git reset HEAD^' right away. This way the problem can be fixed before git push distributes the bad commit to your team.

Let me know if this makes sense or if you have any question. I also accept "Git Challenges". That is if you have a problem you'd like to know how it could be solved in Git, just let me know in the comments and I'll blog about it : ).

-- Felix Geisendörfer aka the_undefined

 

The open source business model

Posted on 12/9/09 by Felix Geisendörfer

Seth Godin explains it perfectly this morning:

You need to make something else abundant in order to gain attention. Then, and only then, will you be able to sell something that's naturally scarce.

Tim and I stumbled across this model by accident when we started our blogs a few years ago. Since then our business has been a 99% byproduct of the "free" stuff we are doing.

-- Felix Geisendörfer aka the_undefined

 

Google Chrome for Mac

Posted on 11/9/09 by Felix Geisendörfer

When @predominant linked to a OSX release for google chrome the other day I couldn't resist.

My initial feeling: Awesome. Feels much snappier than Safari 4. My only two issues: a) No support for Safari-style keyboard shortcuts for the bookmark bar items. b) Even so chrome integrates with Keychain, it doesn't seem to use my Safari logins.

Lucky for me, Google also just released their Extension API. Two hours down the sink, I created my first extension: Bookmark Bar Shortcuts.

I switched from Firefox to Safari as my main browser a long time ago because I just could not deal with its slowness on OSX. I still have a few issues with Chrome, but I think they are due to the experimental Mac release. Once Chrome goes beta I'm pretty sure Safari won't be running on my computer anymore. Nor will Firefox once somebody ports Firebug to Google Chrome.

-- Felix Geisendörfer aka the_undefined

Update: @reconbot says Ctrl + <1-9> already works on Windows. Can somebody confirm?

 

How to Fetch the ENUM Options of a Field - The CakePHP Enumerable Behavior

Posted on 8/9/09 by Tim Koschützki

Hey folks,

for a current client project of ours we had to build an extensive ACL-like permission system. It had to support roles permissions and specific user permissions, possibly overriding the roles permissions. So, to create a user, you had to first define his "role" or "level" as I called it in a dropdown box in a form.

However, the field users.level is an enum type and can have the values 'guest', 'user', 'admin', 'superadmin' and 'root'. The problem is that it could be possible that new levels were added in the future. There was no need though to have a seperate user_levels table and a UserLevel model there, since the system should simply not be as generic to allow that and adding a new level in the future would require a complete other version of the software. So I went the easy way.
Besides, as we use uuids, the users.level field would contain them and after all we want our database to be readable in our favorite db management system.

So what I came up with is a very simple behavior that can extract the options for any ENUM field. It uses simple caching in order for the query to not be run all the time, so make sure to clear your cache as you update your enum field options in the db.

Here is the behavior:

<?php
/**
 * Behavior with useful functionality around models containing an enum type field
 *
 * Copyright (c) Debuggable, http://debuggable.com
 *
 * @package default
 * @access public
 */

class EnumerableBehavior extends ModelBehavior {
/**
 * Fetches the enum type options for a specific field
 *
 * @param string $field
 * @return void
 * @access public
 */

  function enumOptions($model, $field) {
    $cacheKey = $model->alias . '_' . $field . '_enum_options';
    $options = Cache::read($cacheKey);

    if (!$options) {
      $sql = "SHOW COLUMNS FROM `{$model->useTable}` LIKE '{$field}'";
      $enumData = $model->query($sql);

      $options = false;
      if (!empty($enumData)) {
        $patterns = array('enum(', ')', '\'');
        $enumData = r($patterns, '', $enumData[0]['COLUMNS']['Type']);
        $options = explode(',', $enumData);
      }
      Cache::write($cacheKey, $options);
    }
    return $options;
  }
}
?>

To put that into the form I did in the controller:

$enumOptions = ClassRegistry::init('User')->enumOptions('level');
$this->set(compact('enumOptions'));

and then in the form:

echo $form->input('level', array('options' => $enumOptions, 'label' => 'Level:'));

Enjoy and please give feedback.

-- Tim Koschuetzki aka DarkAngelBGE

 
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11