adrian 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8f73a613da14daf5853a7cf3293d631206cccb95
4
+ data.tar.gz: a334dbf9245a776ab4c8183ce2bd85ccb63b432c
5
+ SHA512:
6
+ metadata.gz: 63b1f95bf533968cc32cb7f483af6747199c4d8b0623a55ffbbc5165b493166196a1571a3a651347ae9e1c3a291e1b6a5b40d8d54b84e28d8eaeba0e3e1badcf
7
+ data.tar.gz: 1f874b8b498ac09771a4a11c2dad9cb3bbcfc890ca9d40d862d564b160a56ba03e1202460c8b21a96a15faa4c3869716291ab02b55fbcec5bd7aa5093af4eae0
@@ -29,11 +29,9 @@ module Adrian
29
29
  end
30
30
 
31
31
  def pop_item
32
- items.each do |item|
32
+ while item = items.shift
33
33
  return item if reserve(item)
34
34
  end
35
-
36
- nil
37
35
  end
38
36
 
39
37
  def push_item(value)
@@ -69,9 +67,10 @@ module Adrian
69
67
  end
70
68
 
71
69
  def items
72
- items = files.map { |file| wrap_item(file) }
73
- items.reject! { |item| !item.exist? || filter?(item) }
74
- items.sort_by(&:updated_at)
70
+ return @items if @items && @items.length > 0
71
+ @items = files.map! { |file| wrap_item(file) }
72
+ @items.reject! { |item| !item.exist? || filter?(item) }
73
+ @items.sort_by!(&:updated_at)
75
74
  end
76
75
 
77
76
  def files
@@ -3,9 +3,8 @@ module Adrian
3
3
  attr_accessor :logger
4
4
 
5
5
  def initialize(value)
6
- @value = value
7
- created_at
8
- updated_at
6
+ @value = value
7
+ stat
9
8
  end
10
9
 
11
10
  def path
@@ -28,16 +27,18 @@ module Adrian
28
27
  @value = destination_path
29
28
  end
30
29
 
31
- def atime
32
- File.atime(path).utc
30
+ def stat
31
+ @stat ||= File.stat(path)
33
32
  rescue Errno::ENOENT
34
33
  nil
35
34
  end
36
35
 
36
+ def atime
37
+ stat ? stat.atime.utc : nil
38
+ end
39
+
37
40
  def mtime
38
- File.mtime(path).utc
39
- rescue Errno::ENOENT
40
- nil
41
+ stat ? stat.mtime.utc : nil
41
42
  end
42
43
 
43
44
  def updated_at
@@ -1,3 +1,3 @@
1
1
  module Adrian
2
- VERSION = '2.0.0'
2
+ VERSION = '2.0.1'
3
3
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: adrian
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
5
- prerelease:
4
+ version: 2.0.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Mick Staugaard
@@ -10,54 +9,48 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2013-02-20 00:00:00.000000000 Z
12
+ date: 2015-05-22 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: rake
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
- - - ! '>='
18
+ - - '>='
21
19
  - !ruby/object:Gem::Version
22
20
  version: '0'
23
21
  type: :development
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
- - - ! '>='
25
+ - - '>='
29
26
  - !ruby/object:Gem::Version
30
27
  version: '0'
31
28
  - !ruby/object:Gem::Dependency
32
29
  name: minitest
33
30
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
  requirements:
36
- - - ! '>='
32
+ - - '>='
37
33
  - !ruby/object:Gem::Version
38
34
  version: '0'
39
35
  type: :development
40
36
  prerelease: false
41
37
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
  requirements:
44
- - - ! '>='
39
+ - - '>='
45
40
  - !ruby/object:Gem::Version
46
41
  version: '0'
47
42
  - !ruby/object:Gem::Dependency
48
43
  name: girl_friday
49
44
  requirement: !ruby/object:Gem::Requirement
50
- none: false
51
45
  requirements:
52
- - - ! '>='
46
+ - - '>='
53
47
  - !ruby/object:Gem::Version
54
48
  version: '0'
55
49
  type: :development
56
50
  prerelease: false
57
51
  version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
52
  requirements:
60
- - - ! '>='
53
+ - - '>='
61
54
  - !ruby/object:Gem::Version
62
55
  version: '0'
63
56
  description: A work dispatcher and some queue implementations
@@ -66,6 +59,7 @@ executables: []
66
59
  extensions: []
67
60
  extra_rdoc_files: []
68
61
  files:
62
+ - lib/adrian.rb
69
63
  - lib/adrian/array_queue.rb
70
64
  - lib/adrian/composite_queue.rb
