Wednesday, September 24, 2008

Reia where scripting meets concurrency

Reia reminds me of that Reese's peanut butter cup commercial:

Hey, you got your Ruby/Python in my Erlang! Hey, you got your Erlang in my Ruby/Python!


And then there was this light that went off in someone's head - Why couldn't you bring the "stuff" people like about higher level languages down into something that, quite frankly just kicks ass, in Erlang?

To kick it off - and to quote the Reia wiki:
Reia (pronounced RAY-uh) is a Python/Ruby-like scripting language for the Erlang virtual machine (BEAM). Reia aims to expose all the features and functionality of Erlang in a language more familiar to programmers of scripting languages, while improving string handling, regular expressions, linking with external libraries, and other tasks which are generally considered outside the scope of Erlang. Reia is distributed under the MIT License.


Well, it's happening right now with Reia. I've been watching this project over my GitHub feed for maybe a month or so now and it's really cool seeing the leaps and bounds that Tony Arcieri is making with this little gem of a language. Granted, he still has a ways to go (and he openly admits this), I suggest giving it a try for fun() (that's my new favorite pun by the way).

Let me paste a few ideals from the Reia site to pique your interest a little more:
Concurrent programming is the future - very true, now if DB's would just catch up (oh, wait CouchDB!

You don't need an "everything is a..." language - he calls out SmallTalk and Ruby, but his argument is convincing, I think we've all been here before.

Don't build what you can steal - I really like that quote in regard to using a syntax of Python/Ruby and then laying it lovingly over the Erlang VM and OTP framework.

Monday, September 15, 2008

Judging a book by it's "sucks" result

A friend of mine asked me recently to go in on a little venture of his in the gaming industry. Unable to say "no" to what I believe is a fantastic idea, I went along with it...

Now there was another guy involved (technologically speaking) who wrote something that was a working prototype (awesome). It came down to a little discussion as to what WE should use for the front-end and storage mechanisms.

Well, having deployed a few real life applications in Ruby and having success with them, I only felt the need to display my affection and trust that I had with it and it's frameworks (yes, both Rails and Merb).

The problem I had wasn't that the guy wanted to use Python/Pylons or something in that realm. It was the argument. In fact, now that I've heard it a few times I can almost pinpoint exactly where the debate material is coming from. And that my friends, is simply fantastic. We're still not going along with the right tool for the right job, we're still shooting from the hip with what "we like".

Uh, but Brad, you just said you liked Ruby? You're right, I did. But given the requirements I was handed and based on past experiences it appeared to be the right tool for the right job.

I'm open to using new things - if I wasn't why would I ever give things like CouchDB and Erlang the time of day? They're sitting right on the edge of the programming paradigm shift from what most coders/programmers/developers are use to and it fascinates me.

Back to it.

I'm fine with using Python or whatever for a web interface. One more (hopefully) successful notch in my belt and slap proudly on a resume. But it just absolutely kills me when the keys of an argument are literally plucked from simply searching Google for "why sucks". What's even worse is when it's a predominantly blog rifling .

Please, please, please, I'm begging you the reader of this blog post; the rule here is simple, I'll even wrap it in a blockquote for you to save and tattoo across your chest in a Tupac-ish style:

Research first, execute later.


It's not the other way around, in fact, if you do it the other way around you're going to do your research the hard way; rewriting it in the layers you should have used in the first place.

Monday, September 8, 2008

Is your DataMapper CouchDB adapter PUT'ing where it shouldn't?

It sounds gross, sure...but this was actually a simple problem I foresee someone running into and potentially running around mad about for an hour if they're not too keen on how DataMapper/CouchDB work together. Even if you DO know how they work together, this was still a fun problem to track down.

So let's take an example model that's extremely simple:

class Person
include DataMapper::Resource
# CouchDB Specific
property :id, String, :key => true, :serial => true, :field => :_id
property :rev, String, :field => :_rev
#App Specific
property :name, String, :nullable => false, :length => 75, :key => true
end


Looks harmless, right? That's what I thought too! Well, if you begin your application and get to the point of actually creating a Person you'll be greeted with an error that kicks off with "EOFError: end of file reached ".

So what's happening here?

