Zero Downtime Deploys with Migrations »
Created at: 13.12.2011 22:30, source: Engine Yard Blog, tagged: ruby Technology
I gave a talk at RubyConf that went over how we automate our development and deploy process here at Engine Yard. The part of the talk that got the most questions and spawned the most discussion was about the way we do deploy with zero downtime, even with migrations. Here is a bit more detail on the process.
A Caveat
At Engine Yard, we almost exclusively use DataMapper for our ORM. This means that we specify all of the properties for our models in the model class, there is no database introspection to generate accessors for the properties. I have not tried this technique with ActiveRecord but the concepts will be the same.
Example: Adding a column
This is the simplest example, but also the most common migration that we do.
First, before merging any part of the feature to master that needs a new column, create a migration on master that adds the column.
migration 1, :"add published_at to posts" do
up do
modify_table :posts do
add_column :published_at, Time
end
end
end
Then we simply test the migration, and ship it all the way to production. Now the column is created in the database—ready for us to use when we merge the code that requires the column.
This also allows us to always run migrations last in the deploy, after we have restarted the app servers. This means that new code is running on the app servers earlier in the deploy process.
Renaming a Column
Adding a column is pretty straightforward but there are some migrations that are much trickier to do with zero downtime.
Lets say you have a Post model, and you want to rename the body field to content.
We have a solution for this as well.
Step 1: Add the new column
Same as above, write and deploy the migration to add the new column to the database.
migration 1, :"add content to posts" do
up do
modify_table :posts do
add_column :content, Text
end
end
end
Step 2: Make the code aware of both columns
We usually do this by writing the code as if we were solely using the new column, then having a few accessors and hooks on the model to sync the data over.
class Post
def content
update_content
attribute_get(:content)
end
def content=(new_content)
self.body = new_content
attribute_set(:content, new_content)
end
before :save, :update_content
def update_content
self.content = body
end
end
Step 3: Migrate the data
Now that your code is handling the migration of data as it runs, we need to migrate all columns to the new schema.
We can either use a migration for this or just write and run a rake task to copy all data from the body column to the content column.
Once this step is complete, the content column should be canonical and remain that way due to the way the code is written.
Step 4: Remove the temporary syncing code
We can now remove all references to the body column, including the code that syncs the data between the two columns.
At this point, we are almost done. The code is all updated not to use the old column; it only remains in the database.
Step 5: Drop the column
Finally, all we need to do is write a migration to drop the column from the database and deploy it to production. The code does not reference the column, so we can deploy it at our leisure.
YMMV
This technique has worked very well for us at Engine Yard. It can be more complex, but overall it leads to less friction in the deploy process. When you know that there is no downtime needed for any step of your work, you can simply write code and ship it to production when you're ready, rather than being blocked on waiting for a maintenance window.
Adding a column to the database is by far the most common kind of migration that we do. And using this technique still makes that very simple. Over all it has not added a significant amount of overhead to getting things done, and the lack of friction is a huge win.
Doesn't always work
All this said, there are a small number of cases when you really cannot perform this technique. These are cases where the migration will take a long time and lock tables or cause heavy load on the database server. In the past year, these kinds of migrations have been the only ones that we have had to take downtime for. The most common manifestation was adding an index on a very large table. But if your database is heavily loaded, many ALTER TABLE statements may take an unacceptably long time.
more »
What Are Events, Why Might You Care, and How Can EventMachine Help? »
Created at: 08.12.2011 22:13, source: Engine Yard Blog, tagged: ruby Technology
You have likely heard of event based/driven programming, which you may also see referred to as "evented" programming. It has been around and in use for a long time, but it is seeing a growing swell of interest in recent years. Perl has had POE for years. Likewise, Python has had Twisted for quite a few years. Graphics toolkits such as GTK use event loops to respond to user interface events. Javascript has been getting a lot of attention lately because of the Node.js event driven framework. Ruby has had the EventMachine library since 2006, with other event driven programming libraries such as Rev and Coolio being released since then.
Despite this relative wealth of libraries, and growing interest in the event driven programming paradigm, this realm of software design is still shrouded in mystery and unknowns for many developers. People who are new to it tend to misunderstand it, often assuming magic that does not exist, or simply misunderstanding what "event driven" really means. Even developers with experience writing event based software using one of the previously mentioned libraries are often fuzzy on the details. They may assume that their library of choice represents the "real" world of event based programming. Or simply because their use cases only take them to a few familiar neighborhoods of evented programming, they may retain some of that newbie fog for other parts.
This series of articles is going to attempt to rectify some of those situations. The precise course of the articles will be determined as they progress, but for today, let's start at the beginning. Event Based/Driven Programming. It'a hot. All the cool kids are doing it. It's got EVENTS! Raise your hand if you truly know what that means, or why you should actually care.
Event–noun
- something that happens or is regarded as happening; an occurrence, especially one of some importance.
- the outcome, issue, or result of anything: The venture had no successful event.
- something that occurs in a certain place during a particular interval of time.
That quote was courtesy of http://dictionary.reference.com/browse/event
Applying that definition to the world of software is a pretty direct thing, as it turns out. Event based programming is nothing more than letting the flow of the program be determined by some set of events. Hardware interrupts are an example of a ubiquitous source of events. On Unix systems, signals and the signal handlers that deal with them are a type of event based programming, as well. A typical pattern for windowing systems is to operate with an event based model; the software can't know when one is going to click on a menu item, or a dialog button, so the software instead runs in a loop, waiting for some event to happen. When an event occurs, the software calls into another piece of code to handle that event.
At its simplest, that general pattern of the system being divided into a dyad consisting of one part that detects or selects events, with a second part that handles them, is what event based programming is actually about. If you have been programming for any length of time, the odds are pretty good that at least in some small ways, you have engaged in event driven programming even if you didn't realize it.
If you go back and look at any of those libraries that I mentioned at the top of the articles, you will notice a trend. Each of those libraries is an event driven programming library, but there is a fair amount of variation across them. This is because event driven is a vague label, encompassing numerous patterns and feature sets. One of the most common of these patterns is the Reactor pattern.
The Reactor pattern describes a system that handles asynchronous events, but that does so with synchronous event callbacks. There are several ruby implementations of this pattern, including the most common library for event based programming in Ruby today, EventMachine. A reactor is good at handling many concurrent streams of incoming our outgoing IO, but because the callbacks are invoked synchronously, callback handling can severely impact the concurrency, or apparent concurrency, of a reactor implementation. Nonetheless, reactors are easy to implement, and with a little care, can be used to drive high performance IO on a single threaded, single process application.
As I mentioned, EventMachine is a Reactor implementation. And it is perfectly possible to install EventMachine, look at a few documents and a few examples, and start writing your own event based software that uses it without really having a good idea of how the machine is running under the hood. But there is value in understanding what a Reactor actually is, so that you better understand what a library like EventMachine is doing for you. Ruby gives us a lot of tools that make it reasonably easy to write a very simple pure ruby reactor implementation, so let's do that. It should make this topic much clearer when you see how simple it actually is. All of the code shown below can also be found on GitHub at https://github.com/engineyard/khaines_blog_code_examples/tree/master/what_are_events. All of these pure ruby examples should work on every Ruby implementation. I have tried it on MRI 1.8.7_p352 and 1.9.3_p0, as well as JRuby 1.6.5 and Rubinius 2.0.0dev, though I did not extensively test on anything other than MRI 1.9.3, so quirks may exist.
For our pure ruby reactor, we want only a few features.
- Unlike EventMachine, which also includes substantial support for managing creations of network connections, servers, and other more sophisticated activities, our reactor is going to limit itself to only being a tool for handling events. Therefor, all that it needs is a way to attach and detach IO objects to/from the reactor. We'll use the built in ruby mechanisms for everything else.
- Ruby has the select() call available to it on all platforms, so our reactor will be designed to use it. The select() call returns readable handles, writeable handles, and errors from a set of filehandles to operate on, so those three events (
:read, :write, :error) will likewise be all that our reactor handles. - Timers are very useful, and are pretty easy to implement in a reactor, so it would be nice to have a timer implementation.
Even though it is not strictly necessary for a reactor implementation, I will start our implementation with the timer functionality. Timers are events which are time based. Their callback is triggered at some point after a given time threshold is reached. The difficulty with timers is in choosing a mechanism for storing them such that the ones which need to be triggered can be easily and efficiently detected. Time, however, is a sortable attribute, and there are some data structures that are great for storing sortable data where that sorted data order is important. There are tree based data structures which are very efficient at maintaining this sort of data. Ruby doesn't have one of those as a native data type, so for this example, I will just fake it. If I were writing a serious implementation, I would have to do more work to provide an efficient data structure for timer data. The following data structure is built on top of a hash, makes no claims to be efficient, and provides the bare minimum API for our reactor to have the tool that it needs to implement timers.
class SimpleReactor
class TimerMap < Hash
def []=(k,v)
super
@sorted_keys = keys.sort
v
end
def delete k
r = super
@sorted_keys = keys.sort
r
end
def next_time
@sorted_keys.first
end
def shift
if @sorted_keys.empty?
nil
else
first_key = @sorted_keys.shift
val = self.delete first_key
[first_key, val]
end
end
def add_timer time, *args, &block
time = case time
when Time
Time.to_i
else
Time.now + time.to_i
end
self[time] = [block, args] if block
end
def call_next_timer
_, v = self.shift
block, args = v
block.call(*args)
end
end
end
Ok. Now let's start writing a reactor! Since we started with timers, we'll just write enough to make timers work. So, first, an #initialize method, and a method to add timers.
class SimpleReactor
def initialize
@running = false
@timers = TimerMap.new
@block_buffer = []
end
def add_timer time, *args, &block
time = time.to_i if Time === time
@timers.add_timer time, *args, &block
end
There's nothing interesting with the initialization. It just sets the @running instance variable false. This will be used in an upcoming bit of code. The method to add a timer also does nothing special; it just passes everything into a method of the same name in the TimerMap. The next part that is needed is the skeleton of our reactor. Here is what it looks like:
def next_tick &block
@block_buffer << block
end
def tick
handle_pending_blocks
handle_events
handle_timers
end
def run
@running = true
yield self if block_given?
tick while @running
end
def stop
@running = false
end
def handle_pending_blocks
@block_buffer.length.times { @block_buffer.shift.call }
end
def handle_events
end
def handle_timers
now = Time.now
while !@timers.empty? && @timers.next_time < now
@timers.call_next_timer
end
end
def empty?
@timers.empty? && @block_buffer.empty?
end
end
There you have it. A reactor skeleton, albeit one that only supports timers and next_tick right now. Here's an example that uses it:
require 'simplereactor'
puts <<ETXT
This demo will add a sequence of numbers to a sum, via a timer, once a second,
for four seconds, with the fifth number immediately following the fourth.
1+2+3+4+5 == 15. Let's see if that's the answer that we get."
ETXT
n = 0
reactor = SimpleReactor.new
reactor.add_timer(1) do
puts "one"
n += 1
end
reactor.add_timer(2) do
puts "two"
reactor.add_timer(1, n + 2) do |sum|
puts "three"
reactor.add_timer(1, sum + 3) do |sum|
puts "four"
n = sum + 4
reactor.next_tick do
puts "five"
n += 5
puts "n is #{n}\nThe reactor should stop after this."
end
end
end
end
reactor.tick until reactor.empty?
There's no real magic here. The code shows that one can create timers, and can create new timers within the callback code of existing timers, leveraging Ruby's block syntax. If you run this, you will get output like this:
This demo will add a sequence of numbers to a sum, via a timer, once a second, for four seconds, with the fifth number immediately following the fourth. 1+2+3+4+5 == 15. Let's see if that's the answer that we get. one two three four five n is 15 The reactor should stop after this.
Take note of the last line in the example code -- reactor.tick until reactor.empty?. The reactor will not do anything until that line runs. That line sits in a loop, ticking our reactor repeatedly until there's nothing left for it to do. At that point, #empty? returns true, the loop terminates, and the program terminates.
The next step in this adventure is to add enough code to our reactor to do something useful with IO objects, as well. We need to be able to attach them to the reactor, detach them from the reactor, and put enough intelligence into the reactor to find events to respond to, and trigger the callbacks for those events.
First add a constant and some accessors, and change the #initialize method:
Events = [:read, :write, :error].freeze
attr_reader :ios
def self.run &block
reactor = self.new
reactor.run &block
end
def initialize
@running = false
@ios = Hash.new do |h,k|
h[k] = {
:events => [],
:callbacks => {},
:args => [] }
end
@timers = TimerMap.new
@block_buffer = []
end
This adds a hash for holding our IO objects. It has an initializer to hold an array of events that that the IO object will respond to, a hash of callbacks (potentially one per event type), and some set of args which can be passed to an invoked callback. A hash is also created to hold unhandled events, should they occur.
Next, let's add some methods to attach an IO object to the reactor, setup callbacks, and detach an IO object to the reactor.
def attach io, *args, &block
events = Events & args
args -= events
@ios[io][:events] |= events
setup_callback io, events, *args, &block
self
end
def setup_callback io, events, *args, &block
i = @ios[io]
events.each {|event| i[:callbacks][event] = block }
i[:args] = args
i
end
def detach io
@ios.delete io
end
The code takes an IO object, a set of args to pass into the callback, and a block. It adds it to the @ios hash, and sets up the callback for the given events.
Next, we need to add a few small methods to enable triggering on IO events.
def handle_events
unless @ios.empty?
pending_events.each do |io, events|
events.each do |event|
if @ios.has_key? io
if handler = @ios[io][:callbacks][event]
handler.call io, *@ios[io][:args]
end
end
end
end
end
end
The #handle_events method is straightforward. If there are any attached IO objects, iterate through the events, calling the callbacks for each. In the existing code, we should never have unhandled events, but by adding that now, one could take this library and expand it more easily into a larger pure ruby reactor that handles types of events other that just what select() uses.
def pending_events
# Trim our IO set to only include those which are not closed.
@ios.reject! {|io, v| io.closed? }
h = find_handles_with_events @ios.keys
if h
handles = Events.zip(h).inject({}) {|handles, ev| handles[ev.first] = ev.last; handles}
events = Hash.new {|h,k| h[k] = []}
Events.each do |event|
handles[event].each { |io| events[io] << event }
end
events
else
{} # No handles
end
end
def find_handles_with_events keys
select find_ios(:read), find_ios(:write), keys, 0.01
end
def find_ios(event)
@ios.select { |io, h| h[:events].include? event}.collect { |io, data| io } }
end
def empty?
@ios.empty? && @timers.empty? && @block_buffer.empty?
end
This last bit of code just adds the nitty gritty methods that figures out if there are any events that need to be handled. It removes from @ios any handles that are closed, uses select() to find IO events, and then returns a hash of IO objects and the events that have been triggered on them. String all of this code together, and it is all that you need to have a basic working Reactor pattern for event based programming, with timer support. Here's a trivial example that uses pipes, to illustrate how it works.
require 'simplereactor'
chunk = "01234567890" * 30
reactor = SimpleReactor.new
reader, writer = IO.pipe
reactor.attach writer, :write do |write_io|
bytes_written = write_io.write chunk
puts "Sent #{bytes_written} bytes: #{chunk[0..(bytes_written - 1)]}"
chunk.slice!(0,bytes_written)
if chunk.empty?
reactor.detach write_io
write_io.close
end
end
reactor.attach reader, :read do |read_io|
if read_io.eof?
puts "finished; detaching and closing."
reactor.detach read_io
read_io.close
else
puts "received: #{read_io.read 200}"
end
end
reactor.add_timer(2) do
puts "Timer called; the code should exit after this."
end
reactor.tick until reactor.empty?
All that code does is to open a pair of pipes. The reactor attaches to one end as a writer, and the other end as a reader. The callbacks are used to send data from one end of the pipe to the other, where it is received. The Reactor will run for two seconds, then after the timer runs, the reactor will be empty, and it will exit. It looks like this:
Sent 330 bytes: 012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890 received: 01234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001 received: 2345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890 finished; detaching and closing. Timer called; the code should exit after this.
Here's another example. This one takes user input through the reactor via STDIN, and at the same time runs the stupidest, simplest web server possible. That web server will return a response that includes whatever the user input. The example code is also written to leverage the #run method defined in the library instead of cranking it ourselves.
require './simplereactor'
require 'socket'
server = TCPServer.new("0.0.0.0", 9949)
buffer = ''
puts <<ETXT
Type some text and press after each line. The reactor is attached to
STDIN and also port 9949, where it listens for any connection and responds with
a basic HTTP response containing whatever has been typed to that point. These
two dramatically different IO streams are being handled simultaneously. Type
to exit, or wait one minute, and a timer will fire which causes the
reactor to stop and the program to exit.
ETXT
SimpleReactor.run do |reactor|
reactor.attach(server, :read) do |server|
conn = server.accept
conn.gets # Pull all of the incoming data, even though it is not used in this example
conn.write "HTTP/1.1 200 OK\r\nContent-Length:#{buffer.length}\r\nContent-Type:text/plain\r\nConnection:close\r\n\r\n#{buffer}"
conn.close
end
characters_received = 0
reactor.attach(STDIN, :read) do |stdin|
characters_received += 1
data = stdin.getc # Pull a character at a time, just for illustration purposes
unless data
reactor.stop
else
buffer << data
end
end
reactor.add_timer(60) do
reactor.stop
end
end
When this is executed, it attaches to STDIN, allowing one to provide input which is buffered internally. Any connection to port 9949 returns a simple HTTP response that contains the buffer that was created through STDIN. The process will run for 60 seconds, then the reactor will stop. Bearing in mind that this is a ridiculously trivial example, it does perform pretty well, too. Below is an excerpt from a test run, done using Ruby 1.9.3_preview1, on one of my older Linux machines.
Concurrency Level: 25 Time taken for tests: 1.60504 seconds Complete requests: 15000 Failed requests: 0 Write errors: 0 Total transferred: 1275000 bytes HTML transferred: 75000 bytes Requests per second: 14144.22 [#/sec] (mean) Time per request: 1.768 [ms] (mean) Time per request: 0.071 [ms] (mean, across all concurrent requests) Transfer rate: 1173.97 [Kbytes/sec] received
Of course, this is an absurdly trivial example. There may be bugs, and it doesn't really do a lot for you, but it is an event reactor, written in pure ruby, and if you went through the code and examples as you read, you should have a better feel for what a reactor truly is.
If you want to write more sophisticated event based software, you could continue using a simple hand-rolled pure ruby reactor like this one, or you might choose to use one of the other common libraries for Ruby today. There are several of them, each with their own strengths and weaknesses, though the most common is EventMachine. Just like our simple reactor, EventMachine offers timers and asynchronous handling of events, though EventMachine's versions will scale better. This article's version uses the select() call, which limits code using it to 1024 open file descriptors. On the other hand, EventMachine, if used on a platform that support epoll (Linux) or kqueue (various *BSD platforms), can readily support at least 10s of thousands. EventMachine also offers a more rich set of features for implementing event based code than this article's example reactor. As a parting example, here is the HTTP server example from above, written to use EventMachine.
require 'rubygems'
require 'eventmachine'
module ServerHandler
def initialize(buffer)
@buffer = buffer
super
end
def receive_data data
send_data "HTTP/1.1 200 OK\r\nContent-Length:#{@buffer.length}\r\nContent-Type:text/plain\r\nConnection:close\r\n\r\n#{@buffer}"
close_connection_after_writing
end
end
module KeyHandler
def initialize buffer
@counter = 0
@buffer = buffer
super
end
def receive_data data
@counter += 1
if data.chomp.empty?
EM.stop
else
@buffer << data
end
end
end
puts <<ETXT
Type some text and press after each line. The reactor is attached to
STDIN and also port 9949, where it listens for any connection and responds with
a basic HTTP response containing whatever has been typed to that point. These
two dramatically different IO streams are being handled simultaneously. Type
a blank line to exit, or wait one minute, and a timer will fire which causes the
reactor to stop and the program to exit.
ETXT
buffer = ''
EventMachine.run do
EM.start_server('0.0.0.0',9949,ServerHandler,buffer)
EM.attach(STDIN, KeyHandler, buffer)
EM.add_timer(60) do
EM.stop
end
end
And since I demonstrated the performance of the pure Ruby version, here's the performance of the EventMachine version (using EventMachine 0.12.10), running on the same system, using the same Ruby 1.9.3_preview1 installation.
Concurrency Level: 25 Time taken for tests: 0.696320 seconds Complete requests: 15000 Failed requests: 0 Write errors: 0 Total transferred: 1275425 bytes HTML transferred: 75025 bytes Requests per second: 21541.82 [#/sec] (mean) Time per request: 1.161 [ms] (mean) Time per request: 0.046 [ms] (mean, across all concurrent requests) Transfer rate: 1787.97 [Kbytes/sec] received
The code is structured differently, but as you can see, it works similarly. In our simple reactor example, if you changed data = stdin.getc to data = stdin.gets, the STDIN handling would behave similarly to the EM examples STDIN handling. However, given the experience of writing a pure ruby reactor, even if you have never used EventMachine before, I think you can now look at that piece of EventMachine code and generally understand how it works, both at the level of the ruby code itself, and with a good idea of what EventMachine is handling for you. This basic understanding of how event driven software actually works is key to writing software that uses the event paradigm effectively.
I have focused on EventMachine in this article because it is the most commonly used event reactor implementation in the Ruby world today. As I mentioned at the beginning of the article, however, there are other choices, such as Coolio. In future articles I will continue to focus on EventMachine, but I will try to include some examples from other frameworks, and also some examples focused on JRuby and Rubinius. Please let us know if there are particular topics that you would like to see discussed.
more »
MySQL 5.5 is in Beta »
Created at: 06.12.2011 19:55, source: Engine Yard Blog, tagged: Product ruby
A few months ago we launched an alpha release of MySQL 5.5. Today we are releasing a more robust version as a public Beta, which includes fixes and enhancements based on customer feedback. You can select MySQL 5.5 from your environment and install the Percona Server v5.5.13. The Percona build is an enhanced drop-in replacement for MySQL that allows you to run queries with greater speed and consistency.
Benefits of Upgrading
MySQL 5.5 delivers significant enhancements that enable you to improve the performance and scalability of your web applications. Some reasons to upgrade are:
- InnoDB as default storage engine: Starting in MySQL 5.5, InnoDB is the default storage engine. MySQL 5.5’s InnoDB 1.1 storage engine is re-architected and has many performance and scalability features.
- Improved multi-core performance: The database and its InnoDB storage engine have been enhanced to provide optimum performance and scalability when running on the latest multi-CPU and multi-core hardware and operating systems.
- Improved recovery performance: One of InnoDB's great strengths is its ability to reliably recover data after any type of crash that affects the database. But, this cleanup and checking makes the next restart longer. InnoDB 1.1 has improved the algorithms for recovery to provide faster uptime after a crash.
See the MySQL Documentation for additional information.
Important! MySQL 5.5 on Engine Yard Cloud is a Beta feature. Always test in a development or staging environment before using this feature in production.
Available Upgrade Options
Dump and Restore
Best for: Small to medium data sets
This entails creating a new environment that is running the MySQL 5.5 database version and restoring a dump from the original environment to it. It requires your application to be down (or at least not servicing database requests) for the duration of the dump from the original environment and the restore to the new one. The size of your database matters; the more data you have, the longer it takes to dump and import it on the new database. Instructions on dump and restoring backup files can be found under Scenario 2 in our Database Documentation site.
If you know or suspect that the dump/restore upgrade will take too long (from prior testing or from the size of your database), then contact our Professional Services team to inquire about an assisted in-place upgrade of your existing environment(s).
more »
I heard you liked files »
Created at: 02.12.2011 07:35, source: has_many :through, tagged: ruby
I was going to try and be clever and do a funny riff on this whole subject, but I just can't manage it. Here's the thing. Makefile was a dumb name for a file when Stuart Feldman wrote the make utility in 1977, but you have to forgive him because file systems were quite limited back then and filenames could only be a few characters long. The pattern was <filename.ext> - 8 chars for the name, 3 for the extension. I guess config.make wouldn't fit, config.mak looked weird, so Makefile it was.
Now we have no excuse. At all.
I respect and adore Jim Weirich, but I hope he feels at least a little shame for inflicting "Rakefile" on us all. That name choice seems to have set the stage for a proliferation of copycats. Now we have an ever-growing assortment of files that helpfully tell us they are files right there in the file name. Because something siting in a directory in the file system might be something else, like maybe a turnip or a bad hair day. Capfile, Gemfile, Procfile, Assetfile, Vagrantfile, Guardfile...
You may ask: What's the problem? Why should anyone care about a cute little naming convention that continues a tradition going back over 30 years?
It may not be a huge deal, but there are a couple issues with this. All of these file formats are actually a variation on a well-accepted language: Ruby. But with a name that omits the standard .rb extension, language-aware tools have no chance to help us out. Syntax highlighting? Nope. Will awk search those files for you? No way. Will RubyMine figure out the structure of the code in those files? Forget it. OK, you can add those files to all your tools' configurations, then you're good to go. Until someone creates a new Crapfile and you have to go through and update all those configurations again.
Just because your configuration file's contents are written in a DSL does not mean you should pretend it's not Ruby anymore.
I urge every maintainer of a project that uses a name like Crapfile for the configuration file to move toward using a name that is compatible with language-aware tools. If you can't think of a name yourself, allow me to suggest this:
filename.sub(/file$/, '_config.rb').downcase
UPDATE: It has been pointed out to me that RubyMine actually does a pretty good job of dealing with these file names. Not perfect, but pretty good. Anyway, I don't want to come off as bashing RubyMine (I'm spending more time with it now and it's starting to grow on me), so substitute vim or emacs or TextMate or your most-hated editor instead.
more »
Engine Yard Winter Updates! »
Created at: 29.11.2011 00:03, source: Engine Yard Blog, tagged: Product ruby
Update: Multiple availability zone deployments now available in Alpha. Check out our additional documentation. To sign up for access, go here.
Greetings! As the weather begins to cool, the team here is keeping warm by continuing to knock out more amazing features for all of you. I wanted to let you all know about some of the great things we have cooking over here at Engine Yard that will make life more awesome than it already is.
Highly Available, Highly Addictive
In talking to many of our customers, partners, and developers, one of the issues that frequently comes up is the ability to stay running when data centers inevitably experience an outage. Last April, one such outage impacted a variety of customers on Amazon Web Services. While we are always striving to improve our service, with our multi-region support, we were able to effectively move many of our impacted customers to Amazon’s US West region while minimizing downtime.
We plan to continue adding new features to further mitigate the effects of outages and disruptions. Currently, our development team is in the process of rolling out multiple availability zone deployments. When you create an application, Engine Yard Cloud will automatically deploy your instances across different availability zones in an Amazon Web Services region. We balance the instances efficiently and ensure that master and slave instances are in separate zones. To further improve reliability, each tier (app server, database, and utility) will be balanced independently. The team is doing some final tests and should have it rolled out in a week or so. We’ll release more information on this soon and will announce availability via our @engineyard twitter account.
For customers with specific high availability requirements, Engine Yard Professional Services can customize an environment to meet your needs. For example, Engine Yard Professional Services recently deployed a high availability solution across two data centers for one our customers and completed a regional failover test with success. Be on the lookout soon for a case study on this initiative. If you would like to learn more, please get in touch with our Professional Services team.
Need More Data!
A couple months ago, our data engineering team laid out a plan to strengthen Engine Yard’s data offerings. In an effort to make more database options available to our customers, the data engineering team released PostgreSQL 9.0 into alpha. After collecting some feedback, the team will be releasing PostreSQL 9.1 as a public beta over the next couple of weeks for all of you to use. PostgreSQL has earned a solid reputation for reliability, data integrity, and performance. As we noted earlier, those using Rails 3.1 can take advantage of significant performance gains using PostgreSQL.
The team also recently released MySQL 5.1 and 5.5 into alpha and will be releasing them as public beta shortly, as well. Please check back soon for news regarding MongoDB, Redis, and more!
more »

