Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Added ProxyServer model and controller and ServerStatus middleware
  • Loading branch information
bfcapell authored and Jon de Andres committed Oct 9, 2012
1 parent 03f17f3 commit 6d80b96
Show file tree
Hide file tree
Showing 11 changed files with 279 additions and 2 deletions.
26 changes: 26 additions & 0 deletions ubiquo_design/app/controllers/discovery_controller.rb
@@ -0,0 +1,26 @@
class DiscoveryController < ApplicationController

protect_from_forgery :except => [:create, :update]

def create
respond_to do |format|
case params[:type].to_sym
when :proxy_server
if params[:host].present? && params[:port].present?
@proxy_server = ProxyServer.find_or_initialize(params[:host], params[:port])
@proxy_server.updated_at = Time.now # to force updated

if (@proxy_server.save)
format.xml{ head :ok }
else
format.xml{ head 400 }
end
else
format.xml{ head 400 }
end
else
format.xml{ head 400 }
end
end
end
end
4 changes: 2 additions & 2 deletions ubiquo_design/app/controllers/ubiquo/pages_controller.rb
Expand Up @@ -98,7 +98,7 @@ def expirations
if ubiquo_config_call :expiration_permit, {:context => :ubiquo_design}
render :action => 'expirations'
else
redirect_to :action => 'index'
redirect_to ubiquo_pages_path
end
end
end
Expand Down Expand Up @@ -153,7 +153,7 @@ def expire
else
flash[:error] = t("ubiquo.page.any_page_expired")
end
redirect_to :action => :index
redirect_to ubiquo_pages_path
end

private
Expand Down
27 changes: 27 additions & 0 deletions ubiquo_design/app/models/proxy_server.rb
@@ -0,0 +1,27 @@
class ProxyServer < ActiveRecord::Base

validates_presence_of :host
validates_presence_of :port

DEAD_MINUTES = 5

named_scope :alive, lambda{
{:conditions => { :updated_at => (DEAD_MINUTES.minutes.ago .. 0.minutes.ago) }}
}

named_scope :obsolete, lambda{
{:conditions => ["updated_at < ?", DEAD_MINUTES.minutes.ago] }
}

# Exception raised when the remote server cannot be found.
class RemoteProxyServerNotFound < RuntimeError; end;

def self.delete_all_obsolete
self.obsolete.delete_all
end

def self.find_or_initialize(host, port)
find_by_host_and_port(host, port) || new(:host => host, :port => port)
end

end
3 changes: 3 additions & 0 deletions ubiquo_design/config/routes.rb
Expand Up @@ -16,10 +16,13 @@
post :change_order
put :change_order
delete :change_order
get :expirations
put :expire_pages
end

member do
post :change_name
put :expire
end
end

Expand Down
@@ -0,0 +1,14 @@
class CreateProxyServers < ActiveRecord::Migration
def self.up
create_table :proxy_servers do |t|
t.string :host
t.integer :port

t.timestamps
end
end

def self.down
drop_table :proxy_servers
end
end
17 changes: 17 additions & 0 deletions ubiquo_design/lib/ubiquo_design.rb
@@ -1,3 +1,4 @@
<<<<<<< HEAD
# -*- encoding: utf-8 -*-

require 'ubiquo'
Expand Down Expand Up @@ -35,4 +36,20 @@ def _loader
end
end
end
=======
require 'ubiquo_design/extensions'
require 'ubiquo_design/ubiquo_widgets'
require 'ubiquo_design/render_page'
require 'ubiquo_design/version'
require 'ubiquo_design/cache_managers/base'
require 'ubiquo_design/cache_expiration'
require 'ubiquo_design/cache_rendering'
require 'ubiquo_design/cache_policies'
require 'ubiquo_design/server_status'

ActionController::Base.send(:include, UbiquoDesign::UbiquoWidgets)

if ActionController::Base.perform_caching
ActionController::Base.send(:include, UbiquoDesign::CacheRendering)
ActiveRecord::Base.send(:include, UbiquoDesign::CacheExpiration::ActiveRecord)
end
42 changes: 42 additions & 0 deletions ubiquo_design/lib/ubiquo_design/server_status.rb
@@ -0,0 +1,42 @@
module UbiquoDesign
# This middleware will return a 200 OK if the app is up and running
class ServerStatus
def initialize(app, connection = nil)
@app = app
@connection = connection || default_connection
end

def call(env)
if env["PATH_INFO"] =~ /^\/server_status/
if server_ok?
response(200, 'OK')
else
response(503, 'ERROR: Database Unavailable')
end
else
@app.call(env)
end
end

protected

def response(status, message)
content_type = { "Content-Type" => "text/xml" }
body = "<?xml version=\"1.0\"?><message><status>#{message}</status></message>"

[status, content_type, [body]]
end

def server_ok?
ok = @connection.call if @connection.respond_to?(:call) rescue false
end

def default_connection
Proc.new do
ActiveRecord::Base.establish_connection

ActiveRecord::Base.connection && ActiveRecord::Base.connection.active?
end
end
end
end
3 changes: 3 additions & 0 deletions ubiquo_design/rails/init.rb
Expand Up @@ -4,6 +4,9 @@
UbiquoDesign::Connectors.load!
end