71
65
  - lib/adrian/directory_queue.rb
@@ -79,58 +73,28 @@ files:
79
73
  - lib/adrian/rotating_directory_queue.rb
80
74
  - lib/adrian/version.rb
81
75
  - lib/adrian/worker.rb
82
- - lib/adrian.rb
83
- - test/array_queue_test.rb
84
- - test/composite_queue_test.rb
85
- - test/directory_queue_test.rb
86
- - test/dispatcher_lifecycle_test.rb
87
- - test/dispatcher_test.rb
88
- - test/failure_handler_test.rb
89
- - test/file_item_test.rb
90
- - test/filters_test.rb
91
- - test/girl_friday_dispatcher_test.rb
92
- - test/queue_test.rb
93
- - test/rotating_directory_queue_test.rb
94
- - test/test_helper.rb
95
- - test/worker_test.rb
96
- - README.md
97
- - CONTRIBUTING.md
98
76
  homepage: https://github.com/zendesk/adrian
99
77
  licenses:
100
78
  - Apache License Version 2.0
79
+ metadata: {}
101
80
  post_install_message:
102
81
  rdoc_options: []
103
82
  require_paths:
104
83
  - lib
105
84
  required_ruby_version: !ruby/object:Gem::Requirement
106
- none: false
107
85
  requirements:
108
- - - ! '>='
86
+ - - '>='
109
87
  - !ruby/object:Gem::Version
110
88
  version: '0'
111
89
  required_rubygems_version: !ruby/object:Gem::Requirement
112
- none: false
113
90
  requirements:
114
- - - ! '>='
91
+ - - '>='
115
92
  - !ruby/object:Gem::Version
116
93
  version: '0'
117
94
  requirements: []
118
95
  rubyforge_project:
119
- rubygems_version: 1.8.24
96
+ rubygems_version: 2.0.14
120
97
  signing_key:
121
- specification_version: 3
98
+ specification_version: 4
122
99
  summary: Adrian does not do any real work, but is really good at delegating it