Basically in the adapter, there is a LOC in the create method where it checks to see if there is a key or not (Yea, the one we've specified above as :name).

This creates an assumption of using PUT instead of POST and that is where the issue stems from. So, to fix this problem, all you need to do is DROP the :key => true and things will run as they should.

Now you're probably asking "But, what if I NEED to have that key there, I NEED to relate my models with a foreign key". Not to sound harsh, but just to be clear, you may want to revisit why you're using CouchDB in the first place.

Readability vs Optimization

I recently saw a post come across my Google Reader a few days ago asking what someone should code "for". His two options were Readability or Optimization. I'm not going to link the article for the simple reason it was incredibly brief and it was mostly just a question, the author never really jumped into going one way or the other or leading from one to the other.

So have no fear, I'll do it!

What makes sense? You want code you can read, yet you also want it to run incredibly fast. Interesting! Well, like any project the first one to market usually gets the worm. So cranking out code (read: code that "works") is typically a developer's (and many times the project managers) first concern. Do we have something out there to start drawing in the cash? Yes. So you've effectively coded for "readability" since we're not optimized. You've gotten your product on the market which is really what your first goal SHOULD be, unless of course there's some ungodly amount of volume that you KNEW of and should have optimized according for it in the first place.

Now, wait a minute...that sounds like common sense. If I'm developing something new that no one knows about, what's the point of optimization? I can just crank stuff out that "works" and polish up that while we gain customers/visitors/whomever. Correct!

On the flipside of the previous paragraph, our (I mean everyone's, not mine personally) good friend with a framework Ezra Zygmuntowicz had an interesting quote a while back where he said "Post-optimization is the route of all hosting bills". In the article I'm extrapolating on, one commenter said if one codes strictly for readability, optimization will come automatically because hardware continues to get faster. The author himself also said "Performance can be optimized at the hardware level", which blew my mind. Why are you even asking for hints on code optimization (for PHP) if you already made up your mind to throw hardware at it? I can't speak for him, but I'm pretty sure you're not going to be replacing your systems with the latest and greatest hardware every 18 months are you? Hmm, Nope!

So what do we need to do?


Well, we've already cranked our code to production, things may or may not be fine with the community accessing it, and I'm sure you've been paying close attention to which aspects of your system need work, help, or simply need to be scrapped and redone. Wait, you haven't? Ok, let's start there.

Pay attention to what your application is doing.


Get a decent logging or monitoring system and pay close attention to the needs of your app. Many times we get so caught up in producing that we never pay close attention to the simple things once it's out in the wild. EVEN MORE TIMES than not, people don't see what applications that may be similar in nature are doing or how they're reacting online to try and investigate why they are having these problems. Chances are, your application will have them too - you cannot assume that just because you wrote the code that it is exempt from bottlenecks. In fact, I'd say the vast majority of the time, you're going to hit the exact same problems as your competitors.

Do your research, if they're a fairly transparent company see what growing pains they were having and try to plan accordingly.

Now that we've addressed the issues surrounding our application AND applications which are similar in nature to ours we can now effectively move into the space where we begin optimizing our code. This is a rather vast term and your focus should (in my opinion) stem from your I/O bottlenecks first before jumping to your code. If all seems well in that area or you simply don't have the funding to do much with it, then sure, you're ready to start optimizing code.

So in essence the life cycle is as follows:
1 - Produce working code that meets your needs.

2 - Analyze how it and other I/O (disk/network/database) are affecting your application.

3 - Attempt to alleviate as much of that I/O overhead as you can within your boundaries (manpower, funding, etc...).

4 - Optimize your code.

I think that will get you through the day. I could be wrong, I flew through this post pretty damn fast. I feel a site optimization post coming soon, so get ready for some more Kool Aid to drink.

Wednesday, August 20, 2008

Ruby vs. Erlang vs. The People vs. Your Application

For the past six months or so I've been working on a somewhat under the radar service called Mumbl. Basically, mumbl is a micro-blogging service that solves the whole "Oh, we chose the wrong framework for the wrong platform and our db won't/can't scale" problems most of the bigger folks have. And for all I know they may well have already solved their issues as it seems to be getting better(?) as less and less downtime occurs. Good for them, the Mongolian Horde/money shovel approach to systems and development worked...for now.

Anyway, there's been a momentum gainer amongst Rubyists looking more and more at Erlang. Which, yea is great but I think one of the biggest problems with Ruby developers is that we (yes, I'm one too) don't just drink the punch if things "make sense", WE CHUG IT! We ask that it be hooked intravenously into our veins until it becomes a part of us on a molecular level.

So, having said that, why would someone that's vested deeply in Ruby, which preaches readability and quick, elegant solutions to common problems (whether it be via frameworks or gems) have any interest in Erlang? Erlang is based on ant-turd tokens, which aren't exactly easy to read. Erlang appears to also be fairly verbose in a sense that I can't see it "fitting" for your typical online applications and it certainly isn't the easiest thing to read. So please, if you need to undertake a project that would quite easily be completed using the rails/merbs/django's of the world out there - then utilize them! It's my opinion that Erlang is not a language for application that need constant adjustment, in this particular case applications for the online masses. Leave it to the back-side and you'll thank me on your wedding night!

This was touched on a little bit a while ago (the Erlang thing, not the back-side thing), I had to go dig up the post but you can see Damien Katz's blog entry about a few things he disliked about Erlang. See the comments of his posting for a real roller-coaster ride!

Anyway, getting back to the point here. I think we need to be careful when given the option of the punch, which really is true for anything. But something we, as developers should look at so closely is the separation of trendy with practical. I believe we can all agree that a readable/maintainable application layer with a concise entry point to a highly parallel back-end is probably the best way to go. Maybe not; well, let me try and convince you otherwise.

If you had to throw a jack of many trades developer into the mix of your application I described above how do you think he'd handle it? I think they would greatly appreciate the easy readability of the Ruby code over the Erlang. Once they ramped their way up gaining and understanding of the interfaces it would likely make their lives easier once they made it into the land of Erlang.

So please, let's keep it separate. And let's please, please stop creating half-assed Ruby implementations of things that really don't need it. This recent post on the register certainly struck a nerve with me. It was apparent they we are getting lazy and far too comfortable in our language to expand horizons and use the right tool for the right job. That tool doesn't need to take over completely, getting back to the punch-chugging I mentioned earlier. You need to find it's proper place in your application if it even fits at all, don't make a place for it. And certainly don't make a cheesy knock-off of it in Ruby so you get 1/2 points for utilizing some new (or trendy) methodology.

Ah...now that' feels better.

Wednesday, August 6, 2008

Timezones in Gentoo

I'm on Central time...and there wasn't a clear way (within the gentoo docs) for getting myself on the correct timezone. SO, for anyone in my timezone that needs it...this is the way to do it:

rm /etc/localtime && ln -s /usr/share/zoneinfo/US/Central /etc/localtime

For anyone else, after zoneinfo// - make sense?

40 minutes...and sometimes I wonder about myself.

Monday, August 4, 2008

SFTP and blogger

Just a hint for anyone setting up a hosted blog via the blogger platform.

You will likely need to modify your /etc/ssh/sshd_config file...or else you will be unable to publish to your sftp site.

The change you need to make is:

PasswordAuthentication yes


It's likely already set to "no".

I was getting this error while trying to publish to a hosted blog to my domain and was seeing an error in my ssh log that read:
Did not receive identification string from [google ip addr]


So yea, I hope that helps anyone who needs it.

Saturday, August 2, 2008

Merb does it again...

Remember in the old days when you'd create what I can only explain as a "temporary session" in Rails to notify someone ONCE on a page of something? It could have been a form validation error, a success, just anything that you needed to toss up to the user temporarily. Still with me?

Merb now has this wonderful "message" implementation which they've hooked onto the redirect method. So, by calling:

redirect '/some/path', "We're gonna need a bigger boat..."


You receive a variable "message" that contains your message (conventional, right?). It's basically marshalled and plopped into the querystring and then deserialized into the var. I really like this over the Rails method...but, following what the Pug says - I'm not pitting merb against rails.

.erawtaolB !lleh eht tahw ,naem I .noitatnemelpmi laivirt a hcus ekil smees siht nehw o/i pu gnitae ,snoisses pmt etaerc ot tnaw uoy od lleh eht yhw si gniyas m'I llA

It's late, I'm wiped out and that's the "best" I could do for humor.

Friday, July 25, 2008

CouchDBXapr

Ok, so I've been working on a Xapian implementation for CouchDB to feed off of in Ruby. Just a quick note for anyone who is attempting the same.

1. On OSX, everything works great, the bindings install to their proper places. All is well with the world.

2. However, in production mode, on a Gentoo server, running make check reveals that we are unable to find our libxapian.so file.

SO, in order to remedy this and to save anyone else looking for this fine obscure error. Run make install...

You'll then notice any of your Ruby scripts are unable to process anything that even mentions the word 'xapian'.

Then, simply do the following:

cd /usr/local/lib
cp libxapian.so.15 /usr/lib64/

et voila!

You are now ready for some fulltext goodness and if you're like me are now ready for some much needed rest.

Thursday, July 10, 2008

Integrating with UrlZen

For my twitter-like application (mumbl - not yet released) I've decided to give users the ability to shorten their long URL's for their mumbls as they're typing them using UrlZen.

Here's the Ruby implementation - I'll post a follow-up containing the jQuery portion. basically to get around XSS I call a URL on my system which then calls up UrlZen

require 'mechanize'
agent = WWW::Mechanize.new
@url = params[:url]
@new_url = agent.get("http://urlzen.com/shorten/?autocopy=true&url=#{@url}").search("//p[@class='short_url']//strong").inner_html

Sunday, July 6, 2008

So what happened (the multi-key CouchDB question)?

So, if any of you have been following along with my fun ride upon the cozy cushions of CouchDB, you'll be happy to hear there is hope (well, some - I had to pick up a book on Erlang).

Anyhow, if you follow the link here you will see that there was a list of proposed fixes for my desire to pass in multiple keys to CouchDB instead of just one. Granted, yes it could get out of hand, you could pass in 1,000,000 keys. But so what! Either way you're going to have to query for them, whether it's a query after a query a billion times or if you can somehow lump them together.

So as you can see there were a few options:

1. We could execute our query with each key each time and lump them together. The downside of this is that I really don't want Ruby to have to lump all of those results together, I can only imagine the paging for it would get incredibly *blah*. Plus the memory usage for Ruby to merge all of those DM::Collection objects together would likely be the equivalent of a Chihuahua passing a peach seed. Not pretty.

2. We could use a full text search using Lucene, which CouchDB already has implemented. I suppose the only downside of that would be...??? I'll need to think of something, it's really not a bad idea, it just may come to me later. The extent of my full text search capabilities have been with MySQL and...oh, hold on I keep laughing, it sucked. bad. I really hope CouchDB's is better - I'm sure it is, I haven't seen anything so far that is crap!

3. We (read: Me {Bradford}) hack at the CouchDB internals and allow for views to accept multiple keys for comparison rather than one. I'd like to see this happen via something to the effect of:

A single key query URL
http://.../_view/foo/bars?key="mykey"

A Multi-key query URL
http://.../_view/foo/bars?key[]="mykey1"&key[]="mykey2"
OR
http://.../_view/foo/bars?keys=["mykey1","mykey2","mykey3"]

I'd like to keep it along the lines of form control arrays key[] this way you could just analyze the parameter itself to see what it was (an array or a string) and do the appropriate things with it. Whereas adding a parameter keys may need to be repeated throughout the code (Not likely, but the former makes sense to me most).

I'd like to extend a warm welcome to anyone willing to walk the lines of CouchDB's internals with me in order to implement such functionality, I promise to keep you in line as long as you return the favor. As I said, I'm JUST NOW learning Erlang and am horribly under-qualified, but hey, I really feel strongly about this functionality, so, what the hell, right?

Bring on the opinions!

Thursday, July 3, 2008

It's all about document design with CouchDB

Hello everyone, been stalking the mailing list for a while and thought this might be worthy of a post as I was asked to solve it, yet, I couldn't!

Let's take the classic blog example document with the following fields/values:

"_id": "1f2fc3955b91aed5e7369f0b0ba8214e",
"_rev": "1226709986",
"Author": "Bradford",
"Type": "Post",
"Body": "Just mentioning this for a sample blog post.",
"PostedDate": "2008-07-02T23:22:12-04:00",
"Subject": "My Fine Blog Post",
"Tags": ["octopus","hockey","squidward","bradford","recreation"]

Next, I'd like to find each blog post that contains ANY of the following tags ["octopus","hockey"]. Now, generally speaking this isn't so bad. We could write a simple view:

function (doc) {
if (doc.Type == 'Post') {
for (var i = 0;i < doc.tags.length; i++) {
emit(doc.tags[i],doc);
}
}
}

We would get back each one of our tags as a key, yea? Only if we supplied one at a time. So how does one go about supplying a range, array (not sure what we'd call it here) of keys to be searched on? http://...?key=["octopus","hockey"] maybe? I'm unsure of the plan of attack for such a thing. Maybe I'm just going about it in the wrong direction. Any thoughts?

Friday, June 20, 2008

So I finally bit the bullet and did it...a merb, datamapper and couchdb lovechild.

I got up this morning, wonderful day, got in to the office early, ground up some rocket fuel coffee beans and began my development day. Started off pretty sane, but slowly it turned into a full-blown hackfest!

Suprise, suprise...look whose coding!


Yes, my Cuban bee's after finally hitting my limitations with the CouchDB 0.7.2 adapter I took one for the team and got it working for 0.8.0.

This is by no means complete as I am going to build paging into the adapter as well before I submit it for usage in DataMapper. So without any further delay...Here are the goodies. I'll again just drop in what I've overloaded so you can have a pretty seamless transition if you need it. Also, this is currently running off of the CouchDB 0.8.0 trunk (see this page for subversion linkage)

Also, note the TODO, it should be done later this evening all things considered. Last but not least, I hope this helps someone other than myself, enjoy!

module DataMapper
module Types
class Object < DataMapper::Type
primitive String
size 65535
lazy true
track :hash

def self.dump(value, property)
value.to_json unless value.nil?
end

def self.load(value, property)
value.nil? ? nil : value
end
end
end
end

module DataMapper
class Collection < LazyArray
attr_reader :_total_rows
private

def initialize(query, options = {}, &block)
assert_kind_of 'query', query, Query

unless block_given?
raise ArgumentError, 'a block must be supplied for lazy loading results', caller
end

@query = query
@key_properties = model.key(repository.name)
@_total_rows = options[:total_rows] || 0
super()
load_with(&block)
end

end
end

module DataMapper
module Adapters
class CouchDBAdapter < AbstractAdapter

def read_one(query)
doc = request do |http|
http.request(build_request(query))
end
unless doc["total_rows"] == 0
data = doc['rows'].first
query.model.load(
query.fields.map do |property|
data["value"][property.field.to_s]
end,
query)
end
end

def read_many(query)
doc = request do |http|
http.request(build_request(query))
end
Collection.new(query, {:total_rows => doc['total_rows']}) do |collection|
doc['rows'].each do |doc|
collection.load(
query.fields.map do |property|
property.typecast(doc["value"][property.field.to_s])
end
)
end
end
end
def ad_hoc_request(query)
if query.order.empty?
key = "null"
else
key = (query.order.map do |order|
"doc.#{order.property.field}"
end).join(", ")
key = "[#{key}]"
end

options = []
options << "count=#{query.limit}" if query.limit
options << "skip=#{query.offset}" if query.offset
options = options.empty? ? nil : "?#{options.join('&')}"

request = Net::HTTP::Post.new("/#{self.escaped_db_name}/_temp_view#{options}")
request["Content-Type"] = "application/json"

if query.conditions.empty?
request.body = '{"language":"javascript","map":"function(doc) { if (doc.type == \'' + query.model.name.downcase + '\') { emit(' + key + ', doc);} }"}'
else
conditions = query.conditions.map do |operator, property, value|
condition = "doc.#{property.field}"
condition << case operator
when :eql then " == '#{value}'"
when :not then " != '#{value}'"
when :gt then " > #{value}"
when :gte then " >= #{value}"
when :lt then " < #{value}"
when :lte then " <= #{value}"
when :like then like_operator(value)
end
end
request.body = '{"language":"javascript","map":"function(doc) {if (doc.type == \'' + query.model.name.downcase + '\') { if (' + conditions.join(' && ') + ') { emit(' + key + ', doc);}}}"}'
end

request
end

def request(parse_result = true, &block)
res = nil
Net::HTTP.start(@uri.host, @uri.port) do |http|
res = yield(http)
end
# debugger
JSON.parse(res.body) if parse_result
end

module Migration
def create_model_storage(repository, model)
assert_kind_of 'repository', repository, Repository
assert_kind_of 'model', model, Resource::ClassMethods

uri = "/#{self.escaped_db_name}/_design/#{model.storage_name(self.name)}"
view = Net::HTTP::Put.new(uri)
view['content_type'] = "javascript"
views = model.views.reject {|key, value| value.nil?}
# TODO: This absolutely should be handled up a level.
# You shouuld pass view a hash
#{:map => "function(doc){...}", :reduce => "function(doc){...}"}
# We'll get there...
view.body = { :views => views.each {|k,v| views[k] = {:map => v}} }.to_json

request do |http|
http.request(view)
end
end

def destroy_model_storage(repository, model)
assert_kind_of 'repository', repository, Repository
assert_kind_of 'model', model, Resource::ClassMethods

uri = "/#{self.escaped_db_name}/_design/#{model.storage_name(self.name)}"
response = http_get(uri)
unless response['error']
uri += "?rev=#{response["_rev"]}"
http_delete(uri)
end
end
end

end
end
end

Thursday, June 19, 2008

CouchDB One more thing

I almost forgot. In DataMapper, it currently stores things like arrays, hashes in couchdb perfectly. It converts them into JSON and stores them, so they're query-able! The bad thing is that when it attempts to read them out (currently) it assumes that because the property types in your model are set to "Object" that it needs to first base64 decode the marshalled/encoded object and then de-serialize it.

Well, I really don't want things that could be incredibly important being fudged in my data. Especially now that I have another dimension I can query on. So I "fixed" the object data type for when I'm working with CouchDB. This will allow you to both store and read values such as arrays and/or hashes without any voodoo. Just drop this override in your init.rb or in another place where it's sure to be loaded AFTER datamapper has been initialized.


module DataMapper
module Types
class Object < DataMapper::Type
primitive String
size 65535
lazy true
track :hash

def self.dump(value, property)
value.to_json unless value.nil?
end

def self.load(value, property)
value.nil? ? nil : value
end
end
end
end

DataMapper and CouchDB

It's likely that if you're a regular reader of this hapless place I call a blog then it's likely that you either:
a) have heard me spew off at the mouth about how incredibly awesome couchdb is
or
b) have not and are likely ready to completely disagree with the entire philosophy behind it and call me an idiot. Which is fine; that's fine!

