coordinator 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 480787ac7b5eecf9271ec542f15f5ebf17d23085
4
- data.tar.gz: 9f688ebfcd97125c0292784f8ab06a121b9a4b51
3
+ metadata.gz: e53824a57bc5054c529d8a0566a4c26024fb9eaf
4
+ data.tar.gz: 7db6d332ac9d662721a5c45cb2e0ca52493cf1cf
5
5
  SHA512:
6
- metadata.gz: c4ee690d00d2e78c10636c587c6f701230822c85a43118ab8c605759c4f9f2c75130f773649f2671ea1a4af2a6674d9643bc2be958c3dafbe21c5cc6acac4375
7
- data.tar.gz: 7b4742110498118ffcf39ad32e72b98c55bb8957d3df4f4b67fc065abe705e73a1d00ce2e60018f18839598afc228dbe0d3359830eea5e007a9b6cb83b1a473f
6
+ metadata.gz: ac992d700929b4d5ae35ddabfff494280e77daacc25198e1d2a07fb9be322d7eaea7a9849ec933dfb40eb7532d98530ae47c2200d036caedc9249c241ae11a89
7
+ data.tar.gz: 672e70f26491333ebbabbd33a2692125dfc9af2875aca218b4b7f3b8e491bd4edf8433ef8d5826ca92a6a841986d31e97f7aa750bbb0c2a7a62e4f7da439f6f9
data/README.md CHANGED
@@ -28,6 +28,13 @@ Or install it yourself as:
28
28
  Coordinator::Queue.new("medium"),
29
29
  Coordinator::Queue.new("low")
30
30
  ])
31
+
32
+ @coordinator.add_task("high", 1)
33
+ @coordinator.add_task("medium", 2)
34
+ @coordinator.add_priority_task("high", 3)
35
+
36
+ @coordinator.next_task(["high"]) # returns 3
37
+ @coordinator.next_task(["medium"]) # returns 2
31
38
 
32
39
  ## Contributing
33
40
 
@@ -1,4 +1,5 @@
1
1
  require "coordinator/version"
2
+ require "coordinator/error"
2
3
  require "coordinator/redis_queue"
3
4
  require "coordinator/queue"
4
5
  require "coordinator/base"
@@ -22,11 +22,16 @@ module Coordinator
22
22
  false
23
23
  end
24
24
 
25
+ def set_capacity(skill, capacity)
26
+ queue = queue_for_skill(skill)
27
+ queue.set_capacity(capacity)
28
+ end
29
+
25
30
  private
26
31
 
27
32
  def queue_for_skill(skill)
28
33
  queue = @queues.find {|q| q.skill == skill}
29
- raise "No matching queue for #{skill}" unless queue
34
+ raise Coordinator::Error.new("No matching queue for #{skill}") unless queue
30
35
  queue
31
36
  end
32
37
  end
@@ -0,0 +1,4 @@
1
+ module Coordinator
2
+ class Error < Exception
3
+ end
4
+ end
@@ -1,10 +1,12 @@
1
1
  module Coordinator
2
2
  class Queue
3
- attr_reader :skill
3
+ attr_reader :skill, :rules
4
4
 
5
- def initialize(skill)
5
+ def initialize(skill, capacity=nil, &block)
6
6
  @skill = skill
7
7
  @store = Coordinator::RedisQueue.new(@skill)
8
+ @store.capacity = capacity if capacity
9
+ @custom_block = block if block_given?
8
10
  end
9
11
 
10
12
  def add_task(task)
@@ -16,11 +18,16 @@ module Coordinator
16
18
  end
17
19
 
18
20
  def next_task(skills)
19
- can_work?(skills) ? @store.pop : nil
21
+ eligible?(@store.peek, skills) ? @store.pop : nil
20
22
  end
21
23
 
22
- def can_work?(skills)
23
- skills.include?(@skill)
24
+ def eligible?(task, skills)
25
+ return true if skills.include?(@skill)
26
+ @custom_block ? @custom_block.call(task, skills) : false
27
+ end
28
+
29
+ def set_capacity(capacity)
30
+ @store.capacity = capacity
24
31
  end
25
32
  end
26
33
  end
@@ -3,44 +3,60 @@ require 'json'
3
3
  module Coordinator
4
4
  class RedisQueue
5
5
  def initialize(name)
6
- @name = name
7
- raise "redis not found, please set 'Redis.current'" unless Redis.current
6
+ @queue_name = "#{name}-queue"
7
+ @capacity_name = "#{name}-capacity"
8
+ raise Coordinator::Error.new("'Redis.current' not set") unless Redis.current
8
9
  @redis = Redis.current
9
10
  end
10
11
 
11
12
  def push(item)
13
+ raise Coordinator::Error.new("Queue is at capacity") if full?
12
14
  data = serialize(item)
13
- @redis.rpush(@name, data) unless items.include?(data)
15
+ @redis.rpush(@queue_name, data) unless items.include?(data)
14
16
  end
15
17
 
16
18
  def left_push(item)
17
19
  data = serialize(item)
18
- @redis.lpush(@name, data) unless items.include?(data)
20
+ @redis.lpush(@queue_name, data) unless items.include?(data)
19
21
  end
