Skip to content

Commit

Permalink
feat: add priorities to IP address assignment
Browse files Browse the repository at this point in the history
  • Loading branch information
adamcooke committed Jul 28, 2021
1 parent daf469c commit 21a8d89
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 7 deletions.
2 changes: 1 addition & 1 deletion app/controllers/ip_addresses_controller.rb
Expand Up @@ -33,7 +33,7 @@ def destroy
private

def safe_params
params.require(:ip_address).permit(:ipv4, :ipv6, :hostname)
params.require(:ip_address).permit(:ipv4, :ipv6, :hostname, :priority)
end

end
22 changes: 22 additions & 0 deletions app/models/ip_address.rb
Expand Up @@ -9,6 +9,7 @@
# created_at :datetime
# updated_at :datetime
# hostname :string(255)
# priority :integer
#

class IPAddress < ApplicationRecord
Expand All @@ -18,5 +19,26 @@ class IPAddress < ApplicationRecord
validates :ipv4, :presence => true, :uniqueness => true
validates :hostname, :presence => true
validates :ipv6, :uniqueness => {:allow_blank => true}
validates :priority, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 100, only_integer: true }

scope :order_by_priority, -> { order(priority: :desc) }

before_validation :set_default_priority

private

def set_default_priority
return if priority.present?

self.priority = 100
end

class << self

def select_by_priority
order(Arel.sql("RAND() * priority DESC")).first
end

end

end
2 changes: 1 addition & 1 deletion app/models/queued_message.rb
Expand Up @@ -63,7 +63,7 @@ def send_bounce

def allocate_ip_address
if Postal.ip_pools? && self.message && pool = self.server.ip_pool_for_message(self.message)
self.ip_address = pool.ip_addresses.order("RAND()").first
self.ip_address = pool.ip_addresses.select_by_priority
end
end

Expand Down
13 changes: 13 additions & 0 deletions app/views/ip_addresses/_form.html.haml
Expand Up @@ -10,6 +10,19 @@
.fieldSet__field
= f.label :hostname, :class => 'fieldSet__label'
.fieldSet__input= f.text_field :hostname, :class => 'input input--text'
.fieldSet__field
= f.label :priority, :class => 'fieldSet__label'
.fieldSet__input
= f.text_field :priority, :class => 'input input--text', placeholder: '100'
%p.fieldSet__text
This priority will determine the likelihood of this IP address being selected
for use when sending a message. The higher the number the more likely the IP
is to be chosen. By defalt, the priority is set to the maximum value of 100.
This can be used to warm up new IP addresses by adding them with a low priority.
To give an indication of how this works, if you have three IPs with 1, 50 and 100
as their priorities, and you send 100,000 emails, the priority 1 address will receive
a tiny percentage, the priority 50 will receive roughly 25% and the priority 100 will
receive roughly 75%.

.fieldSetSubmit.buttonSet
= f.submit :class => 'button button--positive js-form-submit'
Expand Down
11 changes: 7 additions & 4 deletions app/views/ip_pools/_form.html.haml
Expand Up @@ -12,16 +12,19 @@
%td IPv4
%td IPv6
%td Hostname
%td Priority
%tbody
- if @ip_pool.ip_addresses.empty?
- ips = @ip_pool.ip_addresses.order_by_priority
- if ips.empty?
%tr
%td.dataTable__empty{:colspan => 3} There are no IP addresses assigned to this pool yet.
- else
- for ip in @ip_pool.ip_addresses
- for ip in ips
%tr
%td{:width => "20%"}= link_to ip.ipv4, [:edit, @ip_pool, ip], :class => "u-link"
%td{:width => "40%"}= ip.ipv6
%td{:width => "40%"}= ip.hostname
%td{:width => "35%"}= ip.ipv6
%td{:width => "35%"}= ip.hostname
%td{:width => "10%"}= ip.priority
%p= link_to "Add an IP address to pool", [:new, @ip_pool, :ip_address], :class => "u-link"


Expand Down
6 changes: 6 additions & 0 deletions db/migrate/20210727210551_add_priority_to_ip_addresses.rb
@@ -0,0 +1,6 @@
class AddPriorityToIPAddresses < ActiveRecord::Migration[5.2]
def change
add_column :ip_addresses, :priority, :integer
IPAddress.where(priority: nil).update_all(priority: 100)
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2020_07_17_083943) do
ActiveRecord::Schema.define(version: 2021_07_27_210551) do

create_table "additional_route_endpoints", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
t.integer "route_id"
Expand Down Expand Up @@ -124,6 +124,7 @@
t.datetime "created_at", precision: 6
t.datetime "updated_at", precision: 6
t.string "hostname"
t.integer "priority"
end

create_table "ip_pool_rules", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
Expand Down

0 comments on commit 21a8d89

Please sign in to comment.