# Use the following in your application to enable the ServerStatus middleware
#config.middleware.use 'UbiquoDesign::ServerStatus'

custom_paths = Gem::Version.new(Rails.version) >= Gem::Version.new('2.3.9') ? :autoload_paths : :load_paths
ActiveSupport::Dependencies.send(custom_paths) << Rails.root.join("app", "models", "widgets")
ActiveSupport::Dependencies.send(custom_paths) << File.join(File.dirname(__FILE__), "..", "app", "models", "widgets")
Expand Down
33 changes: 33 additions & 0 deletions ubiquo_design/test/functional/discovery_controller_test.rb
@@ -0,0 +1,33 @@
require File.dirname(__FILE__) + '/../test_helper'

class DiscoveryControllerTest < ActionController::TestCase

def test_should_create_proxy_server
assert_difference "ProxyServer.count" do
proxy_request
assert_response :success
end
assert_not_nil assigns("proxy_server")
end

def test_should_update_proxy_server
assert_not_nil server = ProxyServer.create(:host => 'hostname', :port => 4000, :updated_at => 1.minute.ago)
initial_updated_at = server.updated_at

assert_no_difference "ProxyServer.count" do
proxy_request(:host => server.host, :port => server.port)
assert_response :success
end

assert_not_equal initial_updated_at, server.reload.updated_at
assert_not_nil assigns("proxy_server")
end

protected

def proxy_request(options = {})
post(:create, {:host => "127.0.0.1", :port => "80", :format => "xml", :type => "proxy_server", :locale => 'ca'}.merge(options))
end


end
66 changes: 66 additions & 0 deletions ubiquo_design/test/unit/proxy_server_test.rb
@@ -0,0 +1,66 @@
require File.dirname(__FILE__) + '/../test_helper'

class ProxyServerTest < ActiveSupport::TestCase

def test_should_create_proxy_server
assert_difference 'ProxyServer.count' do
proxy_server = create_proxy_server
assert !proxy_server.new_record?, "#{proxy_server.errors.full_messages.to_sentence}"
end
end

def test_should_require_host
assert_no_difference "ProxyServer.count" do
proxy_server = create_proxy_server(:host => "")
assert proxy_server.errors.on(:host)
end
end

def test_should_require_port
assert_no_difference "ProxyServer.count" do
proxy_server = create_proxy_server(:port => "")
assert proxy_server.errors.on(:port)
end
end

def test_should_detect_alive
assert_not_nil d = create_proxy_server(:host => 'hostname', :port => 4000, :updated_at => 1.minutes.ago)
d.update_attribute(:updated_at, 1.minutes.ago)
assert d.updated_at > ProxyServer::DEAD_MINUTES.minutes.ago

assert ProxyServer.alive.include?(d)
end

def test_should_destroy_obsolete
create_proxy_server(:host => 'hostname', :port => 4000, :updated_at => 10.minutes.ago)
assert (n = ProxyServer.obsolete.count) > 0
assert_difference "ProxyServer.count", -n do
ProxyServer.delete_all_obsolete
end
end

def test_should_find_existing_proxy_server
server = create_proxy_server(:host => 'hostname', :port => 4000)
assert_equal server, ProxyServer.find_or_initialize(server.host, server.port)
end

def test_should_initialize_new_proxy_server
server = ProxyServer.find_or_initialize('new_host', '80')
assert_equal 'new_host', server.host
assert_equal 80, server.port
end

private

def create_proxy_server(options = {})
default_options = {
:host => "myhost",
:port => 3001
}
ProxyServer.create(default_options.merge(options))
end

def xml_status(avail, busy)
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hash>\n <status>\n <available type=\"integer\">#{avail}</available>\n <busy type=\"integer\">#{busy}</busy>\n </status>\n</hash>\n"
end
end
46 changes: 46 additions & 0 deletions ubiquo_design/test/unit/server_status_test.rb
@@ -0,0 +1,46 @@
require 'test_helper'

class UbiquoDesign::ServerStatusTest < ActiveSupport::TestCase
attr_accessor :middleware
setup :prepare

test "should call app if the path is not server_status" do
env = { 'PATH_INFO' => '/test' }
response = middleware.call(env)

assert_equal 'main app called', response
end

test "should get 200 if the database is available" do
env = { 'PATH_INFO' => '/server_status' }
response = middleware.call(env)

assert_equal 200, response.first
end

test "should get 503 if the database is not available" do
env = { 'PATH_INFO' => '/server_status' }
connections = [Proc.new { false },
Proc.new { nil },
Proc.new { raise ActiveRecord::ActiveRecordError.new }]
connections.each do |unavailable|
middleware = build_middleware(:connection => unavailable)
response = middleware.call(env)

assert_equal 503, response.first
end
end

private

def prepare
@middleware = build_middleware
end

def build_middleware(options = {})
app = options[:app] || stub(:call => 'main app called')
connection = options[:connection]

UbiquoDesign::ServerStatus.new(app, connection)
end
end

0 comments on commit 6d80b96

Please sign in to comment.