burke/zeus — pull request #361 by antifuchs (2013-06-06 21:07:56+00:00)
Title: Remove recursion in favor of iteration for lower backtrace depth

Change the structure of Zeus.go to use throw/catch and iteration
instead of recursive calls to go in order to boot slaves and
commands. This changes the number of backtrace frames occupied by Zeus
to be constant, instead of scaling linear with the depth of the slave
launching a command.

The result is a backtrace that looks like:

```
ZeroDivisionError: divided by 0 from (irb):1:in `/'
from (irb):1
from /Users/asf/foo/dev/lib/dev_plan.rb:70:in `block in '
from /Users/asf/foo/dev/lib/dev_plan.rb:12:in `instance_eval'
from /Users/asf/foo/dev/lib/dev_plan.rb:12:in `block in command'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:137:in `block in command'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace.rb:130:in `call'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace.rb:130:in `block (2 levels) in wrap'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace/class_methods.rb:76:in `call'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace/class_methods.rb:76:in `enter'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace.rb:117:in `enter'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace.rb:129:in `block in wrap'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace/core_ext.rb:59:in `fork'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace/core_ext.rb:59:in `block (2 levels) in in_lspace'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:124:in `command'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:96:in `block in go'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:39:in `catch'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:39:in `go'
```

Instead of:

```
ZeroDivisionError: divided by 0
from (irb):1:in `/'
from (irb):1
from /Users/asf/foo/dev/lib/dev_plan.rb:70:in `block in '
from /Users/asf/foo/pay-server/dev/lib/dev_plan.rb:12:in `instance_eval'
from /Users/asf/foo/dev/lib/dev_plan.rb:12:in `block in command'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:126:in `block in command'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace.rb:130:in `call'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace.rb:130:in `block (2 levels) in wrap'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace/class_methods.rb:76:in `call'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace/class_methods.rb:76:in `enter'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace.rb:117:in `enter'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace.rb:129:in `block in wrap'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace/core_ext.rb:59:in `fork'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/lspace-0.10/lib/lspace/core_ext.rb:59:in `block (2 levels) in in_lspace'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:113:in `command'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:82:in `block (4 levels) in go'
... 25 levels...
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:75:in `each'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:75:in `block (2 levels) in go'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:64:in `loop'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:64:in `block in go'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:38:in `catch'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:38:in `go'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:80:in `block (4 levels) in go'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:80:in `fork'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:80:in `block (3 levels) in go'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:75:in `each'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:75:in `block (2 levels) in go'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:64:in `loop'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:64:in `block in go'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:38:in `catch'
from /Users/asf/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/zeus-0.13.3.0.115/lib/zeus.rb:38:in `go'
```

(Note the `...25 levels...`)

The main benefit of this is aesthetic, and not on the code side (as you can well see in the diff). However, I think it might be worthwhile to not have Zeus cause up to dozens of lines of backtrace material that ends up being useless information in case something goes wrong.

On the other hand, I think a backtrace with O(depth of the command's slave) frames wouldn't be pretty cool, if it could provide some more information on the plan that got you there (which the current zeus backtraces don't do either).

Basically, I'm torn on whether this is the right way to go, but am pretty sure something should be done (-: