[PATCH conductor 3/9] Penalty for failure strategy

ifarkas at redhat.com ifarkas at redhat.com
Thu Aug 16 14:44:03 UTC 2012


From: Imre Farkas <ifarkas at redhat.com>

---
 src/config/locales/strategies/en.yml               |  7 ++
 .../strategies/penalty_for_failure/config.rb       | 65 +++++++++++++++++
 .../penalty_for_failure/penalty_for_failure.rb     | 37 ++++++++++
 .../strategies/penalty_for_failure/strategy.rb     | 81 ++++++++++++++++++++++
 .../views/penalty_for_failure/_edit.html.haml      | 17 +++++
 5 files changed, 207 insertions(+)
 create mode 100644 src/vendor/provider_selection/strategies/penalty_for_failure/config.rb
 create mode 100644 src/vendor/provider_selection/strategies/penalty_for_failure/penalty_for_failure.rb
 create mode 100644 src/vendor/provider_selection/strategies/penalty_for_failure/strategy.rb
 create mode 100644 src/vendor/provider_selection/views/penalty_for_failure/_edit.html.haml

diff --git a/src/config/locales/strategies/en.yml b/src/config/locales/strategies/en.yml
index 49d706b..33b6e79 100644
--- a/src/config/locales/strategies/en.yml
+++ b/src/config/locales/strategies/en.yml
@@ -2,3 +2,10 @@ en:
   strategies:
     strict_order:
       name: 'Strict Order'
