Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow configuring default priority value at midpoint of range #39

Merged
merged 10 commits into from
Apr 29, 2024
35 changes: 31 additions & 4 deletions lib/delayed/priority.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,39 @@ def alerts=(alerts)
@alerts = alerts&.sort_by { |k, _| names.keys.index(k) }&.to_h
end

def assign_at_midpoint?
@assign_at_midpoint || false
end

def assign_at_midpoint=(assign_at_midpoint)
@assign_at_midpoint = assign_at_midpoint
end
tkoar marked this conversation as resolved.
Show resolved Hide resolved

def ranges
@ranges ||= names.zip(names.except(names.keys.first)).each_with_object({}) do |((name, lower), (_, upper)), obj|
obj[name] = (lower...(upper || Float::INFINITY))
end
end

def names_to_priority
tkoar marked this conversation as resolved.
Show resolved Hide resolved
return names unless assign_at_midpoint?

new_names_to_priority = {}

sorted_priorities_by_name = names&.sort_by(&:last)
sorted_priorities_by_name.each.with_index do |(name, priority_value), index|
if assign_at_midpoint?
tkoar marked this conversation as resolved.
Show resolved Hide resolved
(_, next_priority_value) = sorted_priorities_by_name[index+1] || [nil, priority_value.to_i + 10]
midpoint = priority_value.to_i + ((next_priority_value.to_i - priority_value.to_i).to_f/2.0).ceil
new_names_to_priority[name] = new(midpoint)
else
new_names_to_priority[name] = new(priority_value)
end
end

new_names_to_priority.sort_by(&:last).to_h
tkoar marked this conversation as resolved.
Show resolved Hide resolved
end

private

def default_names
Expand All @@ -99,12 +126,12 @@ def default_alerts
end

def respond_to_missing?(method_name, include_private = false)
names.key?(method_name) || super
names_to_priority.key?(method_name) || super
end

def method_missing(method_name, *args)
if names.key?(method_name) && args.none?
names[method_name]
if names_to_priority.key?(method_name) && args.none?
names_to_priority[method_name]
else
super
end
Expand All @@ -118,7 +145,7 @@ def method_missing(method_name, *args)

def initialize(value)
super()
value = self.class.names[value] if value.is_a?(Symbol)
value = self.class.names_to_priority[value] if value.is_a?(Symbol)
tkoar marked this conversation as resolved.
Show resolved Hide resolved
@value = value.to_i
end

Expand Down
61 changes: 61 additions & 0 deletions spec/delayed/priority_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
RSpec.describe Delayed::Priority do
let(:custom_names) { nil }
let(:custom_alerts) { nil }
let(:assign_at_midpoint) { nil }

around do |example|
described_class.assign_at_midpoint = assign_at_midpoint
described_class.names = custom_names
described_class.alerts = custom_alerts
example.run
Expand Down Expand Up @@ -43,6 +45,17 @@
expect(described_class.reporting).to eq 30
end

context 'when assign_at_midpoint is set to true' do
let(:assign_at_midpoint) { true }

it 'returns the midpoint value' do
expect(described_class.interactive).to eq 5
expect(described_class.user_visible).to eq 15
expect(described_class.eventual).to eq 25
expect(described_class.reporting).to eq 35
end
tkoar marked this conversation as resolved.
Show resolved Hide resolved
end

context 'when customized to high, medium, low' do
let(:custom_names) { { high: 0, medium: 100, low: 500 } }

Expand Down Expand Up @@ -81,6 +94,16 @@
)
end
end

context 'when assign_at_midpoint is set to true' do
let(:assign_at_midpoint) { true }

it 'returns the midpoint value' do
expect(described_class.high).to eq 50
expect(described_class.medium).to eq 300
expect(described_class.low).to eq 505
end
end
end
end

Expand All @@ -93,13 +116,37 @@
expect(described_class.new(-123).name).to eq nil
end

context 'when assign_at_midpoint is set to true' do
let(:assign_at_midpoint) { true }

it 'provides the name of the priority range' do
expect(described_class.new(0).name).to eq :interactive
expect(described_class.new(3).name).to eq :interactive
expect(described_class.new(10).name).to eq :user_visible
expect(described_class.new(29).name).to eq :eventual
expect(described_class.new(999).name).to eq :reporting
expect(described_class.new(-123).name).to eq nil
end
end

it 'supports initialization by symbol value' do
expect(described_class.new(:interactive)).to eq(0)
expect(described_class.new(:user_visible)).to eq(10)
expect(described_class.new(:eventual)).to eq(20)
expect(described_class.new(:reporting)).to eq(30)
end

context 'when assign_at_midpoint is set to true' do
let(:assign_at_midpoint) { true }

it 'supports initialization by symbol value' do
expect(described_class.new(:interactive)).to eq(5)
expect(described_class.new(:user_visible)).to eq(15)
expect(described_class.new(:eventual)).to eq(25)
expect(described_class.new(:reporting)).to eq(35)
end
end

it "supports predicate ('?') methods" do
expect(described_class.new(0).interactive?).to eq true
expect(described_class.new(3)).to be_interactive
Expand All @@ -110,6 +157,20 @@
expect(described_class.new(-123).interactive?).to eq false
end

context 'when assign_at_midpoint is set to true' do
let(:assign_at_midpoint) { true }

it "supports predicate ('?') methods" do
expect(described_class.new(0).interactive?).to eq true
expect(described_class.new(3)).to be_interactive
expect(described_class.new(3).user_visible?).to eq false
expect(described_class.new(10)).to be_user_visible
expect(described_class.new(29)).to be_eventual
expect(described_class.new(999)).to be_reporting
expect(described_class.new(-123).interactive?).to eq false
end
end

it 'supports alert threshold methods' do
described_class.alerts = {
interactive: { age: 77.seconds },
Expand Down
Loading