Skip to content

Commit

Permalink
added Puma backend
Browse files Browse the repository at this point in the history
  • Loading branch information
filiptepper committed Mar 4, 2013
1 parent 9eee295 commit 3198c58
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 50 deletions.
1 change: 1 addition & 0 deletions Gemfile
Expand Up @@ -12,5 +12,6 @@ group :development, :test do
gem "jeweler", "~> 1.6"
gem "thin", "~> 1.5"
gem "unicorn", "~> 4.5"
gem "puma", "~> 1.6"
gem "em-http-request", "~> 1.0"
end
22 changes: 22 additions & 0 deletions README.md
Expand Up @@ -159,6 +159,28 @@ proxy = Heroku::Forward::Proxy::Server.new(backend, host: '0.0.0.0', port: port)
proxy.forward!
```

### Puma

For more information about Puma see [http://puma.io/](http://puma.io/).

The Puma back-end supports the following options.

* **application**: application to load
* **env**: environment, eg. `:development`
* **socket**: socket, eg. `/tmp/puma.sock`
* **config_file**: Puma configuration file

```ruby
require 'heroku-forward'
require 'heroku/forward/backends/puma'

application = File.expand_path('../my_app.ru', __FILE__)
config_file = File.expand_path('../config/puma.rb', __FILE__)
backend = Heroku::Forward::Backends::Puma.new(application: application, env: env, config_file: config_file)
proxy = Heroku::Forward::Proxy::Server.new(backend, host: '0.0.0.0', port: port)
proxy.forward!
```

Fail-Safe
---------

Expand Down
5 changes: 5 additions & 0 deletions heroku-forward.gemspec
Expand Up @@ -19,8 +19,10 @@ Gem::Specification.new do |s|
"lib/heroku-forward.rb",
"lib/heroku/forward.rb",
"lib/heroku/forward/backends.rb",
"lib/heroku/forward/backends/base.rb",
"lib/heroku/forward/backends/thin.rb",
"lib/heroku/forward/backends/unicorn.rb",
"lib/heroku/forward/backends/puma.rb",
"lib/heroku/forward/config/locales/en.yml",
"lib/heroku/forward/errors.rb",
"lib/heroku/forward/errors/backend_failed_to_start_error.rb",
Expand Down Expand Up @@ -52,6 +54,7 @@ Gem::Specification.new do |s|
s.add_development_dependency(%q<jeweler>, ["~> 1.6"])
s.add_development_dependency(%q<thin>, ["~> 1.5"])
s.add_development_dependency(%q<unicorn>, ["~> 4.5"])
s.add_development_dependency(%q<puma>, ["~> 1.6"])
s.add_development_dependency(%q<em-http-request>, ["~> 1.0"])
else
s.add_dependency(%q<em-proxy>, [">= 0.1.8"])
Expand All @@ -64,6 +67,7 @@ Gem::Specification.new do |s|
s.add_dependency(%q<jeweler>, ["~> 1.6"])
s.add_dependency(%q<thin>, ["~> 1.5"])
s.add_dependency(%q<unicorn>, ["~> 4.5"])
s.add_dependency(%q<puma>, ["~> 1.6"])
s.add_dependency(%q<em-http-request>, ["~> 1.0"])
end
else
Expand All @@ -77,6 +81,7 @@ Gem::Specification.new do |s|
s.add_dependency(%q<jeweler>, ["~> 1.6"])
s.add_dependency(%q<thin>, ["~> 1.5"])
s.add_dependency(%q<unicorn>, ["~> 4.5"])
s.add_dependency(%q<puma>, ["~> 1.6"])
s.add_dependency(%q<em-http-request>, ["~> 1.0"])
end
end
Expand Down
27 changes: 27 additions & 0 deletions lib/heroku/forward/backends/base.rb
@@ -0,0 +1,27 @@
module Heroku
module Forward
module Backends
class Base
attr_accessor :application, :socket, :environment, :pid

def terminate!
return false unless spawned?
Process.kill 'QUIT', @pid
@spawned = false
true
end

def spawned?
!!@spawned
end

private

def check!
raise Heroku::Forward::Errors::MissingBackendOptionError.new('application') unless @application && @application.length > 0
raise Heroku::Forward::Errors::MissingBackendApplicationError.new(@application) unless File.exists?(@application)
end
end
end
end
end
50 changes: 50 additions & 0 deletions lib/heroku/forward/backends/puma.rb
@@ -0,0 +1,50 @@
require 'heroku/forward/backends/base'

module Heroku
module Forward
module Backends
class Puma < Base
attr_accessor :config_file

def initialize(options = {})
@application = options[:application]
@socket = options[:socket] || Heroku::Forward::Utils::Dir.tmp_filename('puma-', '.sock')
@env = options[:env] || 'development'
@config_file = options[:config_file]
end

def spawn!
return false if spawned?
check!

args = ['puma']
args.push '--environment', @env
args.push '--config', @config_file if @config_file
args.push '--bind', "unix://#{@socket}"
args.push @application

@pid = Spoon.spawnp(*args)
@spawned = true
end

def terminate!
return false unless spawned?
Process.kill 'QUIT', @pid
@spawned = false
true
end

def spawned?
!!@spawned
end

private

def check!
raise Heroku::Forward::Errors::MissingBackendOptionError.new('application') unless @application && @application.length > 0
raise Heroku::Forward::Errors::MissingBackendApplicationError.new(@application) unless File.exists?(@application)
end
end
end
end
end
28 changes: 3 additions & 25 deletions lib/heroku/forward/backends/thin.rb
@@ -1,12 +1,9 @@
require 'heroku/forward/backends/base'

module Heroku
module Forward
module Backends
class Thin
attr_accessor :application
attr_accessor :socket
attr_accessor :environment
attr_accessor :pid

class Thin < Base
attr_accessor :ssl
attr_accessor :ssl_key_file
attr_accessor :ssl_cert_file
Expand Down Expand Up @@ -48,25 +45,6 @@ def spawn!
@pid = Spoon.spawnp(* spawn_with)
@spawned = true
end

def terminate!
return false unless spawned?
Process.kill 'QUIT', @pid
@spawned = false
true
end

def spawned?
!! @spawned
end

private

def check!
raise Heroku::Forward::Errors::MissingBackendOptionError.new('application') unless @application && @application.length > 0
raise Heroku::Forward::Errors::MissingBackendApplicationError.new(@application) unless File.exists?(@application)
end

end
end
end
Expand Down
25 changes: 4 additions & 21 deletions lib/heroku/forward/backends/unicorn.rb
@@ -1,8 +1,10 @@
require 'heroku/forward/backends/base'

module Heroku
module Forward
module Backends
class Unicorn
attr_accessor :application, :socket, :environment, :pid, :config_file
class Unicorn < Base
attr_accessor :config_file

def initialize(options = {})
@application = options[:application]
Expand All @@ -24,25 +26,6 @@ def spawn!
@pid = Spoon.spawnp(*args)
@spawned = true
end

def terminate!
return false unless spawned?
Process.kill 'QUIT', @pid
@spawned = false
true
end

def spawned?
!!@spawned
end

private

def check!
raise Heroku::Forward::Errors::MissingBackendOptionError.new('application') unless @application && @application.length > 0
raise Heroku::Forward::Errors::MissingBackendApplicationError.new(@application) unless File.exists?(@application)
end

end
end
end
Expand Down
57 changes: 57 additions & 0 deletions spec/lib/heroku/forward/backends/puma_spec.rb
@@ -0,0 +1,57 @@
require 'spec_helper'
require 'heroku/forward/backends/puma'

describe Heroku::Forward::Backends::Puma do
describe "with defaults" do
let(:backend) do
Heroku::Forward::Backends::Puma.new
end

after do
backend.terminate!
end

it "#spawned?" do
backend.spawned?.should be_false
end

context "checks" do
it "checks for application" do
expect {
backend.spawn!
}.to raise_error Heroku::Forward::Errors::MissingBackendOptionError
end

it "checks that the application file exists" do
expect {
backend.application = 'spec/foobar'
backend.spawn!
}.to raise_error Heroku::Forward::Errors::MissingBackendApplicationError
end

end

it "#spawn!" do
backend.application = "spec/support/app.ru"
backend.spawn!.should_not == 0
sleep 2
backend.terminate!.should be_true
end
end

context "constructs command" do
let(:backend) do
Heroku::Forward::Backends::Puma.new(
:application => 'spec/support/app.ru',
:env => 'test',
:socket => '/tmp/puma.sock',
:config_file => 'spec/support/puma.rb'
)
end

it "forwards arguments to spawner" do
Spoon.should_receive(:spawnp).with(*%w{puma --environment test --config spec/support/puma.rb --bind unix:///tmp/puma.sock spec/support/app.ru}).and_return(0)
backend.spawn!
end
end
end
10 changes: 6 additions & 4 deletions spec/lib/heroku/forward/proxy/server_spec.rb
@@ -1,16 +1,18 @@
require 'spec_helper'
require 'heroku/forward/backends/thin'
require 'heroku/forward/backends/unicorn'
require 'heroku/forward/backends/puma'

describe Heroku::Forward::Proxy::Server do

[
Heroku::Forward::Backends::Thin,
Heroku::Forward::Backends::Unicorn
Heroku::Forward::Backends::Unicorn,
Heroku::Forward::Backends::Puma
].each do |backend_type|

context "with #{backend_type.name} backend" do

let(:backend) do
backend_type.new(:application => 'spec/support/app.ru')
end
Expand Down Expand Up @@ -42,7 +44,7 @@
end
end
end

end
end

Expand Down
1 change: 1 addition & 0 deletions spec/support/puma.rb
@@ -0,0 +1 @@
threads 0, 2

0 comments on commit 3198c58

Please sign in to comment.