+    penalty_for_failure:
+      name: 'Penalty for Failure'
+      views:
+        edit:
+          penalty_percentage: 'Penalty for each failure (in percentage)'
+          time_period_minutes: 'Time period over which the failures are aggregated (in minutes)'
+          failure_count_hard_limit: 'The number of failures over which the provider account should not be used if possible'
diff --git a/src/vendor/provider_selection/strategies/penalty_for_failure/config.rb b/src/vendor/provider_selection/strategies/penalty_for_failure/config.rb
new file mode 100644
index 0000000..466f346
--- /dev/null
+++ b/src/vendor/provider_selection/strategies/penalty_for_failure/config.rb
@@ -0,0 +1,65 @@
+#
+#   Copyright 2012 Red Hat, Inc.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+
+module ProviderSelection
+  module Strategies
+    module PenaltyForFailure
+
+      class Config
+
+        include ActiveModel::Validations
+        include ActiveModel::Conversion
+        extend ActiveModel::Naming
+
+        attr_accessor :penalty_percentage
+        attr_accessor :time_period_minutes
+        attr_accessor :failure_count_hard_limit
+
+        validates_presence_of :penalty_percentage
+        validates_presence_of :time_period_minutes
+        validates_numericality_of :penalty_percentage,
+                                  :greater_than => 0, :less_than => 100
+        validates_numericality_of :time_period_minutes,
+                                  :greater_than => 0, :less_than => 2147483647
+        validates_numericality_of :failure_count_hard_limit,
+                                  :greater_than => 0, :less_than => 1000,
+                                  :allow_blank => true
+
+        def initialize(attributes = {})
+          attributes ||= ProviderSelection::Strategies::PenaltyForFailure::Strategy.default_options
+
+          attributes.each do |name, value|
+            send("#{name}=", value)
+          end
+        end
+
+        def persisted?
+          false
+        end
+
+        def to_hash
+          {
+            :penalty_percentage => @penalty_percentage.to_i,
+            :time_period_minutes => @time_period_minutes.to_i,
+            :failure_count_hard_limit => @failure_count_hard_limit.to_i
+          }
+        end
+
+      end
+
+    end
+  end
+end
diff --git a/src/vendor/provider_selection/strategies/penalty_for_failure/penalty_for_failure.rb b/src/vendor/provider_selection/strategies/penalty_for_failure/penalty_for_failure.rb
new file mode 100644
index 0000000..8d37e20
--- /dev/null
+++ b/src/vendor/provider_selection/strategies/penalty_for_failure/penalty_for_failure.rb
@@ -0,0 +1,37 @@
+#
+#   Copyright 2012 Red Hat, Inc.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+
+require File.join(File.dirname(__FILE__), 'strategy')
+require File.join(File.dirname(__FILE__), 'config')
+
+module ProviderSelection
+  module Strategies
+    module PenaltyForFailure
+
+      class Base
+
+        extend ProviderSelection::ChainableStrategyOptions::ClassMethods
+
+        @properties = {
+            :edit_partial => 'penalty_for_failure/edit',
+            :config_klass => Config
+        }
+
+      end
+
+    end
+  end
+end
diff --git a/src/vendor/provider_selection/strategies/penalty_for_failure/strategy.rb b/src/vendor/provider_selection/strategies/penalty_for_failure/strategy.rb
new file mode 100644
index 0000000..3f4820b
--- /dev/null
+++ b/src/vendor/provider_selection/strategies/penalty_for_failure/strategy.rb
@@ -0,0 +1,81 @@
+#
+#   Copyright 2012 Red Hat, Inc.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+
+module ProviderSelection
+  module Strategies
+    module PenaltyForFailure
+
+      class Strategy
+
+        include ProviderSelection::ChainableStrategy::InstanceMethods
+
+        @default_options = {
+          :penalty_percentage => 5,
+          :time_period_minutes => 4 * 60
+        }
+
+        def self.default_options
+          @default_options
+        end
+
+        def calculate
+          rank = @strategies.calculate
+
+          # Query the number of failures for each provider account
+          failures_count = {}
+          rank.default_priority_group.matches.map(&:provider_account).uniq.each do |provider_account|
+            failures_count[provider_account] = provider_account.failure_count
+          end
+
+
+          # Modify the score of each match in every priority groups
+          rank.priority_groups.each do |priority_group|
+            priority_group.matches.each do |match|
+              match.penalize_by(failures_count[match.provider_account] * @options[:penalty_percentage])
+            end
+          end
+
+          return rank unless @options.has_key?(:failure_count_hard_limit)
+
+          # Create priority group for failing provider accounts with higher
+          # score than the default one
+          failing_provider_accounts = failures_count.inject([]) do |result, (provider_account, failure_count)|
+            if failure_count >= @options[:failure_count_hard_limit]
+              result << provider_account
+            end
+
+            result
+          end.uniq
+
+          rank.priority_groups.each do |priority_group|
+            priority_group.delete_matches(:provider_account, failing_provider_accounts)
+          end
+
+          failing_priority_group = ProviderSelection::PriorityGroup.new(rank.default_priority_group.score * 100)
+          failing_provider_accounts.each do |provider_account|
+            failing_priority_group.matches << Match.new(:provider_account => provider_account)
+          end
+
+          rank.priority_groups << failing_priority_group
+
+          rank
+        end
+
+      end
+
+    end
+  end
+end
diff --git a/src/vendor/provider_selection/views/penalty_for_failure/_edit.html.haml b/src/vendor/provider_selection/views/penalty_for_failure/_edit.html.haml
new file mode 100644
index 0000000..83c8ec3
--- /dev/null
+++ b/src/vendor/provider_selection/views/penalty_for_failure/_edit.html.haml
@@ -0,0 +1,17 @@
+.strategy-options
+  - if @config.errors.any?
+    = render 'layouts/error_messages', :object => @config
+
+  %fieldset
+    .field
+      = form.label(:penalty_percentage, t('strategies.penalty_for_failure.views.edit.penalty_percentage'))
+      .input
+        = form.text_field(:penalty_percentage)
+    .field
+      = form.label(:time_period_minutes, t('strategies.penalty_for_failure.views.edit.time_period_minutes'))
+      .input
+        = form.text_field(:time_period_minutes)
+    .field
+      = form.label(:failure_count_hard_limit, t('strategies.penalty_for_failure.views.edit.failure_count_hard_limit'))
+      .input
+        = form.text_field(:failure_count_hard_limit)
-- 
1.7.11.2




More information about the aeolus-devel mailing list