diff --git a/ubiquo_design/app/controllers/discovery_controller.rb b/ubiquo_design/app/controllers/discovery_controller.rb new file mode 100644 index 00000000..ac91cc52 --- /dev/null +++ b/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 diff --git a/ubiquo_design/app/controllers/ubiquo/pages_controller.rb b/ubiquo_design/app/controllers/ubiquo/pages_controller.rb index d22da92c..83cb2638 100644 --- a/ubiquo_design/app/controllers/ubiquo/pages_controller.rb +++ b/ubiquo_design/app/controllers/ubiquo/pages_controller.rb @@ -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 @@ -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 diff --git a/ubiquo_design/app/models/proxy_server.rb b/ubiquo_design/app/models/proxy_server.rb new file mode 100644 index 00000000..df2fd7c6 --- /dev/null +++ b/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 diff --git a/ubiquo_design/config/routes.rb b/ubiquo_design/config/routes.rb index 38c2abac..87bbe34c 100644 --- a/ubiquo_design/config/routes.rb +++ b/ubiquo_design/config/routes.rb @@ -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 diff --git a/ubiquo_design/install/db/migrate/20110713092646_create_proxy_servers.rb b/ubiquo_design/install/db/migrate/20110713092646_create_proxy_servers.rb new file mode 100644 index 00000000..20a8683f --- /dev/null +++ b/ubiquo_design/install/db/migrate/20110713092646_create_proxy_servers.rb @@ -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 diff --git a/ubiquo_design/lib/ubiquo_design.rb b/ubiquo_design/lib/ubiquo_design.rb index e600772b..353cb289 100644 --- a/ubiquo_design/lib/ubiquo_design.rb +++ b/ubiquo_design/lib/ubiquo_design.rb @@ -1,3 +1,4 @@ +<<<<<<< HEAD # -*- encoding: utf-8 -*- require 'ubiquo' @@ -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 diff --git a/ubiquo_design/lib/ubiquo_design/server_status.rb b/ubiquo_design/lib/ubiquo_design/server_status.rb new file mode 100644 index 00000000..00617151 --- /dev/null +++ b/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 = "#{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 diff --git a/ubiquo_design/rails/init.rb b/ubiquo_design/rails/init.rb index 0edd2cd4..519570a2 100644 --- a/ubiquo_design/rails/init.rb +++ b/ubiquo_design/rails/init.rb @@ -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") diff --git a/ubiquo_design/test/functional/discovery_controller_test.rb b/ubiquo_design/test/functional/discovery_controller_test.rb new file mode 100644 index 00000000..bb33f50e --- /dev/null +++ b/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 diff --git a/ubiquo_design/test/unit/proxy_server_test.rb b/ubiquo_design/test/unit/proxy_server_test.rb new file mode 100644 index 00000000..1694b7d2 --- /dev/null +++ b/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) + "\n\n \n #{avail}\n #{busy}\n \n\n" + end +end diff --git a/ubiquo_design/test/unit/server_status_test.rb b/ubiquo_design/test/unit/server_status_test.rb new file mode 100644 index 00000000..e7d0c4ad --- /dev/null +++ b/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