Anyway to quote the wonderful couchdb page:


Apache CouchDB is a distributed, fault-tolerant and schema-free document-oriented database accessible via a RESTful HTTP/JSON API. Among other features, it provides robust, incremental replication with bi-directional conflict detection and resolution, and is queryable and indexable using a table-oriented view engine with JavaScript acting as the default view definition language.


So rather than having blobs of tables prone to locking or even rows that are prone to locking. Either way, no matter which RDBMS you use, you're likely to be trapped into the same issues.

A quick rant - it's not the language, it's the I/O. Be it database, disk (likely from a database) or the network; your language doesn't matter. An incredibly well-crafted application will still fall to pieces because of one of those three issues.

Back to it - so with couchdb, you store documents (think of them as rows, but they can be 3-dimensional), you can store just a standard field (text), arrays, hashes, marshal and base64 encode an object, you name it you can put it in there. And it's all linear and most importantly it's based on map/reduce.

So in the old country where you'd key in on those ever-so important relationships and eager-loading to save on the n+1 problem, you don't necessarily run into that with couchdb. Why? Because your map function will return all of the documents that are of interest to one another for your view. You're simply storing crap in all of the files, the more de-normalized the better! You can think of it sort of like this: a row could be considered a document. But within your document, you store all of the pertinent information instead of just storing an _id field with the appropriate row's id as a value. It works to get rid of those horrible join queries by de-normalizing the data.

It's really rather difficult for me to talk about as I'm still wading my way through it. I'm really not confident in my explanation about, but again I'm trying to find this as I go along as well. So feel free to post any "fixes" in the comments as seen fit.

Enter the DataMapper.

As of datamapper 0.9.2 they have added an adapter for couchdb. Some people would really like to just put some javascript together and link directly to couch to save some layers, but the fundamental problem with that (for now) is that you give up your databases security. A HUGE thing, I know. Even for people using it with ORM's in front of it, it's still problematic. You're prone to attacks because it's purely HTTP-based. And spoofing over HTTP is a joke. If you want to know why or how I know these things, just ask.

Anyways, the benefit of using an ORM in front of the database is two fold for me. First, I don't have to worry about some script-kiddie coming across, scraping my site and yanking my application out from under me. Yea, maybe that's selfish of me being an open source developer, but hey, I use open source to make; guess what? MONEY! Uh, where the hell was I? Oh yes. So the second thing aside from separating the databases secure-less protocol is simply the ease of use when tying it into the actual metal of my application. Validations, simple object creation, abstraction it's all there and makes my application a wonderful thing to work in.

Now, for every good there is certainly a bad. Currently DM's CouchDB adapter only works with version 0.7.2. There are a whole host of people trying to write ruby-based ORM's that work exclusively with CouchDB. That's great! Really, it is. But there is a long, long road to tread when you undertake such projects. Which is why I have chosen to stick by it and just alter the adapter to suit my needs and then when the time comes, release it back into the open. It's not a huge endeavor to alter the adapter as it stands now. Having hacked through the guts of it for the last week, I have come to greatly respect all of the hard, intelligent work that goes into DataMapper and Merb respectively. When comparing it to some of the internals of Rails, with all of the "magic", super calls, alias_method_chains and what not, one can truly appreciate readable, sensible code that you can literally walk through without having to do a stack trace! Excellent job, men!

Finally, this wouldn't be complete without me sharing a little nugget of information. This may not be the best way to go about handling this certain "problem" but it works well for me and maybe it will work well for you too (if you decide to drink the CouchDB punch)!

Let's talk about paging for a moment. How do you typically do it in applications like Rails, PHP, *.NET, anything really? Well, you typically need to perform two queries, right? One that gets the total count of records that you'll be acting upon and another to pull in that data a little at a time (via a limit and offset). Luckily for us, CouchDB actually provides you back the full list of documents which were queries on. Thus eliminating the count(*) query. So what I have done is modified the CouchDB adapter just slightly to return back an attr_reader which holds the total number of documents in your view. See the following code samples:
The first, is the override on how DataMapper's Collection works. My first thoughts were to just include the total rows with each object in the Collection. But that's sloppy, eats up memory and you wouldn't have access to it without instantiating one of the objects in the collection (redundant, yea?). So, let's go up a level and just attach it to the Collections themselves. Again, maybe there's a better way but hey, this is what I came up with.


module DataMapper
class Collection < LazyArray
attr_reader :_total_rows
private

def initialize(query, options = {}, &block)
assert_kind_of 'query', query, Query

unless block_given?
raise ArgumentError, 'a block must be supplied
end

@query = query
@key_properties = model.key(repository.name)
@_total_rows = options[:total_rows] || 0
super()
load_with(&block)
end

end
end


The second sample is where we pass in the total_rows attribute from the returned document's JSON store and pass it as an option to the Collection.initialize method as it is constructed. We grab the value, pass it up and it's now available in one spot for your collection as a read-only attribute. Bye-bye count query!

module DataMapper
module Adapters
class CouchDBAdapter < AbstractAdapter
def read_many(query)
doc = request do |http|
http.request(build_request(query))
end
Collection.new(query, {:total_rows => doc['total_rows']}) do |collection|
doc['rows'].each do |doc|
collection.load(
query.fields.map do |property|
property.typecast(doc["value"][property.field.to_s])
end
)
end
end
end
end
end
end


So please do yourself a favor, investigate couchdb, it's nowhere near perfect at the moment, but you owe it to yourself to expand your horizons and really marvel at the speed at which it performs. You know that "lag" in ActiveRecord/DataMapper when you're operating on rows in MySQL/Postgres or even Oracle? Guess what? It's simply not there!

In fact on a server of mine which only has 256Mb of RAM, I can write a record, pull it, build up and tear down a merb thread and respond to the browser in less than a second. The age of the created_at I store in the document reads "0 seconds ago". Now, right now you're thinking well Bradford, that's not really impressive...I mean what about concurrency? This web stuff is all about concurrency! You're right! But I forgot to mention that I was running siege on the same server running 20 concurrent connections reading the same stuff I was putting in and it was still just as fast. On cheap, un-optimized hardware it performs incredibly fast. So please, check it out - the guys who work on this thing are wonderful (irc.freenode.net #couchdb) and it's really exciting to be watching this project grow!

Next up - how mowing the grass and application development could maybe one day have a lot in common. Aside from both being done electronically.

boy oh boy

So much stuff going on. New job, potential for my shares in an old job to be worth a great deal, summer-time, the Red Wings winning the Stanley Cup, mumbl! Hard to keep a guy like me blogging with all the stuff going on.

I'm not going to make this post about NOT blogging. It's more of an intro to what's to come. Not in a day or two, but within the next hour or so. My first topic is going to be of the freshest thing in my mind: the datamapper couchdb adapter. After that I have a phone call regarding some pretty big stuff. It could be my ticket towards some serious cash for helping guide a small start-up through the funding period. What a ride that has been over the last year and a half! Working for free (well, for stock options at least - we know what those can be worth).

So without any further ado. The real blogging item...

Thursday, May 15, 2008

Have you ever...

You buy a Twix bar from your favorite vending machine at work. You begin eating the first of the two bars, only to find yourself caught up in the gooey-caramel and cookie bliss.

You finish.

You reach for that second bar and WHAM!

You ate them so damn fast, you didn't even know you had already burned through them to relish it a second time.


Inside, we are all fat kids.

Thursday, May 1, 2008

Check this out...

I know I've written a lot about SliceHost in the last few weeks (they're pretty sweet). But I must hand it to Engine Yard...I recently wanted to check my uptime (I hadn't in quite a while as you will soon see) just to get a feel for the longevity of hosting a Rails app. So, without any further ado...

rex@ey00-s00289 ~ $ uptime
12:15:51 up 249 days, 9:24, 1 user, load average: 0.32, 2.00, 1.29


Not too shabby...

Sunday, April 27, 2008

thin, mongrel, evented mongrel and...Rodan?

I doubt I'll single-handedly spread the word about the caveats of using event-driven web servers (thin, evented mongrel), but I can at least give people Googling something that they may stumble upon while doing research. I want to keep it short and sweet.

If you're going to run an event-driven web server like thin or evented mongrel you have got to be careful about any requests that could run "long". File uploads, reports, and long atomic updates could leave your event chains blocked until they complete.

What this post is not...
1. It's not about Rodan, I'm just crazy and felt like putting that in the title; get over it.
2. It's not about why thin is better than mongrel or why mongrel is better than thin.

What this post is about weighing the options between these two great web servers so that you can make the right decision.

So, a couple things...
1. I use thin. And it is awesome. And I am lucky that I can use it on a site that has little "blips" for requests. So it hauls complete and utter ass.
2. I also use mongrel. And it too is awesome. And in this particular case, I DO have some long-running requests.

So what does it come down to - just educate yourself on the right tool for the right job. Don't jump ship on something just because it's the new, hip thing. I did just that when thin first started making ripples and then once site volume picked up, *poof* my requests sat in la-la land just waiting to be picked up. Anyone having flashbacks to when they were 13 waiting for their Mother to come pick them up from the mall?

I hate to jump around, but it's just how I write...I'm getting better[?]. Thin has support (oh and merb does too) to defer any long-running requests. So, as long as you're willing to configure thin and tell it which controler:action to defer to a threaded model you'll keep on servin' up those hoe-cakes just as fast as the surfer requests'em. WTF?

I should give the love here as to what triggered this post - the fine folks over at softies on rails had a quickie about thin and mongrel.
So please, weigh the differences - neither of these fantastic ruby-based servers should get any flame for under-achieving if you misuse them.

Related links...http://brainspl.at/articles/2008/04/18/deferred-requests-with-merb-ebb-and-thin
Strengthening the Ruby Ecosystem II: Merb

Saturday, April 26, 2008

osCommerce and PHP5

The splendid little e-commerce application that could[n't]: osCommerce is a bit quirky running on the "bleeding edge" of PHP[5]. Just as a quick heads up to you AND any would-be script-kiddies it requires that both of the following are enabled - just as a caution, anyone concerned about their sites well-being and knows anything about PHP configs should get a bucket:


register_globals = On
register_long_arrays = On


Everyone done dry-heaving? Good! I was absolutely beside myself when I saw what was required to run this application. It's been around for a few years now and it is shocking that they still operate with such disregard for online purchasing security AND performance.

So anyway, if you're seeing issues in your admin area to the tune of tep_href_link NONSSL or really anything related to tep_href_link and then some path (check your query string) it's likely you need to enable those bountiful long arrays.

*Insert drawn out sigh here*

Can't we all just shopify?!?!

Tuesday, April 22, 2008

Earth Day

Not a whole lot to blog about this morning, I did notice one thing. My commute to work today was noticeably shorter than normal, it appeared people actually car-pooled or found another means of transportation to get to work. I left significantly later in the morning rush traffic and just found it odd that parts of i40 were completely empty.

Or, it could just be a coincidence. Nothing more, nothing less...

That's all for now.

Sunday, April 20, 2008

So far so good; no, GREAT!

The other day I wrote about a hosting company that blew me away and I wasn't even a client of theirs. Well, I can now say that I'm the proud owner of two 256MB slices from SliceHost:

1. Gentoo running nginx and a soon-to-be-named rails application.
2. CentOS running a LAMP setup for a soon-to-be-name PHP application (actually, several).

First impressions were everything I had hoped they could have been. I'm about 3-4 years removed from any hardcore system administration. And the background I did have was with RedHat and FreeBSD. Thankfully the Linux community has gotten it right with package installers, making the halcyon days of system administration now uber!

Things learned...
I thought I'd run Feisty on the secondary slice...but, funk dat. I had always wanted to run Cent and heard great things about it and I can say, I really wish that I had installed it on my first slice. Gentoo on the other hand is fabulous for the lean and mean setup that I'm a fan of with web and database servers. Keep all the crap out (who really needs vi anyway?) and bring only what you need to survive.

Finally, I really need to emphasize just how deceptively fast a 256Mb slice is when you begin compiling and installing things like mysql, apache, ruby and imagemagick. What seems to have taken forever (even on my MacBook Pro) in the past, now, literally seemed to have taken a fraction of the time. I can't explain why exactly (grid computing for the win?) but quite frankly, I don't care (I really do - and if anyone can explain it via comments, go for it.) it's fast and I'm as happy as I thought I would be using these guys and their incredible service.

The two times I got stuck (on packages that seemed to exist yet weren't installing) a quick reference to the community pages on SliceHosts absolutely wonderful information repository got me back on track in no time.

Wednesday, April 16, 2008

Sliced Bread. Now, Sliced Hosting!

It slices it dices, it...well, no, it just hosts.

So here I am, not even a paying customer of this place and I'm already excited about using them based on some valid feedback and about 30 minutes of researching customers of theirs. For a project I'm consulting this seems to be an ideal move for what we need. I can add resources when need be, load-balance AND host multiple application platforms. I've got the control from the ground up without an insane price tag.

I mean for $20/month you have a pretty vast development machine which you can control the environment of. Now, granted I'm still trying to find the gap in the armor here, so I'm not going to say this is the greatest thing since sliced (sorry for the pun) bread but...when Engine Yard is floating around at $300/month (however, yes you basically have bought an IT-staff) this seems to be the best way to start out your idea and have a nice path for growth.

Anyway, props to Jason "my name is too easy to Google for" Bynum. for pointing me in their direction.

Wednesday, April 9, 2008

Tip #0 - Less[Everything] is more!

Ok, Ok, so I didn't make a post yesterday after I had pledged to keep up-to-date on this. I'm sure with a little brain-washing and conditioning I'll get there. Hopefully today, I make up for it...let's begin.

With so many mentions of "eating your own dog food" made in the recent weeks, I've taken it upon myself to keep the ball rolling. This post is going to be my segue (there will be a pause - don't be so literal) into my 5 tips for the contest currently taking place over at Railscasts.com.

So with all that said I think a great candidate for the "eats their own dogfood" award should go to lesseverything. These guys are (seemingly) successfully running a business on Ruby/Rails (literally). So we'll just jump to the first example: you're a contractor, you need to keep track of your billable revenue (invoices, etc...) but, you aren't exactly happy with the open-source products on the market. Well, like anyone who is in this for the science (and profit) you naturally would roll your own. But, and this is where I really feel many small companies hurt themselves, you make it for "you" (DHH) not for everyone. Well, let's take a step back here. You can either absorb the costs time/hosting/beer/etc that came along with building this accounting system OR you make it simple enough that anyone and their aunt Minnie could jump in and track invoices.

These guys have accomplished this. And it's essentially the way (I believe) any small business with the programming capabilities should operate. If you can build something which helps you immensely and is flexible enough to aid in helping others at a minimal cost to maintain - that's billable revenue my friend! Check this out for yourselves at lessaccounting.com. What's that you say? How do they keep the "www" off of their domain for branding purposes? Why it's simple - they'll tell you. So, just as a wrap-up real quick a little quote from their site:
Who is Less Accounting designed for?

We designed Less Accounting to meet our needs as small business owners. We tried to develop it flexible enough for personal use, but if you are a big business Less Accounting probably isn't for you.


I'd like to add a little something to that, if you're a bigger business - chances are your accounting system is overcomplicated anyways - overhaul and simplify. I know it's not the easiest thing to do what with all the personnel you've hired from your own family, but Uncle Joe will understand. He knows deep down in his heart that an Access database just won't cut it any longer and you're not prepared to take the plunge into a commercial accounting product. Give this a try...you'll thank me later.

LessEverything has also released upon humanity, what I had been hoping someone would do for a long time and that is a social networking platform on Rails. I've had somewhat limited exposure to it, mostly because I think the world is better off without more social networking sites, however, it's what everyone wants. And I use this saying a lot as a developer and it really holds true here:
I want to develop a lever for <project>, polish it a little and deploy it.


Even if you're not writing a social network, there are quite a few benefits this application takes care of for you right off the bat. Adding blogs to accounts, creating relationships between accounts, many things which apply to a host of scenarios could be accomplished with some minimal undertaking. In terms of performance, I haven't sieged anything I've made with it so far, I guess that's another post outside the scope of my 6 tips.

So to wrap up - Tip #0 is identify your own needs and if it's viable, don't be so one dimensional, allow others to benefit (for a low cost), keep it simple and above all just get it out there! It's income you weren't expecting to have and who knows, maybe its earnings out-perform your original projects.

Monday, April 7, 2008

Keeping it going

Every couple of months Seth Godin goes and pokes everyone in the eye with a nugget about why your blog is important. I've read it at least twice in the past and now a third time. It's marketing, I get it...but this time, I REALLY get it because I'm going to do it!

Yes, the wonderful rule of three worked on me, I can't tell why it took three tries to get the fire lit up under my ass to keep this thing up to date (not only for my own sanity but to maybe help someone else out there). I could post for a year and not have anything really useful to say, just clogging this toilet of information up with more ramblings and complaints. But, in all of that I do have a hidden agenda to try to get some useful things in amongst it.

Hopefully with the opportunity that's staring me square in the face at the moment, I can make something of it (and myself) and express my successes and failures along the way. If nothing else, I should be able to look back and see what went wrong and what went right. Maybe it will help someone else as well.

Rails Cast hits 11, err 100.

Pretty cool little contest going on over at railstcasts. There's even an 8Gb iPod touch up for grabs...I've got my tips picked out already, of course, the tricky part is going to be blogging about them.

I encourage anyone who knows anything about Rails to post something, hopefully this contest has a great turnout and the community as a whole will benefit from some of the minds that aren't exactly "mainstream" (The Dr. Nic's, Fowlers, etc...). Not that there's anything wrong with them, I just think the more insight into this framework the better.

Good luck trying to get my iPod!


MINE!

Sunday, March 16, 2008

Oh Noes, Your Business is Under Attack!

A somewhat interesting link came through my RSS reader this morning, it wasn't the well articulated basis of this gentleman's argument, nor was it the catchy title. What really made me think (and laugh) was the first post by a man named Will, who apparently works for the aforementioned company "waging war" upon Ruby/Rails.

I think it speaks volumes if you or the company you work for really has to dive into some random persons personal blog and begin defending yourself when all this guy is doing is giving an opinion. You're putting out a competing product (uh, sure!) and that's great...some will use it many will not. But it really makes me shake my head (knowing some people who work at Zend personally) when I see a Zend'er come out with the gloves up just clutching and grabbing for some traction on their products worth.

Really, if your product was worth a damn in the first place you'd likely have 9 other posts to this one touting the grace and power your product encapsulates. Instead, you put those gloves up because you know you have put out an inferior product and are trying not to be the last kid picked.

Finally, I must admit here that "Will" (IF that IS your REAL name...haha) does a good job of playing the diplomat, trying not to insult the blogger's intelligence and still keep him as a potential client (although, from the sounds of it, he's made his decision).