123
- test_files:
124
- - test/array_queue_test.rb
125
- - test/composite_queue_test.rb
126
- - test/directory_queue_test.rb
127
- - test/dispatcher_lifecycle_test.rb
128
- - test/dispatcher_test.rb
129
- - test/failure_handler_test.rb
130
- - test/file_item_test.rb
131
- - test/filters_test.rb
132
- - test/girl_friday_dispatcher_test.rb
133
- - test/queue_test.rb
134
- - test/rotating_directory_queue_test.rb
135
- - test/test_helper.rb
136
- - test/worker_test.rb
100
+ test_files: []
@@ -1,7 +0,0 @@
1
- # Contributing
2
-
3
- 1. Fork it
4
- 2. Create your feature branch (`git checkout -b my-new-feature`)
5
- 3. Commit your changes (`git commit -am 'Added some feature'`)
6
- 4. Push to the branch (`git push origin my-new-feature`)
7
- 5. Create new Pull Request
data/README.md DELETED
@@ -1,34 +0,0 @@
1
- # Adrian
2
-
3
- Adrian is a work dispatcher and some queue implementations.
4
- Adrian does not do any real work, but is really good at delegating it.
5
- Adrian **does not care how** real work get's done, but **makes damn sure that it does get done**.
6
-
7
- ## Installation
8
-
9
- Add this line to your application's Gemfile:
10
-
11
- gem 'adrian'
12
-
13
- And then execute:
14
-
15
- $ bundle
16
-
17
- Or install it yourself as:
18
-
19
- $ gem install adrian
20
-
21
- ## Usage
22
-
23
- TODO: Write usage instructions here
24
-
25
- ## Copyright and license
26
-
27
- Copyright 2013 Zendesk
28
-
29
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
30
- You may obtain a copy of the License at
31
-
32
- http://www.apache.org/licenses/LICENSE-2.0
33
-
34
- 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.
@@ -1,33 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- describe Adrian::ArrayQueue do
4
- it 'should allow construction with an array' do
5
- q = Adrian::ArrayQueue.new([1,2,3])
6
- q.pop.value.must_equal 1
7
- q.pop.value.must_equal 2
8
- q.pop.value.must_equal 3
9
- q.pop.must_be_nil
10
- end
11
-
12
- it 'should allow construction without an array' do
13
- q = Adrian::ArrayQueue.new
14
- q.pop.must_be_nil
15
- end
16
-
17
- it 'should act as a queue' do
18
- q = Adrian::ArrayQueue.new
19
-
20
- q.push(1)
21
- q.push(2)
22
- q.push(3)
23
-
24
- q.length.must_equal 3
25
-
26
- q.pop.value.must_equal 1
27
- q.pop.value.must_equal 2
28
- q.pop.value.must_equal 3
29
- q.pop.must_be_nil
30
-
31
- q.length.must_equal 0
32
- end
33
- end
@@ -1,44 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- describe Adrian::CompositeQueue do
4
- before do
5
- @q1 = Adrian::ArrayQueue.new
6
- @q2 = Adrian::ArrayQueue.new
7
- @q = Adrian::CompositeQueue.new(@q1, @q2)
8
- end
9
-
10
- describe "popping" do
11
- it 'should return nil when all queues are empty' do
12
- @q.pop.must_be_nil
13
- end
14
-
15
- it 'should return an item from the first queue that has items' do
16
- @q1.push(1)
17
- @q1.push(2)
18
- @q2.push(3)
19
- @q2.push(4)
20
-
21
- @q.pop.value.must_equal(1)
22
- @q.pop.value.must_equal(2)
23
- @q.pop.value.must_equal(3)
24
- @q.pop.value.must_equal(4)
25
- @q.pop.must_be_nil
26
- @q1.pop.must_be_nil
27
- @q2.pop.must_be_nil
28
- end
29
-
30
- it 'sets the original queue on the item' do
31
- @q1.push(1)
32
- @q2.push(2)
33
-
34
- @q.pop.queue.must_equal @q1
35
- @q.pop.queue.must_equal @q2
36
- end
37
- end
38
-
39
- describe "pushing" do
40
- it "should not be allowed" do
41
- lambda { @q.push(1) }.must_raise(RuntimeError)
42
- end
43
- end
44
- end
@@ -1,153 +0,0 @@
1
- require_relative 'test_helper'
2
- require 'tempfile'
3
- require 'tmpdir'
4
- require 'fileutils'
5
- require 'logger'
6
-
7
- describe Adrian::DirectoryQueue do
8
- before do
9
- @logger = Logger.new('/dev/null')
10
- @q = Adrian::DirectoryQueue.create(:path => Dir.mktmpdir('dir_queue_test'), :delay => 0, :logger => @logger)
11
- end
12
-
13
- after do
14
- FileUtils.rm_r(@q.available_path, :force => true)
15
- FileUtils.rm_r(@q.reserved_path, :force => true)
16
- end
17
-
18
- it 'should act as a queue for files' do
19
- item1 = Tempfile.new('item1-').path
20
- item2 = Tempfile.new('item2-').path
21
- item3 = Tempfile.new('item3-').path
22
-
23
- @q.push(item1)
24
- @q.push(item2)
25
- @q.push(item3)
26
-
27
- @q.length.must_equal 3
28
-
29
- @q.pop.must_equal Adrian::FileItem.new(item1)
30
- @q.pop.must_equal Adrian::FileItem.new(item2)
31
- @q.pop.must_equal Adrian::FileItem.new(item3)
32
- @q.pop.must_be_nil
33
-
34
- @q.length.must_equal 0
35
- end
36
-
37
- describe 'file backend' do
38
-
39
- describe 'pop' do
40
- before do
41
- @item = Adrian::FileItem.new(Tempfile.new('item').path)
42
- end
43
-
44
- it 'provides an available file' do
45
- @q.push(@item)
46
- assert_equal @item, @q.pop
47
- end
48
-
49
- it 'moves the file to the reserved directory' do
50
- @q.push(@item)
51
- original_path = @item.path
52
- item = @q.pop
53
- assert_equal @item, item
54
-
55
- assert_equal false, File.exist?(original_path)
56
- assert_equal true, File.exist?(File.join(@q.reserved_path, @item.name))
57
- end
58
-
59
- it 'reserves the file for an hour by default' do
60
- @q.push(@item)
61
- reserved_item = @q.pop
62
- assert reserved_item
63
- one_hour = 3_600
64
-
65
- Time.stub(:now, reserved_item.updated_at + one_hour - 1) do
66
- assert_equal nil, @q.pop
67
- end
68
-
69
- Time.stub(:now, reserved_item.updated_at + one_hour) do
70
- assert_equal @item, @q.pop
71
- end
72
-
73
- end
74
-
75
- it 'touches the item' do
76
- @q.push(@item)
77
- now = Time.now + 100
78
- item = nil
79
- Time.stub(:now, now) { item = @q.pop }
80
-
81
- assert_equal now.to_i, item.updated_at.to_i
82
- end
83
-
84
- it 'skips the file when moved by another process' do
85
- def @q.files
86
- [ 'no/longer/exists' ]
87
- end
88
- assert_equal nil, @q.pop
89
- end
90
-
91
- it "only provides normal files" do
92
- not_file = Dir.mktmpdir(@q.available_path, 'directory_queue_x')
93
- assert_equal nil, @q.pop
94
- end
95
-
96
- it "set's the logger on the item" do
97
- @item.logger.must_be_nil
98
- @q.push(@item)
99
- @q.pop.logger.must_equal @logger
100
- end
101
-
102
- end
103
-
104
- describe 'push' do
105
- before do
106
- @item = Adrian::FileItem.new(Tempfile.new('item').path)
107
- end
108
-
109
- it 'moves the file to the available directory' do
110
- original_path = @item.path
111
- @q.push(@item)
112
-
113
- assert_equal false, File.exist?(original_path)
114
- assert_equal true, File.exist?(File.join(@q.available_path, @item.name))
115
- end
116
-
117
- it 'touches the item' do
118
- now = Time.now - 100
119
- Time.stub(:now, now) { @q.push(@item) }
120
-
121
- assert_equal now.to_i, @item.updated_at.to_i
122
- end
123
-
124
- end
125
-
126
- describe 'filters' do
127
- it 'should add a delay filter if the :delay option is given' do
128
- q = Adrian::DirectoryQueue.create(:path => Dir.mktmpdir('dir_queue_test'))
129
- filter = q.filters.find {|filter| filter.is_a?(Adrian::Filters::Delay)}
130
- filter.must_equal nil
131
-
132
- q = Adrian::DirectoryQueue.create(:path => Dir.mktmpdir('dir_queue_test'), :delay => 300)
133
- filter = q.filters.find {|filter| filter.is_a?(Adrian::Filters::Delay)}
134
- filter.wont_equal nil
135
- filter.duration.must_equal 300
136
- end
137
-
138
- it 'should add a lock filter that can be configured with the :lock_duration option' do
139
- q = Adrian::DirectoryQueue.create(:path => Dir.mktmpdir('dir_queue_test'))
140
- filter = q.filters.find {|filter| filter.is_a?(Adrian::Filters::FileLock)}
141
- filter.wont_equal nil
142
- filter.duration.must_equal 3600 # default value
143
-
144
- q = Adrian::DirectoryQueue.create(:path => Dir.mktmpdir('dir_queue_test'), :lock_duration => 300)
145
- filter = q.filters.find {|filter| filter.is_a?(Adrian::Filters::FileLock)}
146
- filter.wont_equal nil
147
- filter.duration.must_equal 300
148
- end
149
- end
150
-
151
- end
152
-
153
- end
@@ -1,82 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- describe "Adrian::Dispatcher lifecycle" do
4
- class Worker < Adrian::Worker
5
- def work
6
- $done_items << item.value
7
- end
8
- end
9
-
10
- before do
11
- $done_items = []
12
- @q = Adrian::ArrayQueue.new([1,2,3])
13
- end
14
-
15
- describe "stop_when_done" do
16
- describe "set to true" do
17
- before do
18
- @dispatcher = Adrian::Dispatcher.new(:stop_when_done => true)
19
- end
20
-
21
- it "should have all the work done and stop" do
22
- t = Thread.new do
23
- @dispatcher.start(@q, Worker)
24
- end
25
-
26
- sleep(0.5)
27
-
28
- @q.pop.must_be_nil
29
-
30
- $done_items.must_equal([1,2,3])
31
-
32
- @dispatcher.running.must_equal false
33
- end
34
- end
35
-
36
- describe "set to false" do
37
- before do
38
- @dispatcher = Adrian::Dispatcher.new(:stop_when_done => false)
39
- end
40
-
41
- it "should have all the work done and continue" do
42
- t = Thread.new do
43
- @dispatcher.start(@q, Worker)
44
- end
45
-
46
- sleep(0.5)
47
-
48
- @q.pop.must_be_nil
49
-
50
- $done_items.must_equal([1,2,3])
51
-
52
- @dispatcher.running.must_equal true
53
- t.kill
54
- end
55
- end
56
- end
57
-
58
- describe "#stop" do
59
- before do
60
- @dispatcher = Adrian::Dispatcher.new(:sleep => 0.1)
61
- end
62
-
63
- it "should stop a running dispatcher" do
64
- t = Thread.new do
65
- @dispatcher.start(@q, Worker)
66
- end
67
-
68
- sleep(0.5)
69
-
70
- @dispatcher.running.must_equal true
71
- t.status.wont_equal false
72
-
73
- @dispatcher.stop
74
-
75
- sleep(0.5)
76
-
77
- @dispatcher.running.must_equal false
78
- t.status.must_equal false
79
- end
80
- end
81
-
82
- end
@@ -1,99 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- describe Adrian::Dispatcher do
4
- before do
5
- $done_items = []
6
- @q = Adrian::ArrayQueue.new([], :max_age => 1000)
7
- @dispatcher = Adrian::Dispatcher.new(:stop_when_done => true)
8
- @worker = TestWorker
9
- end
10
-
11
- class TestWorker
12
-
13
- def initialize(item)
14
- @item = item
15
- @done_items = []
16
- end
17
-
18
- def perform
19
- $done_items << @item.value
20
- end
21
-
22
- def report_to(boss)
23
- @boss = boss
24
- end
25
-
26
- end
27
-
28
- describe "work delegation" do
29
- it "should instantiate an instance of the worker for each item and ask it to perform" do
30
- @q.push(1)
31
- @q.push(2)
32
- @q.push(3)
33
-
34
- @dispatcher.start(@q, @worker)
35
-
36
- $done_items.must_equal([1, 2, 3])
37
- end
38
- end
39
-
40
- describe "a queue with old items" do
41
- before do
42
- @q.push(Adrian::QueueItem.new(1, Time.now))
43
- @old_item = Adrian::QueueItem.new(2, Time.now - 2000)
44
- @q.push(@old_item)
45
- @q.push(Adrian::QueueItem.new(3, Time.now))
46
- end
47
-
48
- it 'skips the old items' do
49
- @dispatcher.start(@q, @worker)
50
-
51
- $done_items.must_equal([1, 3])
52
- end
53
-
54
- it 'calls the handler for Adrian::Queue::ItemTooOldError' do
55
- handled_items = []
56
- handled_exceptions = []
57
-
58
- @dispatcher.on_failure(Adrian::Queue::ItemTooOldError) do |item, worker, exception|
59
- handled_items << item
60
- handled_exceptions << exception
61
- end
62
-
63
- @dispatcher.start(@q, @worker)
64
-
65
- handled_items.must_equal [@old_item]
66
- handled_exceptions.size.must_equal 1
67
- handled_exceptions.first.must_be_instance_of Adrian::Queue::ItemTooOldError
68
- end
69
- end
70
-
71
- describe "work evaluation" do
72
-
73
- it "stops when receiving a termination signal" do
74
- @dispatcher = Adrian::Dispatcher.new(:stop_when_done => false)
75
- dispatch_thread = Thread.new { @dispatcher.start(@q, @worker) }
76
- sleep(0.1)
77
- assert_equal true, @dispatcher.running
78
-
79
- Process.kill('TERM', Process.pid)
80
- assert_equal false, @dispatcher.running
81
- dispatch_thread.exit
82
- end
83
-
84
- it "should use the failure handler to handle the result" do
85
- @dispatcher.on_failure(RuntimeError) do |item, worker, exception|
86
- @q.push(item)
87
- end
88
-
89
- @dispatcher.work_done(1, nil)
90
- @q.pop.must_be_nil
91
-
92
- @dispatcher.work_done(1, nil, nil)
93
- @q.pop.must_be_nil
94
-
95
- @dispatcher.work_done(1, nil, RuntimeError.new)
96
- @q.pop.value.must_equal 1
97
- end
98
- end
99
- end
@@ -1,44 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- require 'adrian/failure_handler'
4
-
5
- describe Adrian::FailureHandler do
6
- before do
7
- @handler = Adrian::FailureHandler.new
8
-
9
- $failure = nil
10
-
11
- @handler.add_rule(RuntimeError) { :runtime }
12
- @handler.add_rule(StandardError) { :standard }
13
- end
14
-
15
- it "should match rules in the order they were added" do
16
- block = @handler.handle(RuntimeError.new)
17
- assert block
18
- block.call.must_equal :runtime
19
-
20
- block = @handler.handle(StandardError.new)
21
- assert block
22
- block.call.must_equal :standard
23
- end
24
-
25
- it "should do nothing when no rules match" do
26
- @handler.handle(Exception.new).must_be_nil
27
- end
28
-
29
- describe "the success rule" do
30
- before do
31
- @handler = Adrian::FailureHandler.new
32
- @handler.add_rule(nil) { :success }
33
- end
34
-
35
- it "should match when there is no exception" do
36
- @handler.handle(RuntimeError.new).must_be_nil
37
-
38
- block = @handler.handle(nil)
39
- assert block
40
- block.call.must_equal :success
41
- end
42
- end
43
-
44
- end
@@ -1,152 +0,0 @@
1
- require_relative 'test_helper'
2
- require 'tempfile'
3
-
4
- describe Adrian::FileItem do
5
- before do
6
- @item = Adrian::FileItem.new(Tempfile.new('file_item_test').path)
7
- end
8
-
9
- it 'aliases value as path' do
10
- item = Adrian::FileItem.new('path/a')
11
- assert_equal 'path/a', item.value
12
- end
13
-
14
- it 'has a name from the path' do
15
- item = Adrian::FileItem.new('path/name.ext')
16
- assert_equal 'name.ext', item.name
17
- end
18
-
19
- it 'is equal to another item when they have the same name' do
20
- item1 = Adrian::FileItem.new('path/a')
21
- item2 = Adrian::FileItem.new('path/b')
22
- assert(item1 != item2)
23
-
24
- item3 = Adrian::FileItem.new('path/a')
25
- assert_equal item1, item3
26
- end
27
-
28
- describe 'updated_at' do
29
-
30
- it 'is the atime of the file' do
31
- @item.updated_at.must_equal File.atime(@item.path)
32
- end
33
-
34
- it 'is nil when moved by another process' do
35
- item = Adrian::FileItem.new('moved/during/initialize')
36
- assert_equal false, item.exist?
37
- assert_equal nil, item.updated_at
38
- end
39
-
40
- it 'is cached' do
41
- updated_at = @item.updated_at
42
- assert @item.updated_at
43
- File.unlink(@item.path)
44
- assert_equal false, @item.exist?
45
-
46
- assert_equal updated_at, @item.updated_at
47
- end
48
-
49
- end
50
-
51
- describe 'created_at' do
52
-
53
- it 'is the mtime of the file' do
54
- @item.created_at.must_equal File.mtime(@item.path)
55
- end
56
-
57
- it 'is nil when moved by another process' do
58
- item = Adrian::FileItem.new('moved/during/initialize')
59
- assert_equal false, item.exist?
60
- assert_equal nil, item.created_at
61
- end
62
-
63
- it 'is cached' do
64
- created_at = @item.created_at
65
- assert @item.created_at
66
- File.unlink(@item.path)
67
- assert_equal false, @item.exist?
68
-
69
- assert_equal created_at, @item.created_at
70
- end
71
-
72
- end
73
-
74
- describe 'move' do
75
- before do
76
- @destination = Dir.mktmpdir('file_item_move_test')
77
- end
78
-
79
- it 'moves the file to the given directory' do
80
- @item.move(@destination)
81
- assert_equal true, File.exist?(File.join(@destination, @item.name))
82
- end
83
-
84
- it 'updates the path to its new location' do
85
- @item.move(@destination)
86
- assert_equal @destination, File.dirname(@item.path)
87
- end
88
-
89
- it 'logs the move on the logger' do
90
- destination_file_name = File.join(@destination, File.basename(@item.path))
91
- logger = MiniTest::Mock.new
92
- logger.expect(:info, nil, ["Moving #{@item.path} to #{destination_file_name}"])
93
- @item.logger = logger
94
-
95
- @item.move(@destination)
96
-
97
- logger.verify
98
- end
99
-
100
- it 'does not change the atime' do
101
- atime = File.atime(@item.path)
102
- @item.move(@destination)
103
- File.atime(@item.path).must_equal atime
104
- end
105
-
106
- it 'does not change the mtime' do
107
- mtime = File.mtime(@item.path)
108
- @item.move(@destination)
109
- File.mtime(@item.path).must_equal mtime
110
- end
111
-
112
- end
113
-
114
- describe 'touch' do
115
-
116
- it 'changes the update timestamp to the current time' do
117
- now = Time.now - 100
118
- Time.stub(:now, now) { @item.touch }
119
-
120
- assert_equal now.to_i, @item.updated_at.to_i
121
- end
122
-
123
- it 'changes the atime' do
124
- atime = File.atime(@item.path).to_i
125
-
126
- now = (Time.now - 100)
127
- Time.stub(:now, now) { @item.touch }
128
-
129
- now.to_i.wont_equal atime
130
- File.atime(@item.path).to_i.must_equal now.to_i
131
- end
132
-
133
- it 'does not change the mtime' do
134
- mtime = File.mtime(@item.path).to_i
135
-
136
- now = (Time.now - 100)
137
- Time.stub(:new, now) { @item.touch }
138
-
139
- now.to_i.wont_equal mtime
140
- File.mtime(@item.path).to_i.must_equal mtime
141
- end
142
-
143
- end
144
-
145
- it 'exists when the file at the given path exists' do
146
- assert_equal true, @item.exist?
147
- File.unlink(@item.path)
148
-
149
- assert_equal false, @item.exist?
150
- end
151
-
152
- end
@@ -1,105 +0,0 @@
1
- require_relative 'test_helper'
2
- require 'tempfile'
3
- require 'tmpdir'
4
-
5
-
6
- describe Adrian::Filters do
7
- before do
8
- @q = Object.new.extend(Adrian::Filters)
9
- @item = Adrian::QueueItem.new("hello")
10
- end
11
-
12
- class FakeFilter
13
-
14
- def initialize(options = {})
15
- @allow = options.fetch(:allow)
16
- end
17
-
18
- def allow?(item)
19
- @allow == true
20
- end
21
-
22
- end
23
-
24
- describe "#filter?" do
25
-
26
- it "is true when any filter denies the item" do
27
- @q.filters << FakeFilter.new(:allow => true)
28
- @q.filters << FakeFilter.new(:allow => false)
29
-
30
- assert_equal true, @q.filter?(@item)
31
- end
32
-
33
- it "is false when all filters allow the item" do
34
- @q.filters << FakeFilter.new(:allow => true)
35
- assert_equal false, @q.filter?(@item)
36
- end
37
-
38
- end
39
-
40
- module Updatable
41
- attr_accessor :updated_at
42
- end
43
-
44
- describe Adrian::Filters::Delay do
45
- before do
46
- @filter = Adrian::Filters::Delay.new
47
- @updatable_item = Adrian::QueueItem.new("hello")
48
- @updatable_item.extend(Updatable)
49
- @updatable_item.updated_at = Time.now
50
- @fifteen_minutes = 900
51
- end
52
-
53
- it "allows items that have not been recently updated" do
54
- Time.stub(:now, @updatable_item.updated_at + @fifteen_minutes) do
55
- assert_equal true, @filter.allow?(@updatable_item)
56
- end
57
- end
58
-
59
- it "denies items that have been recently updated" do
60
- assert_equal false, @filter.allow?(@updatable_item)
61
- end
62
-
63
- it "has a configurable recently updated duration that defaults to 15 minutes" do
64
- assert_equal @fifteen_minutes, @filter.duration
65
- configured_filter = Adrian::Filters::Delay.new(:duration => 1)
66
-
67
- assert_equal 1, configured_filter.duration
68
- end
69
-
70
- end
71
-
72
- describe Adrian::Filters::FileLock do
73
- before do
74
- @filter = Adrian::Filters::FileLock.new(:reserved_path => 'path/to/locked')
75
- @available_item = Adrian::FileItem.new("path/to/file")
76
- @locked_item = Adrian::FileItem.new("path/to/locked/file")
77
- @one_hour = 3_600
78
- end
79
-
80
- it "allows items that are not locked" do
81
- assert_equal true, @filter.allow?(@available_item)
82
- end
83
-
84
- it "allows items with an expired lock" do
85
- @locked_item.stub(:updated_at, Time.now - @one_hour) do
86
- assert_equal true, @filter.allow?(@locked_item)
87
- end
88
- end
89
-
90
- it "does not allow items with a fresh lock" do
91
- @locked_item.stub(:updated_at, Time.now) do
92
- assert_equal false, @filter.allow?(@locked_item)
93
- end
94
- end
95
-
96
- it "has a configurable lock expiry duration that defaults to one hour" do
97
- assert_equal @one_hour, @filter.duration
98
- configured_filter = Adrian::Filters::FileLock.new(:duration => 1, :reserved_path => 'path/to/locked')
99
-
100
- assert_equal 1, configured_filter.duration
101
- end
102
-
103
- end
104
-
105
- end
@@ -1,28 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- describe Adrian::GirlFridayDispatcher do
4
- before do
5
- $done_items = []
6
- @q = Adrian::ArrayQueue.new
7
- @dispatcher = Adrian::GirlFridayDispatcher.new(:stop_when_done => true)
8
- end
9
-
10
- describe "work delegation" do
11
- it "should instantiate an instance of the worker for each item and ask it to perform" do
12
- worker = Class.new(Adrian::Worker) do
13
- def work
14
- sleep(rand)
15
- $done_items << @item.value
16
- end
17
- end
18
-
19
- @q.push(1)
20
- @q.push(2)
21
- @q.push(3)
22
-
23
- @dispatcher.start(@q, worker)
24
-
25
- $done_items.sort.must_equal([1, 2, 3])
26
- end
27
- end
28
- end
@@ -1,48 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- describe Adrian::Queue do
4
- class TestQueue < Adrian::Queue
5
- attr_accessor :item
6
-
7
- def pop_item
8
- @item
9
- end
10
-
11
- def push_item(item)
12
- @item = item
13
- end
14
- end
15
-
16
- describe 'when a max age is defined' do
17
- before { @q = TestQueue.new(:max_age => 60) }
18
-
19
- it 'validates the age of items' do
20
- item = Adrian::QueueItem.new('value', Time.now)
21
- @q.push(item)
22
- @q.pop.must_equal item
23
-
24
- item = Adrian::QueueItem.new('value', Time.now - 120)
25
- @q.push(item)
26
- lambda { @q.pop }.must_raise(Adrian::Queue::ItemTooOldError)
27
- end
28
-
29
- end
30
-
31
- it 'sets the queue on the items' do
32
- q = TestQueue.new
33
-
34
- item = Adrian::QueueItem.new('value', Time.now)
35
-
36
- item.queue.must_be_nil
37
-
38
- q.push(item)
39
-
40
- item.queue.must_be_nil
41
-
42
- popped_item = q.pop
43
-
44
- popped_item.must_equal item
45
- item.queue.must_equal q
46
- end
47
-
48
- end
@@ -1,55 +0,0 @@
1
- require_relative 'test_helper'
2
- require 'tempfile'
3
- require 'tmpdir'
4
- require 'fileutils'
5
-
6
- describe Adrian::RotatingDirectoryQueue do
7
- before do
8
- @root_path = Dir.mktmpdir('dir_queue_test')
9
- @q = Adrian::RotatingDirectoryQueue.create(:path => @root_path)
10
- Timecop.freeze
11
- end
12
-
13
- after do
14
- Timecop.return
15
- FileUtils.rm_r(@root_path, :force => true)
16
- end
17
-
18
- describe 'pop' do
19
- it 'only provides files available in the current time-stamped directory' do
20
- @item1 = Adrian::FileItem.new(Tempfile.new('item1').path)
21
- @item2 = Adrian::FileItem.new(Tempfile.new('item2').path)
22
- @item3 = Adrian::FileItem.new(Tempfile.new('item3').path)
23
-
24
- todays_directory = File.join(@root_path, Time.now.strftime('%Y-%m-%d'))
25
- tomorrows_directory = File.join(@root_path, (Time.now + 60 * 60 * 24).strftime('%Y-%m-%d'))
26
-
27
- FileUtils.mkdir_p(todays_directory)
28
- FileUtils.mkdir_p(tomorrows_directory)
29
-
30
- @item1.move(todays_directory)
31
- @item2.move(tomorrows_directory)
32
- @item3.move(@root_path)
33
-
34
- @q.pop.must_equal @item1
35
- @q.pop.must_be_nil
36
- end
37
- end
38
-
39
- describe 'push' do
40
- before do
41
- @item = Adrian::FileItem.new(Tempfile.new('item').path)
42
- end
43
-
44
- it 'moves the file to the time-stamped available directory' do
45
- original_path = @item.path
46
- @q.push(@item)
47
-
48
- assert_equal false, File.exist?(original_path)
49
- assert_equal true, File.exist?(File.join(@q.available_path, @item.name))
50
-
51
- @item.path.must_equal File.join(@root_path, Time.now.strftime('%Y-%m-%d'), @item.name)
52
- end
53
- end
54
-
55
- end
@@ -1,13 +0,0 @@
1
- require 'bundler/setup'
2
-
3
- begin
4
- require 'debugger'
5
- rescue LoadError => e
6
- end
7
-
8
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
9
-
10
- require 'adrian'
11
-
12
- require 'minitest/autorun'
13
- require 'timecop'
@@ -1,38 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- describe Adrian::Worker do
4
- describe "#perform" do
5
- before { @item = 2}
6
-
7
- it "should report back to the boss" do
8
- worker_class = Class.new(Adrian::Worker) do
9
- def work; item + 2; end
10
- end
11
-
12
- worker = worker_class.new(@item)
13
- boss = MiniTest::Mock.new
14
- worker.report_to(boss)
15
-
16
- boss.expect(:work_done, nil, [@item, worker, nil])
17
- worker.perform
18
-
19
- boss.verify
20
- end
21
-
22
- it "should NEVER raise an exception" do
23
- worker_class = Class.new(Adrian::Worker) do
24
- def work; raise "STRIKE!"; end
25
- end
26
-
27
- worker = worker_class.new(@item)
28
- boss = MiniTest::Mock.new
29
- worker.report_to(boss)
30
-
31
- boss.expect(:work_done, nil, [@item, worker, RuntimeError])
32
-
33
- worker.perform
34
-
35
- boss.verify
36
- end
37
- end
38
- end