daemon-kit 0.1.8 released

Posted by Kenneth Kalmer on August 04, 2010

I’m proud to announce that daemon-kit has finally made it to 0.1.8.1, almost a year after the last patch release. There has been a lot of changes since the last release, mostly cleanly up and staying with the times (so to speak). Github has an awesome compare view, detailing the historic moment, and I’ll go through it here in some detail as well.

First off I’d like to thank a few people who have quietly and vocally contributed to or promoted daemon-kit. In no particular order, thanks goes to:

The two biggest changes for me has been converting all the generators to use Thor, and using Bundler in the generated daemons. Both of these projects have received some flack, but they both continue to serve me very well and I’m sure they’ll serve daemon-kit well.

The logger got some minor updates, to be more compatible with the standard Ruby logger class. A brand new XMPP generator is included, and it uses Blather for some awesome evented-goodness. Argument handling got fixed up, email exceptions got removed from the project (I might consider implementing them after overhauling the error reporting features of dk). Hoptoad error reporting got upgraded to the use the newer API. The generated rake tasks are more forgiving when rspec/cucumber or other gems are missing. The cron daemon got some love, allowing easier exception logging/notification for when scheduled tasks fail.

I’ll continue chipping away at the project, tidying up loose ends as they are reported, and start developing a proper test suite for everything.

Over the long term I’m hoping to reach the following goals:

  • Always running the eventmachine reactor (think node.rb)
  • Support for more modular daemons, including ’single-file’ daemons
  • Support for daemons inside Rails projects

Some things will probably get thrown out, like generating configs for god & monit. The more I use chef, the more I realize that those responsibilities lie with the infrastructure management (or devops), and not within the project itself. I’m aware this might cause an upset, however I firmly believe that a lighter and smaller daemon-kit will serve the greater community better.

Thanks for making daemon-kit the number 1 daemonizing project. Please share the love and send feedback, and more importantly use Github issues to log issues, feedback, and wishes.

Paginating documents with couchrest and will_paginate

Posted by Kenneth Kalmer on February 08, 2010

CouchDB is hands down my favorite of the NoSQL variants and offers some pretty spectacular features, none of which I will bore you with in this post. I will however jot down how I (fairly easily) achieved pagination with couchrest & will_paginate in a fairly large Rails application recently.

John P Wood discussed some issues they faced with will_paginate and couchrest during the migration of TextMe to CouchDB, but l left out some code to work with. Couchrest itself had some pagination support that got pulled to some extent… This left me wanting, and wondering, since it was my turn to walk down this path.

CouchDB is a different beast, its aggressive use of indexes means that occasionally you loose some functionality that you’ve been accustomed to having in other persistence mechanisms, like the number of rows matching a query. Jan Lenhardt explains on the CouchDB issue tracker in more detail, but it boils down that you need a reduce function to calculate the number of rows. Sounds difficult? Not at all!

In my case I had a collection of announcements to deal with, and the announcement archives is a paginating collection of documents. Standard will_paginate stuff, nothing special.

Those reading in a reader would want to click through to the post to view the embedded gists further down, or view them directly at Github.

Below is a condensed version of the model from our paginating system:

I’ve included only one view and a corresponding class method, as it is enough to proof the principle. Lets dissect.

The map/reduce functions are extremely simplistic, they simply emit the announcer and the date the announcement was created. This allows for easy scoping and ordering of the announcements. The reduce simply counts our returned records. The magic is in the class method that sets up our WillPaginate::Collection with data from our views.

Line 30 creates a new WillPaginate::Collection instance, passing it the page number and total per page as parameters, it gives us back a pager that we can manipulate.

Lines 31 through 38 uses couchrest’s pagination support to pull out data from our view. The most important things to note here are that the page and per_page options are sent to the paginator and we skip the reduce step.

Once we have our records loaded, we ‘replace’  the pager’s collection with our results from our view (line 40).

The final step is to determine the total number of documents available to us, and for this we need the reduce function. On line 42 we call the same view, with the same arguments, except for requiring the reduce step to happen. We use the results (lines 43 to 47) to inform the pager (will_paginate’s pager) how many rows there are in total.

The controller and the views might look something like this:

It worked, and it shows that we don’t loose as much as we might think when moving away from ActiveRecord and the ton of plugins surrounding it.

Thanks to John for documenting the migration of TextMe, just knowing that it was possible to combine couchrest & will_paginate gave me the push I needed to figure this out.

Disclaimer: This code is extracted “as is” from a real life system and might contain idioms/phrases, and even code, that doesn’t make 100% when viewed in a gist. Please wear your thinking cap when applying this lesson to your own projects.

Correlating documents in CouchDB 5

Posted by Kenneth Kalmer on December 13, 2009

I’m in the very fortunate position, two actually, of being able to 1) migrate my biggest production application from MySQL to CouchDB, and 2) build a stunning new system for a multinational welfare organization on top of CouchDB.

I’ve been lurking in the CouchDB world for quite some time and have spent a lot of time wrestling with how to loosely relate documents in CouchDB to each other. A big part of learning to use CouchDB successfully is to break away from the shackles of the relational world. Relationships between documents is one such a shackle that seems hard to break.

It is unavoidable that data has to be correlated, and I wanted to rethink how to do it. After plenty of discussions in #ruote with John Mettraux we came up with a model based on how the web works. Since CouchDB is “off the web”, the approach feels quite fitting to me and hopefully to you too.

First some insight into my thinking at this stage.

The web has been successful in loosely expressing relationships between documents. Take two examples:

and

For those of you reading this through a reader, click through to see the gist’s above.

Simple as it seems, in both cases we have a document that is somehow related to the page. The nature of the relationship is expressed via the rel attribute, and the target specified via the href attribute. This got me thinking. Since CouchDB is made off the web, can’t these same principles be applied?

Yes, they can. And here is how:

Currently you might be tempted to express relationships link this in your JSON:

Where changing it to this holds the key:

If anything this format, albeit more verbose, expresses the relationships more clearly and in a format that is web friendly. We’ve broken the shackles of relational thinking.

Enter Correlate

Correlate is an experiment in this line of thinking. It is a mixin for CouchRest’s extended documents that allows you to express these relationships:

Correlate generates getter and setter methods for working with your relationships and lot more (review the README). It also includes a compatibility layer for ActiveRecord to help when you’re migrating from ActiveRecord to CouchRest or building a system on CouchDB that needs to access legacy data via ActiveRecord.

The project is still pretty much a moving target, but I’d love to hear how others address the same issues. Correlate does a great job at maintaining relationship information in a web friendly manner and providing you with some convenience around the verbose data structure. Correlate also has a lot of room for improvement, but that will hopefully change over the coming days as I continue integrating it deeply into my existing projects.

Please fork the project on github and join the experiment with me.

Rails specs not running under Ruby 1.9 ?

Posted by Kenneth Kalmer on September 27, 2009

I spent some time getting PowerDNS on Rails to run on Ruby 1.9.1, which ended up being very easy due to the small amount of plugins & gems used by the project. The only change I had to make myself was to the acts_as_audited plugin, where the one-line fix got merged upstream.

The worst part of the process was getting the specs to run with rake spec. Using ./script/spec it worked on individual specs and on all the specs worked as advertised, but rake spec didn’t do anything.

After a lot of time spent in the debugger I wasn’t any wiser. The only difference was that in Ruby 1.8 the example groups were fully loaded, and in Ruby 1.9 they were empty. I gave up and started searching relentlessly for some information on the issue. I couldn’t find anything, until I found an indirect solution on the rspec wiki. It seems that if you have any versions of the test-unit gem after the 1.2.3 release installed, your Rails specs will simply not run. For me, removing test-unit 2.0.3 made the difference and the specs ran properly. PowerDNS on Rails has now joined the ranks of my Ruby 1.9 compatible projects.

  • Tags

    activerecord air amqp analytics audits bash bind capistrano cheat convert couchdb daemon-kit dlz dns elsewhere gentoo gist git hoptoad linux macros mercurial messaging mysql nginx olympics plugins postfix postini powerdns presentations projects quickies rails rake review ruby ruby19 ruote security shoes sitemap ssl svn webby
  • Recent Posts

  • Archives

  • Alltop. Seriously?! I got in?