It's really great to have passion (see my last post) but sometimes you can't let that get in the way of what people outside your click think. Let them have it, if you're right, well then they'll all see in the end when you succeed.

Friday, March 14, 2008

Repeatability

It's been a long time and there is some really rather interesting things I should be blogging about (to me at least) but haven't. I've been really rather depressed lately for some reason or another (impending horrible recession, a shitty haircut, sleeplessness, the usual for a 27 year old male). Anyway, just like it had done for me in the past, seeing success in the Red Wings always seems to really cheer me up.

So last night Detroit goes down 3-2 heading into the 3rd period to the Dallas Stars. Ok, stick a fork in them already. They're done! Wait! Datsyuk scores 36(?) seconds into the period and then Samuelson pops one in about thirty seconds later. We're tied up, baby!!! Ok, now if we can just hold them off...they do. AND Filppula pops in an empty netter to make it 5-3. Detroit wins their (league leading I might add) 46th game, hits the 100 point plateau, they're now undefeated in March (as opposed to obliterated in the month of February) and now have clinched their 17th straight Stanley Cup playoff berth. Let me put that stat out there one more time for you.

The Detroit Red Wings have clinched their 17th consecutive Stanley Cup playoff berth


Are you kidding me? 17 years in a row Detroit heads into the playoffs. That's the longest streak in professional sports. Evar! Tell me this, name something you've done that's difficult, that you've competed for that you did 17 years in a row either by yourself or with a team. No luck, huh?

