Skip to content
Browse files

First draft of ControlTower announcement

git-svn-id: http://svn.macosforge.org/repository/ruby/MacRubyWebsite/trunk@4515 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information...
1 parent f072a8b commit 1b4666981fabb0420aa09f4a987ee00e9bbb58ff @jballanc jballanc committed Sep 14, 2010
View
74 content/blog/2010/09/16/announcing-control-tower.txt
@@ -0,0 +1,74 @@
+---
+title: ControlTower
+created_at: 2010-09-16 11:57:25.075413 -04:00
+blog_post: true
+layout: blog_entry
+author: Joshua Ballanco
+filter:
+ - erb
+ - textile
+---
+<% @page[:excerpt] = capture_erb do %>
+We are pleased to announce the first version of ControlTower, a Rack-based web application server for Ruby. ControlTower can already run basic rack and Sinatra apps, but there are still a lot of features to add.
+<% end %>
+
+h3. "It's called ControlTower!":http://www.youtube.com/watch?v=QbdXt2K27NU
+
+Way back in the announcement for MacRuby 0.5, we cryptically mentioned that we had gotten a web server to run a basic Sinatra app. While that statement was true, the server we had wasn't even really alpha worthy. At that point, it was more about proof of concept. If you have been watching the subversion repository you might have noticed that a new top-level project appeared about 4 months ago. If you're subscribed to the mailing list, you probably have even seen a bit of discussion take place about this project, and yet we still weren't quite ready to announce it to the world. Well, that changes today!
+
+Today we are officially announcing version 0.1 of ControlTower, the Rack-based web app server for MacRuby.
+
+If you're a casual follower of MacRuby, here is what you need to know in a nut-shell:
+
+<div class="control-tower">
+* ControlTower is a Rack-based web application server, written from the ground for MacRuby
+* It takes advantage of MacRuby's ability to mix-n-match Cocoa APIs with Ruby, so it will (for the forseable future) _only_ run on MacRuby
+* It can be used on its own or with a reverse proxy to serve any Rack-based web app whose libraries are supported by MacRuby (i.e. Sinatra, but not Rails...yet)
+* We are also interested in other non-traditional ways an embeddable Ruby web app server might be useful for native app development
+* It's small, it's light weight, and it's reasonably fast
+<div>
+<br />
+
+h3. How do I use it?
+
+To get ControlTower, you can checkout the source using subversion at @http://svn.macosforge.org/repository/ruby/ControlTower/tags/0.1@. Once you have the source you can use rake to build the gem (requires developer tools) and macgem to install like so:
+
+<pre class="commands">
+$ rake gem
+$ sudo macgem install pkg/control_tower-0.1-universal-darwin-10.gem
+</pre>
+
+There are two basic ways to interact with a Rack-based web server: create a rack-up file, or use a Rack::Handler in your code. Currently, both of these mechanisms work with ControlTower. Using a rack-up file is probably the simplest and most straight forward way to get up and running, and we've included a number of sample rack-up files in the "sample" directory of the repository. Once you have built and installed the ControlTower gem, you can use the @control_tower@ command to run any rack-up config:
+
+<pre class="commands">
+$ control_tower -R sample/simple_hello.ru
+You are cleared for take-off!
+Listening on 0.0.0.0:3000
+</pre>
+
+Alternatively, if you would like to start up the ControlTower server from within your code, you can use the @Rack::Handler::ControlTower@ class included with the ControlTower gem. This class has a single @run@ method that takes a rack "app" object and an options hash as its arguments. The options hash can be used to set the same server parameters as the command line tool. So, for example you can do:
+
+<%- coderay :lang => 'ruby' do -%>
+app = MyApp.new
+Rack::Handle::ControlTower.run(app, {:port => 80,
+ :host => 'myserver.com',
+ :concurrent => true })
+<%- end -%>
+
+Though, keep in mind that this method will block untill the server stops running, so if you want to do something else while the server is running you should put this code in a thread.
+<br />
+
+h3. What's in a Web Server?
+
+In general, all Ruby web app servers consist of the same three components: a socket manager, a header parser, and a request handler. Incoming requests initially encounter the socket manager which begins receiving data from the incoming connection. This data is then fed to the header parser until all of the headers have been received. These headers, along with any request body data (e.g. a form being POSTed), are then passed on to the request handler. The request handler makes any necessary changes on the server, gathers any data needed for a reply, and then sends that reply back to the socket manager which will send the reply back to the client.
+
+Ever since Mongrel, just about every Ruby web app server has used Zed Shaw's Ragel-based HTTP parser to parse headers on incoming requests, and ControlTower does too. Since the appearance of Rack, servers can count on an "app" object provided by a web app framework to handle the requests, in accordance with the Rack spec, and being a Rack-based server ControlTower relies on this as well. That leaves the socket manager as the only one of the three components that will differ considerably between servers. In the case of Thin the socket manager is an EventMachine event loop. In the case of Unicorn sockets are managed using a prefork mechanism. In ControlTower, we do our socket management with Grand Central Dispatch.
+
+The way this works is that each new incoming request is asynchronously dispatched to a GCD queue to be parsed and handled. In the default case, this queue is a serial queue, so requests are handled first-in first-out. By placing incoming requests onto a queue immediately, the server is quickly able to accept the next incoming request. If the @-c@ switch is used with the control_tower command or the @:concurrent@ key is set to true in the handler's options hash, ControlTower will use a concurrent GCD queue in place of the serial one. This means that ControlTower can handle multiple requests concurrently inside a single process; up to 75 at once on an 8-core MacPro (compared to 20 simultaneous requests per Thin process in threaded mode). If you want to give concurrent mode a try, just make sure that your web app and database layer are truly thread-safe, and not just green-thread-safe.
+<br />
+
+h3. How can I help?
+
+Glad you asked! ControlTower is still a relatively young project, so there is still lots to do. Right now, it is a small, robust server capable of handling moderate loads, but it doesn't have as many features as other Rack-based servers like Thin or Unicorn. Most notably, we do not yet support keep-alive. Other wish-list items include the addition of Rack adapters for the various common Ruby web app frameworks, support for unix domain sockets, and the ability to do Web Sockets.
+
+Of course, you don't have to be heavy into server development to lend a hand. We could use a lot of help just with testing and documentation (both of which are lacking currently). Perhaps the simplest and most important thing you can do to help is to try it out and send in your bug reports and feature requests. We started building ControlTower for our own purposes, but now we're ready to share it with the community and see where you take it.
View
22 content/blog/2010/09/index.txt
@@ -0,0 +1,22 @@
+---
+title: 08
+created_at: 2010-08-09 00:57:24.985737 -04:00
+filter: erb
+dirty: true
+---
+<h2><%= h(@page.title) %></h2>
+
+<%
+ articles = @pages.find(:all, :in_directory => @page.dir, :recursive => true,
+ :sort_by => "created_at", :reverse => true, :blog_post => true)
+ articles.delete(@page)
+ paginate(articles, 10) do |page|
+-%>
+<div class="article">
+ <h1><%= link_to_page(page) %><span class="date">(<%= page.created_at.strftime('%Y-%m-%d') %>)</span></h1>
+
+ <div class="body">
+ <%= render(page) %>
+ </div>
+</div>
+<% end -%>
View
10 content/css/master.css
@@ -5,6 +5,16 @@ body {
color: #333;
}
+em {
+ font-style: italic;
+}
+
+li {
+ list-style-position: outside;
+ list-style-type: disc;
+ margin-left: 32px;
+}
+
#logo {
width=300px;
}
View
21 content/documentation/gcd.txt
@@ -26,7 +26,7 @@ h3. Queues: The What and the Why
Queues, represented in MacRuby by the @Dispatch::Queue@ class, are data structures that execute tasks. Under the hood, GCD maintains a pool of POSIX threads to which queues dispatch their tasks; GCD will grow and shrink this pool dynamically and distribute its threads evenly among available processors.
Queues can execute their tasks either concurrently or sequentially. All queues begin executing tasks in the order in which they were received, but concurrent queues can run many tasks at once, whereas serial queues wait for one to complete before starting the next. GCD provides three singleton concurrent queues and allows the creation any number of serial queues. Performing work on a queue is extremely easy:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# Create a new serial queue.
queue = Dispatch::Queue.new('org.macruby.examples.gcd')
# Synchronously dispatch some work to it.
@@ -41,7 +41,7 @@ queue.async do
sleep 1.0
puts 'Done!'
end
-</pre>
+<%- end -%>
If you paste this code into a running @macirb@ prompt, you’ll see that the queue blocks until the task specified in the @#sync@ block is finished, while task we specified in the block we passed to the @#async@ method is executed asynchronously in the background.
@@ -51,7 +51,7 @@ h3. A Real-Life Use Case: Synchronization
Ensuring that methods and data are accessed by one and only one thread at a time is a common problem in software development today. However, unlike languages such as Java and Objective-C, Ruby has no built-in language support for synchronization, relying instead on the Mutex and Monitor classes. However, GCD introduces another elegant idiom for synchronization that is higher-level than Mutex and significantly simpler than Monitor:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
class MissileLauncher
def initialize
@queue = Dispatch::Queue.new('org.macruby.synchronizer')
@@ -65,7 +65,7 @@ class MissileLauncher
end
end
end
-</pre>
+<%- end -%>
h3. Synchronization with Groups
@@ -75,7 +75,7 @@ h3. Groups in Action: Futures
Languages like "Io":http://www.iolanguage.com/ and "Oz":http://www.mozart-oz.org/ provide the notion of "futures":http://en.wikipedia.org/wiki/Futures_and_promises: proxy objects that perform expensive computations in the background. By using GCD queues to execute the tasks and groups to synchronize the tasks’ execution, we have a simple, concise and reliable implementation of futures in MacRuby:
-<pre class="commands">
+<%- coderay :laungage => 'ruby' do -%>
include Dispatch
class Future
def initialize(&block)
@@ -93,24 +93,25 @@ class Future
@value
end
end
-</pre>
+<%- end -%>
+
Now it’s easy to schedule long-running tasks in the background:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
some_result = Future.new do
p 'Engaging delayed computation!'
sleep 2.5
:done # Your result would go here.
end
-</pre>
+<%- end -%>
Accessing the value is as easy as calling @some_result.value@.
h3. Parallelization and Synchronization
Now let’s see an example of how easy it is to parallelize your code with the GCD’s groups and concurrent queues:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
class Array
def parallel_map(&block)
result = []
@@ -131,7 +132,7 @@ class Array
result
end
end
-</pre>
+<%- end -%>
This example uses the queue accessed through @Dispatch::Queue.concurrent@ to speed up @Array#map@ by spreading out the total work across the system’s available processors. From a two-core Macbook Air to a 16-core Mac Pro, GCD executes the tasks dispatched on the concurrent queue across all available processors. With fewer than a dozen lines of code, we’ve parallelized @#map@ and avoided race conditions by using groups to synchronize.
View
72 content/documentation/rubycocoa-to-macruby.txt
@@ -20,19 +20,19 @@ h3. Importing Frameworks
To import a framework in RubyCocoa, you use a combination of Ruby's @require@ method and RubyCocoa's @require_framework@ addition:
-<pre class="commands">
+<%- coderay :languag => 'ruby' do -%>
# RubyCocoa code
require 'osx/cocoa'
OSX.require_framework('CoreData')
-</pre>
+<%- end -%>
MacRuby unifies these methods with the @framework@ method added to the @Kernel@ module:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# MacRuby code
framework 'Cocoa'
framework 'CoreData'
-</pre>
+<%- end -%>
h3. Namespaces
@@ -42,19 +42,19 @@ h3. Inheritance
Because RubyCocoa is not implemented on top of Objective-C, it requires objects passed to Objective-C APIs to inherit from @NSObject@:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# RubyCocoa code
class MyClass < NSObject
end
-</pre>
+<%- end -%>
In MacRuby, the Objective-C @NSObject@ and Ruby @Object@ classes are identical; therefore, because Ruby classes implicitly inherit from @Object@, all objects in MacRuby are valid @NSObjects@. Explicit inheritance is therefore no longer required:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# MacRuby code
class MyClass
end
-</pre>
+<%- end -%>
h3. Class Compatibility
@@ -81,94 +81,94 @@ $ macirb --simple-prompt
Because Cocoa code often requires working with C struct types, MacRuby allows you to pass in an @Array@ containing the required data where a C struct would normally be expected. Some examples follow:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# MacRuby code
window.frame = NSMakeRect(0, 0, 100, 200) # Using the NSMakeRect function
window.frame = NSRect.new(NSPoint.new(0, 0), # Using the MacRuby NSRect class
NSSize.new(100, 200))
window.frame = [0, 0, 100, 200] # Using a array in flat style
window.frame = [[0, 0], [100, 200]] # Using an array [point, size] style
-</pre>
+<%- end -%>
Please note that MacRuby's @Range@, @Set@, and @Enumerator@ classes are *not* bridged to their Cocoa or CoreFoundation equivalents.
h3. Keyword Arguments
Objective-C's interleaved-keyword syntax is not compatible with traditional Ruby syntax. To be able to call Cocoa API's from RubyCocoa, you use the "underscore hack", which translates Ruby-style function calls into ObjC calls by joining the selector's components together with underscores:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# RubyCocoa code
NSFileManager.defaultManager.createFileAtPath_contents_attributes(p, c, a)
-</pre>
+<%- end -%>
In order to make the use of Objective-C methods from MacRuby as natural as possible, the MacRuby team extended standard Ruby syntax to support Objective-C style interleaved arguments:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# MacRuby code
NSFileManager.defaultManager.createFileAtPath(p, contents:c, attributes:a)
-</pre>
+<%- end -%>
This is the best way to call Objective-C methods; code written using the underscore hack or RubyCocoa's @objc_send@ function will fail to run under MacRuby.
MacRuby allows you to use this syntax in your own method declarations, too:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# MacRuby code
def saveWorld(planet, fromVillain: badguy, withHero:superhero)
superhero.fight(badguy)
planet.thank(superhero)
end
-</pre>
+<%- end -%>
However, it's important to note that this syntax is unique to MacRuby; code written in that uses this syntax will fail to run on any other implementation of Ruby.
h3. Interface Builder
MacRuby's integration with Interface Builder is significantly cleaner than RubyCocoa's. Previously, declaring an instance variable that also functioned as an Interface Builder outlet required two declarations, one to declare Ruby-style accessors and another to declare a key-value compliant accessor:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# RubyCocoa code
class MyView < NSView
attr_accessor :pdfView
ib_outlet :pdfView
end
-</pre>
+<%- end -%>
MacRuby extends the semantics of @attr_accessor@ and @attr_writer@ to provide a key-value compliant setter method that Interface Builder will recognize. As such, all references to the @ib_outlet@ method can be removed:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# MacRuby code
class MyView < NSView
attr_accessor :pdfView
end
-</pre>
+<%- end -%>
Another significant improvement comes in the form of transparent support for Interface Builder actions. RubyCocoa required that IB actions be declared with the @ib_action@ helper method:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# RubyCocoa code
class MyController < NSObject
ib_action(:firstPage) do |sender|
currentPDFView.setPageNumber(1)
end
end
-</pre>
+<%- end -%>
Because of MacRuby's tight integration with the Objective-C runtime, there is no special syntax required to declare an IB action: any Ruby method can serve as an IB action, though it must have a @sender@ parameter like in Objective-C:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# MacRuby code
class MyController
def firstPage(sender)
currentPDFView.pageNumber = 1
end
end
-</pre>
+<%- end -%>
h3. super()
In RubyCocoa, the @super()@ function did not work correctly if the superclass method being called was implemented in Objective-C. A further extension to the underscore hack became necessary:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# RubyCocoa code
class MyClass < NSObject
def init
@@ -177,11 +177,11 @@ class MyClass < NSObject
self # Always return self from init!
end
end
-</pre>
+<%- end -%>
MacRuby rectifies this inconsistency, allowing the @super()@ function to call both Ruby and Objective-C methods:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# MacRuby code
class MyClass
def init
@@ -190,7 +190,7 @@ class MyClass
self # Always return self from init!
end
end
-</pre>
+<%- end -%>
h3. Exception Handling
@@ -200,38 +200,38 @@ h3. Other Syntactic Extensions
The MacRuby team has ported the syntactic extensions present in RubyCocoa for cases when Objective-C idioms differ with Ruby idioms, such as in the case of mutator methods and boolean accessor methods:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
layer.setPosition([100, 100]) # Objective-C style
layer.position = [100, 100] # Ruby style; calls the same method the Objective-C one does
layer.isHidden # Objective-C style
layer.hidden? # Ruby allows the '?' character in method names
-</pre>
+<%- end -%>
MacRuby provides additional syntax for the commonly-used @objectForKey:@ and @setObject:forKey:@ methods:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
obj.objectForKey('data') # Objective-C style
obj['data'] # Ruby style
obj.setObject('mystery', forKey: 'data') # Objective-C style
obj['data'] = 'mystery' # Ruby style
-</pre>
+<%- end -%>
h3. Property Lists
RubyCocoa added extensions for easy manipulation of property lists:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# RubyCocoa code
array_data = ['a', 'b', 'c'].to_plist
OSX.load_plist(array_data)
-</pre>
+<%- end -%>
MacRuby ports these extensions, adding @load_plist@ to the @Kernel@ module and @to_plist@ to @Object@:
-<pre class="commands">
+<%- coderay :language => 'ruby' do -%>
# MacRuby code
array_data = ['a', 'b', 'c'].to_plist
load_plist(array_data)
-</pre>
+<%- end -%>
</div>

0 comments on commit 1b46669

Please sign in to comment.
Something went wrong with that request. Please try again.