20
22
 
21
23
  def pop
22
- data = @redis.lpop(@name)
24
+ data = @redis.lpop(@queue_name)
23
25
  parse(data)
24
26
  end
25
27
 
26
28
  def remove(item)
27
29
  data = serialize(item)
28
- @redis.lrem(@name, 1, data)
30
+ @redis.lrem(@queue_name, 1, data)
29
31
  end
30
32
 
31
33
  def peek
32
- data = @redis.lrange(@name, 0, 0).first
34
+ data = @redis.lrange(@queue_name, 0, 0).first
33
35
  parse(data)
34
36
  end
35
37
 
36
38
  def length
37
- @redis.llen(@name)
39
+ @redis.llen(@queue_name)
40
+ end
41
+
42
+ def capacity
43
+ data = @redis.get(@capacity_name)
44
+ parse(data)
45
+ end
46
+
47
+ def capacity=(capacity)
48
+ @redis.set(@capacity_name, capacity)
38
49
  end
39
50
 
40
51
  private
41
52
 
53
+ def full?
54
+ return false unless capacity
55
+ length >= capacity
56
+ end
57
+
42
58
  def items
43
- @redis.lrange(@name, 0, length)
59
+ @redis.lrange(@queue_name, 0, length)
44
60
  end
45
61
 
46
62
  def serialize(item)
@@ -1,3 +1,3 @@
1
1
  module Coordinator
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -1,8 +1,7 @@
1
1
  require 'minitest/autorun'
2
2
  require 'minitest/reporters'
3
- require "fakeredis"
3
+ require 'fakeredis'
4
4
 
5
- Redis.current = Redis.new
6
5
  Minitest::Reporters.use!(Minitest::Reporters::DefaultReporter.new(color: true))
7
6
 
8
7
  ENV['RACK_ENV'] = 'test'
@@ -19,5 +19,12 @@ describe 'Coordinator::Base' do
19
19
  assert_equal 2, @coordinator.next_task(["medium"])
20
20
  assert_equal false, @coordinator.next_task(["medium"])
21
21
  end
22
+
23
+ it 'raises exception when no queue exists' do
24
+ err = -> {
25
+ @coordinator.add_task("forgotten", 1)
26
+ }.must_raise Coordinator::Error
27
+ err.message.must_match /No matching queue for forgotten/
28
+ end
22
29
  end
23
30
  end
@@ -24,13 +24,26 @@ describe "Coordinator::Queue" do
24
24
  end
25
25
  end
26
26
 
27
- describe "can_work?" do
27
+ describe "eligible?" do
28
28
  it "returns true when skill present" do
29
- assert @queue.can_work?(["high"])
29
+ assert @queue.eligible?(nil, ["high"])
30
30
  end
31
31
 
32
32
  it "returns false when skill not present" do
33
- refute @queue.can_work?(["general", "rogers"])
33
+ refute @queue.eligible?(nil, ["low", "normal"])
34
+ end
35
+
36
+ it "can override default behaviour" do
37
+ queue = Coordinator::Queue.new("normal") do |task, skills|
38
+ return true if skills.include?("low")
39
+ return true if task == 4
40
+ task == 3 && skills.include?("special")
41
+ end
42
+ refute queue.eligible?(2, ["special"])
43
+ assert queue.eligible?(nil, ["normal"]), "default behaviour"
44
+ assert queue.eligible?(2, ["low"]), "override through skill"
45
+ assert queue.eligible?(4, []), "override through task"
46
+ assert queue.eligible?(3, ["special"]), "override through both"
34
47
  end
35
48
  end
36
49
  end
@@ -18,6 +18,15 @@ describe 'Coordinator::RedisQueue' do
18
18
  @queue.push("a")
19
19
  assert_equal 1, @queue.length
20
20
  end
21
+
22
+ it 'adds the same item only once' do
23
+ @queue.capacity = 1
24
+ @queue.push("a")
25
+ err = -> {
26
+ @queue.push("b")
27
+ }.must_raise Coordinator::Error
28
+ err.message.must_match /Queue is at capacity/
29
+ end
21
30
  end
22
31
 
23
32
  describe '.left_push' do
@@ -70,6 +79,14 @@ describe 'Coordinator::RedisQueue' do
70
79
  end
71
80
  end
72
81
 
82
+ describe '.capacity' do
83
+ it 'gets the top item and does not remove' do
84
+ assert_equal nil, @queue.capacity
85
+ @queue.capacity = 2
86
+ assert_equal 2, @queue.capacity
87
+ end
88
+ end
89
+
73
90
  it 'allows for objects' do
74
91
  [1000, "taco", {"a" => 1}, [1,2,3]].each do |o|
75
92
  @queue.push(o)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coordinator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tyler Mercier
@@ -97,6 +97,7 @@ files:
97
97
  - coordinator.gemspec
98
98
  - lib/coordinator.rb
99
99
  - lib/coordinator/base.rb
100
+ - lib/coordinator/error.rb
100
101
  - lib/coordinator/queue.rb
101
102
  - lib/coordinator/redis_queue.rb
102
103
  - lib/coordinator/version.rb