Ok, try 15 times...*crickets chirping*
10 times?
5 times?
2 times? Alright then...now think about what happened. Why couldn't you hit that 3rd time leading to a fourth or fifth? I'll pause while we go crack a beer open and sulk...we just weren't "in" it to win it. People lose passion, drive, patience, any number of things and the whole thing falls apart.

You really can tell a lot about an organization which many had written off at the beginning of the season to do poorly after last years showing (hell, they were even doubted to go far last season). The Ilitch family truly hires intelligent people with the same goals to run their club and it shows. Other teams could learn a lot from this model...as novel a concept as it may seem. It truly amazes me to see such a large organization have such stellar results year after year after...(continue as needed).

What always gets me about it still is that this is all done without all of the "flash" that many other clubs (certainly here in the South) resort to in order to get asses in the seats. Cheerleaders, give-aways, $2 beers until the 3rd period...these are gimmicks, we know this...they're admitted to. If you want to get people out to see your product...PUT TOGETHER A GREAT PRODUCT! Apple dealt with this for years, the Nashville Predators are scrambling to put themselves back together after a phenomenal year, in fact I'm sure if we sat and thought it through there are a number of organizations, both for and non-profit that fall into this funk. I believe Seth Godin considers this The Dip. I usually find it highly ironic how many of the things ol' Seth talks about are usually many of the things I deal with as a software developer, a husband, a team mate. But it made me really think back to my love affair with the Red Wings when he blogged about persistence.

Persistence, probably the one constant I've had described about myself from my parents, my wife, coaches, bosses, co-workers. Not in a bad way (heh, at least I don't think) but anyway, brings me back to my point of people no matter what the background, foreground, whatever have the same goal year in, year out and they are passionate, persistent and driven towards that goal it absolutely can be achieved.

What does that say about your organization? Your VP of <some division>, do you even know what that division is doing?

Incredible.

Sunday, February 17, 2008

Why Erlang will run "The Matrix"

Ok, so I had blogged and even somewhat complained about Erlang as an "every day" language. I'm here right now to say that I was dead wrong.

Erlang is simply amazing as I've gone from merely flipping through pages and references online and in books, to fiddling with gen_server off and on and to actually implementing a small facebook application based on Nick Gerakines' erlang_facebook module.

What I found funny about that last bit (the facebook app) is that after seeing an implementation of it in Ruby, it was actually easier to comprehend just what all was going on in the ERLANG version. Yes, I said it, the Erlang was easier to read.

Getting back on track...

After digging deep into getting my head around Erlang, something kind of crept up on me as I went along. Particularly when it came to message passing and "hot" code swapping...

You ready? Put on your tinfoil hat. Below is my list of reasons that "The Matrix" could become a reality and why it would be implemented in Erlang.

1. You ever wonder why we can only really "use" less than 10% of our brains? Ever wonder what that other 90-some percent is doing? That's right, passing messages to other "processes" and handling other distributed tasks.

2. When it comes to the hot code loading, this (I think) is a prime example of how a "Smith" would work. Think about it, "Oh, someone just ate the blue pill, better inject myself without taking this heap offline!". Bahng!

3. This blog post is currently fueled by Jameson 18 yr. Irish Whiskey.

4. Anything that scales just by adding cores (or nice, warm, fresh humans) and has been sitting somewhat idle in the wings for the last 20 years or so has GOT to be hiding something. I mean c'mon, most of the "love languages" (your Ruby, Python, PHP) look at a multi-core system and don't really know what to do with themselves.

5. (And this will be the last one as I'm losing momentum) The system can self-sustain for obscene periods of time, if one had the crazy "available systems" (people) one could die (literally and figuratively) and it really wouldn't matter, you'd have another waiting to take it's place AND you've got around 90% of it's processing power at your disposal.

This has been fun() (I can't help myself, I'm sorry) I hope some of you who come across this add some more to this list in the comments, I think there's a lot of cracks to be made.

Monday, February 11, 2008

'Wings BACK on a 3 game skid

Dan Cleary is out 6-8 weeks after taking a puck to the jaw and breaking it in two places (his jaw, not the puck). So there's an integral part of Detroit's 2nd-line scoring gone until, let's face it; April - hell, probably until the playoffs start.

Does this mean Kenny Holland is going to become more...I don't want to say desperate, but let's say...alert during the trade deadline? Looking over the list of names available out there, no one really looks to be a good fit for Cleary's "out of the way" scoring tactics. Finding someone with the knack that Cleary has (in my opinion) is like trying to find someone to replace Brett Hull. You really can't. The way these guys creep into the play completely unnoticed is simply incredible. Yes, it's true - I'm sure it is very easy to lose sight of whom to cover when Detroit is in your zone but c'mon, hasn't anyone gone and looked at tape? You'd be amazed how many goals Dan would score just slipping into the area around the face-off circles. If I had the time and the resources, I'd make you a little scatterplot to make you a believer.

I just hope the Red Wings can find someone to fill that void(?) on defense, I'm not too keen about Rob Blake for some reason, probably because he's 38 and is currently nursing a foot injury. Being a defenseman myself I know how often you take pucks to the feet - IT'S A LOT!!! So to pick up a huge name like that and be teetering on the brink of injury like he is...I can't see Ken Holland picking him up; I just can't. But Brad, didn't they sign Bertuzzi last year? Yes, they did - look how that turned out. He played in 8 games for Detroit last year: 2 goals, 2 assists and he was a +3. ZZZZZZzzzz...Don't come in here with that attitude. Detroit has chunks of guys like him in their stool. They're a dime a dozen on their farm team. I think for the 'Wings to have a great success in the trade arena, they should pick up a scorer: Mats Sundin is available! And finally, try to find at least a decent defenseman - maybe a stable, stay-at-home type of guy. If it works out with Blake, fantastic - I'd love to see Detroit bring a championship back home again, but boy does it not sit well with me.

Wednesday, February 6, 2008

Attachment Mania

I'm sitting face to face with a problem...

That problem being the ability to add an attachment to a "message" of sorts. Think of it as attaching a file to a forum post...except not everyone should have access to this file. And we need to do this with Ruby on Rails.

So what do we need?

Well, first and foremost I suggest we create a directory which sits outside the rails app itself. Say:
/var/myapp/attachments

Brad, why in the hell do you want to do that?


Simple, these are very private files which are going to be stored. No one should be able to just key-up the path in the browser to get to them. It will save me the lawsuit and bandwidth.

The second thing we need is to free up mongrel from serving up any static files. Let mongrel handle requests for rails but let nginx handle the static file response. This little nugget will allow us to do such a thing from rails in a clear, concise manner.

The last thing we need is to alter our capistrano script to not whipe our cache of attachments each time we deploy a new version of our rails application.

I'll post a response with my findings, if anyone has any suggestions...well, you know where to post.

Ask and ye shal receive

So as an update to my post earlier today (Wed), I've come to find out (via a conversation with Thin's main man Marc-André Cournoyer) that a PATCH to run Thin via Swiftiply is in the release queue as seen m'eow.

So, the instant the 0.7 release is out look for a whole new round of benchmarks to be produced. From what I was told, usage will reflect something like this:
this start --servers 3 --switiply --port 5000


Also, read the comments, you'll see some numbers which are being hacked away at on a work in progress. Only 22 days until 0.7 releases; I can't wait!

Application Throughput is for Closers Only

After reading a few informative posts and some statistics on application deployments and their performance with rails and the growing number of available proxies/webservers, I thought I'd take my shot at putting something fast together on a not-so beefy machine.

Read this article first and then this (Thin), this (Garbage Collection in Rails) and then this (Rails Routing).

Ok, ok, you probably didn't reall all of those...but at least read the first one. My goal is to try to bake all these together with an app that will actually do something outside of "hello, world" and see what type of performance I can juice out of an Ubuntu (Gibbon) box running on a 1.8Ghz AMD and 1.5Gb RAM. I have a fairly lightweight financial management application I've built on rails that is a perfect candidate for this type of experiment.

What's going to be involved? Nginx, Swiftiply, Thin, Postgresql and of course Rails. Now I'd like to mention here that currently (correct me if I'm wrong) there isn't a patch to run Thin via Swiftiply - I plan on changing that now that I don't have to huddle my family into a crawl space due to the 8,000 tornado warnings we had last night. It's like the world didn't want me to implement it!

Anyway, I'll post progress as I make it - if nothing else it's going to be a fun learning experience. Maybe some notoriety will come about from it if I can tie Thin into Swiftiply "un-shittily" (I'm sure someone will bitch about something).

That's all for now.

Saturday, February 2, 2008

I'm gonna make it after all...

Started my new job with a fine non-profit organization. I'll probably get to the second part of why I wasn't a good fit at my previous employer at some point. So much going on at the moment with side projects, wife taking back-to-back vacations, the economy taking a big dump on itself (we're all screwed by the way). It's been rather difficult trying to get some shut-eye the last two weeks, hopefully in the coming month I'll get some time to relax, dump my brain into this blog and finally share some dirty ruby and or rails goodness. Hell, with the installation of my new linux desktop (kudos to the Ubuntu guys for a great desktop implementation with gutsy gibbon) I really hope to get some time to tinker with merb, thin and nginx running from postgres with a datamapper ORM. But we'll cross that bridge when we come to it...

Back to the goat rodeo.

Friday, January 18, 2008

'Wings finally break 3 game skid.

Just to give anyone reading a heads-up, I'll post my hockey blurbs here and there, because I need to give my team a "shout out". Maybe I'll even convert you into a hockey fan along the way...

The Detroit Red Wings ended a three game losing streak Thursday night in a 3-2 shootout victory over the Vancouver Canucks. Dan Cleary posted the only 2 regulation goals for Detroit, with Henrik Zetterberg putting away the only shootout goal.

Dominik Hasek certainly shined on in this game stopping 26 of 28 shots and shutting the Canuck shooters down in the shootout.

In years past, I could probably (and given the time, I most likely will because I'm a nerd like that) graph two "slips" in the Red Wings seasonal performance. One in November and one in late January/early February, almost like clockwork. I'll hopefully put something together in the coming weeks with all the madness going on.

Cheers for the Red Wings!

Thursday, January 17, 2008

More on the pegs story later...

Today, I've found a really great "summarizing" podcast by the gentlemen over at Rails Envy. In the very first episode I listened to, I was introduced to a few really rather interesting gems and plugins in the works.

The first of which is Rack.
Rack provides a common API for connecting web frameworks, web servers and layers of software in between."
-- rack.rubyforge.org

From the little I've read on this, it's a great means for essentially creating your own frameworks in Ruby and the web server of your choice.  Who's feeling entrepreneurial?  Maybe this will be the start of more ruby web-frameworks.   Mmm, probably not.  In my humble opinion I really believe having Rails and Merb is going to be plenty.  My theory on the two becoming the alpha-dogs of ruby web-frameworks is as follows:

Rails will become the entry-level framework where developers new to the "scene" will rails <project> there way towards a more blissful means of web development.  After a while, maybe some of them will want to take the framework in a new direction, get upset with ActiveRecord or simply become filled with rage when many of their patches to Rails are denied.  Where will they go?  What other option is there?  At the moment; NONE really.

Enter Merb.  Once the new kid on the block has matured into a full version and someone steps out of the woodwork stating "hey, x-app I wrote runs Merb and here are some damn-fine performance numbers to back it up", I'm sure the march out of the rails community will slowly but surely begin.  Merb could quite possibly end up being the "hardcore" framework for Ruby programmers and ultimately get the nod as the "Enterprise Ruby" framework.

So what evidence is there to back up such a claim, Bradford?  Well, let's take a look at Engine Yard.  They're positioned right now with a huge capital investment (US$3.5m) and are now able to bring a full (and paid-for) Rubinius team.  On top of which there has been talk of them open sourcing their hosting platform (whose name I can't recall at the moment).  They already employ (and I believe he owns part of EY) the core developer of Merb (Ezra Zygmuntowicz), so what's to stop them from deploying an end-to-end, SUPPORTED technology stack leveraged on these technologies?  Absolutely nothing, that's what!

Only time will tell, but with the recipe for success that Rails personifies for other framework creators - hopefully, I'm right.

Wednesday, January 2, 2008

Square pegs in round holes Pt. 1

Is everyone here? No? Fuck it, I'm going anyway...


I'm currently employed at a medical laboratory that was bought out a few months ago. In the beginning there were a few changes that needed to be made to the data-model (expected things). We (the people in "IT") were told that standard operating procedure at this "new" company was that everything server/application related would get swept into the corporate fruitcake and moved to North Carolina.

It was then apparent to these worker-bee's of the new corporate entity that this did not sit well with our group (which consists of me; a software developer, a network administrator and a help-desk technician). So stories were being floated down from people who, in the corporate hierarchy, are nothing more than someone's gopher about how we were unique and how everything would stay as is. Jobs weren't in jeopardy and life was good - not a care in the world. This same type of story was handed to other departments, sans servers of course.

Various meetings were held telling everyone to sit tight while things were jumbled about - you can insert your favorite corporate buzzwords here. I'm sure if you pictured it in your head you could just imagine this meeting. A southern gentleman who resembled Cotton Hill from King of the Hill standing in front of 80 people, fielding questions ever so diplomatically. The nervousness and longevity of his answers went completely unnoticed by my co-workers who resembled in my eyes a bunch of dogs at obedience class. *You can stop nodding now*

No one thought for a second to have a plan. They let these people waltz in and rip the rug right out from underneath them. Sad.

There's part of me that has some empathy for them but to take such a gamble on you and your families well-being based on some slick-talkin' stranger is simply ridiculous.

ESPN Radio and their advertisers

I have XM Radio and have had it for a number of years. I love it. I also love ESPN. So naturally having the two together is great. What's not so great is the advertising that ESPN hocks on it's xm channel (140). It's the same stuff every break: "Male enhancement in 3-5 seconds?!" or "Tired of seeing everyone around you living the good life?". You'd think a media juggernaut like ESPN could pull in some better schwag to push into our ears than this garbage.

I'm not sure how much longer I can take it; I mean you always have the ability to change the dial...but I'm American, that's a lot of work.

Thinking back on it - I think a solid work around would be the ability (like you have on a directv remote) to hit a "previous" button so that hopping between channels is easier.

This was a shitty rant...but what do I care - it's just a place for me to let the trash out of my head. It will be (I'm guessing) a good six months before anyone even see's this stuff.

Hi, my name is...

I know what you're thinking...This is just what the world needs - another "I think I'm witty and sarcastic so that must mean I'm funny" software developer blog. You're god damn right it does!

Hopefully I make something of this.