refinery 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.autotest +10 -0
- data/.gitignore +5 -0
- data/CHANGELOG +1 -0
- data/LICENSE +21 -0
- data/README.rdoc +50 -0
- data/README.textile +50 -0
- data/Rakefile +39 -0
- data/VERSION +1 -0
- data/bin/epub +53 -0
- data/bin/monitor +47 -0
- data/bin/pubnow +61 -0
- data/bin/refinery +53 -0
- data/config/config.example.yml +18 -0
- data/lib/refinery/config.rb +48 -0
- data/lib/refinery/configurable.rb +15 -0
- data/lib/refinery/daemon.rb +124 -0
- data/lib/refinery/event_publisher.rb +120 -0
- data/lib/refinery/heartbeat.rb +30 -0
- data/lib/refinery/loggable.rb +9 -0
- data/lib/refinery/monitor.rb +116 -0
- data/lib/refinery/publisher.rb +24 -0
- data/lib/refinery/queueable.rb +20 -0
- data/lib/refinery/server.rb +86 -0
- data/lib/refinery/statistics.rb +61 -0
- data/lib/refinery/stats_server.rb +134 -0
- data/lib/refinery/utilities.rb +33 -0
- data/lib/refinery/validations.rb +48 -0
- data/lib/refinery/worker.rb +65 -0
- data/lib/refinery.rb +74 -0
- data/logs/README +1 -0
- data/publishers/error.rb +8 -0
- data/publishers/sample.rb +8 -0
- data/publishers/sleep.rb +7 -0
- data/refinery.gemspec +105 -0
- data/test/config.yml +10 -0
- data/test/test_helper.rb +21 -0
- data/test/unit/config_test.rb +42 -0
- data/test/unit/configurable_test.rb +11 -0
- data/test/unit/daemon_test.rb +37 -0
- data/test/unit/event_publisher_test.rb +11 -0
- data/test/unit/heartbeat_test.rb +22 -0
- data/test/unit/loggable_test.rb +11 -0
- data/test/unit/publisher_test.rb +13 -0
- data/test/unit/queueable_test.rb +24 -0
- data/test/unit/server_test.rb +39 -0
- data/test/unit/statistics_test.rb +41 -0
- data/test/unit/utilities_test.rb +25 -0
- data/test/unit/validations_test.rb +37 -0
- data/test/unit/worker_test.rb +44 -0
- data/workers/error.rb +8 -0
- data/workers/sample.rb +8 -0
- data/workers/sleep.rb +7 -0
- metadata +122 -0
@@ -0,0 +1,65 @@
|
|
1
|
+
module Refinery #:nodoc:
|
2
|
+
# Base class for workers. Place subclasses of this in the workers
|
3
|
+
# directory.
|
4
|
+
#
|
5
|
+
# Workers may include validation logic to verify that the message
|
6
|
+
# has the correct keys and values before processing.
|
7
|
+
class Worker
|
8
|
+
include Refinery::Loggable
|
9
|
+
include Refinery::Configurable
|
10
|
+
include Refinery::Utilities
|
11
|
+
include Refinery::Validations
|
12
|
+
include Refinery::Queueable
|
13
|
+
|
14
|
+
# Initialize the worker with the given daemon.
|
15
|
+
def initialize(daemon)
|
16
|
+
@daemon = daemon
|
17
|
+
end
|
18
|
+
|
19
|
+
# Run the worker with the given message. The result from the worker's
|
20
|
+
# <code>execute</code> method is returned along with the run time.
|
21
|
+
#
|
22
|
+
# Validation will occur prior to calling execute.
|
23
|
+
def run(message)
|
24
|
+
result = false
|
25
|
+
|
26
|
+
validate(message)
|
27
|
+
|
28
|
+
logger.debug "Executing worker #{self.class.name}"
|
29
|
+
time = Benchmark.realtime do
|
30
|
+
begin
|
31
|
+
result = execute(message)
|
32
|
+
rescue Exception => e
|
33
|
+
logger.error "Error executing worker #{self.class.name}: #{e.message}"
|
34
|
+
raise e
|
35
|
+
end
|
36
|
+
end
|
37
|
+
logger.debug "Completed worker #{self.class.name} in #{time} seconds"
|
38
|
+
return result, time
|
39
|
+
end
|
40
|
+
|
41
|
+
# Get the data store for the worker.
|
42
|
+
#
|
43
|
+
# The data store is provided through the Moneta interface.
|
44
|
+
#
|
45
|
+
# If the configuration providers a data_store:class option then that class
|
46
|
+
# will be used (the class must be in the Moneta module), otherwise
|
47
|
+
# Moneta::S3 will be used.
|
48
|
+
def data_store(options)
|
49
|
+
class_name = processor_config['workers']['data_store']['class'] rescue 'S3'
|
50
|
+
ds_class = Moneta.const_get(camelize(class_name))
|
51
|
+
(@data_store ||= {})[options] ||= ds_class.new(
|
52
|
+
:access_key_id => config['aws']['credentials']['access_key_id'],
|
53
|
+
:secret_access_key => config['aws']['credentials']['secret_access_key'],
|
54
|
+
:bucket => options[:bucket],
|
55
|
+
:multi_thread => true
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
# Get's the config element starting at the processer
|
61
|
+
def processor_config
|
62
|
+
config['processors'][daemon.name]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/refinery.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'socket'
|
5
|
+
require 'benchmark'
|
6
|
+
|
7
|
+
# The Refinery module contains all of the classes for the refinery system.
|
8
|
+
module Refinery
|
9
|
+
|
10
|
+
# Require the specified library.
|
11
|
+
#
|
12
|
+
# The short name is the require path and the display_name will be shown
|
13
|
+
# if the library cannot be loaded.
|
14
|
+
def self.require_library(short_name, display_name)
|
15
|
+
begin
|
16
|
+
require short_name
|
17
|
+
rescue LoadError
|
18
|
+
puts "#{display_name} is required, please install it"
|
19
|
+
exit
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Require all of the dependencies.
|
24
|
+
def self.require_libraries
|
25
|
+
require_library('rubygems', 'Rubygems')
|
26
|
+
require_library('right_aws', 'RightScale AWS gem')
|
27
|
+
require_library('json', 'JSON gem')
|
28
|
+
require_library('moneta', 'Moneta gem')
|
29
|
+
require_library('moneta/s3', 'Moneta S3 implementation')
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.require_optional_library(short_name, display_name)
|
33
|
+
begin
|
34
|
+
require short_name
|
35
|
+
rescue LoadError
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.require_optional_libraries
|
40
|
+
require_optional_library('sequel', 'Sequel gem')
|
41
|
+
require_optional_library('ramaze', 'Ramaze')
|
42
|
+
end
|
43
|
+
|
44
|
+
# Require internal code files
|
45
|
+
def self.require_internals
|
46
|
+
require 'refinery/loggable'
|
47
|
+
require 'refinery/configurable'
|
48
|
+
require 'refinery/queueable'
|
49
|
+
|
50
|
+
require 'refinery/utilities'
|
51
|
+
|
52
|
+
require 'refinery/validations'
|
53
|
+
|
54
|
+
require 'refinery/config'
|
55
|
+
require 'refinery/heartbeat'
|
56
|
+
require 'refinery/server'
|
57
|
+
require 'refinery/daemon'
|
58
|
+
require 'refinery/worker'
|
59
|
+
require 'refinery/event_publisher'
|
60
|
+
require 'refinery/publisher'
|
61
|
+
require 'refinery/monitor'
|
62
|
+
require 'refinery/statistics'
|
63
|
+
require 'refinery/stats_server'
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
# Raised if a source file cannot be loaded
|
68
|
+
class SourceFileNotFound < RuntimeError
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
Refinery::require_libraries
|
73
|
+
Refinery::require_optional_libraries
|
74
|
+
Refinery::require_internals
|
data/logs/README
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Log files from Refinery will be written here. Do not remove this directory.
|
data/publishers/error.rb
ADDED
data/publishers/sleep.rb
ADDED
data/refinery.gemspec
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{refinery}
|
5
|
+
s.version = "0.9.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Anthony Eden"]
|
9
|
+
s.date = %q{2009-06-01}
|
10
|
+
s.description = %q{Process data in a distributed fashion.}
|
11
|
+
s.email = %q{anthonyeden@gmail.com}
|
12
|
+
s.executables = ["epub", "monitor", "pubnow", "refinery"]
|
13
|
+
s.extra_rdoc_files = [
|
14
|
+
"LICENSE",
|
15
|
+
"README.rdoc",
|
16
|
+
"README.textile"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".autotest",
|
20
|
+
".gitignore",
|
21
|
+
"CHANGELOG",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"README.textile",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"bin/epub",
|
28
|
+
"bin/monitor",
|
29
|
+
"bin/pubnow",
|
30
|
+
"bin/refinery",
|
31
|
+
"config/config.example.yml",
|
32
|
+
"lib/refinery.rb",
|
33
|
+
"lib/refinery/config.rb",
|
34
|
+
"lib/refinery/configurable.rb",
|
35
|
+
"lib/refinery/daemon.rb",
|
36
|
+
"lib/refinery/event_publisher.rb",
|
37
|
+
"lib/refinery/heartbeat.rb",
|
38
|
+
"lib/refinery/loggable.rb",
|
39
|
+
"lib/refinery/monitor.rb",
|
40
|
+
"lib/refinery/publisher.rb",
|
41
|
+
"lib/refinery/queueable.rb",
|
42
|
+
"lib/refinery/server.rb",
|
43
|
+
"lib/refinery/statistics.rb",
|
44
|
+
"lib/refinery/stats_server.rb",
|
45
|
+
"lib/refinery/utilities.rb",
|
46
|
+
"lib/refinery/validations.rb",
|
47
|
+
"lib/refinery/worker.rb",
|
48
|
+
"logs/README",
|
49
|
+
"publishers/error.rb",
|
50
|
+
"publishers/sample.rb",
|
51
|
+
"publishers/sleep.rb",
|
52
|
+
"refinery.gemspec",
|
53
|
+
"test/config.yml",
|
54
|
+
"test/test_helper.rb",
|
55
|
+
"test/unit/config_test.rb",
|
56
|
+
"test/unit/configurable_test.rb",
|
57
|
+
"test/unit/daemon_test.rb",
|
58
|
+
"test/unit/event_publisher_test.rb",
|
59
|
+
"test/unit/heartbeat_test.rb",
|
60
|
+
"test/unit/loggable_test.rb",
|
61
|
+
"test/unit/publisher_test.rb",
|
62
|
+
"test/unit/queueable_test.rb",
|
63
|
+
"test/unit/server_test.rb",
|
64
|
+
"test/unit/statistics_test.rb",
|
65
|
+
"test/unit/utilities_test.rb",
|
66
|
+
"test/unit/validations_test.rb",
|
67
|
+
"test/unit/worker_test.rb",
|
68
|
+
"workers/error.rb",
|
69
|
+
"workers/sample.rb",
|
70
|
+
"workers/sleep.rb"
|
71
|
+
]
|
72
|
+
s.has_rdoc = true
|
73
|
+
s.homepage = %q{http://github.com/aeden/refinery}
|
74
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
75
|
+
s.require_paths = ["lib"]
|
76
|
+
s.rubyforge_project = %q{refinery}
|
77
|
+
s.rubygems_version = %q{1.3.1}
|
78
|
+
s.summary = %q{Refinery processes data in a distributed environment.}
|
79
|
+
s.test_files = [
|
80
|
+
"test/test_helper.rb",
|
81
|
+
"test/unit/config_test.rb",
|
82
|
+
"test/unit/configurable_test.rb",
|
83
|
+
"test/unit/daemon_test.rb",
|
84
|
+
"test/unit/event_publisher_test.rb",
|
85
|
+
"test/unit/heartbeat_test.rb",
|
86
|
+
"test/unit/loggable_test.rb",
|
87
|
+
"test/unit/publisher_test.rb",
|
88
|
+
"test/unit/queueable_test.rb",
|
89
|
+
"test/unit/server_test.rb",
|
90
|
+
"test/unit/statistics_test.rb",
|
91
|
+
"test/unit/utilities_test.rb",
|
92
|
+
"test/unit/validations_test.rb",
|
93
|
+
"test/unit/worker_test.rb"
|
94
|
+
]
|
95
|
+
|
96
|
+
if s.respond_to? :specification_version then
|
97
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
98
|
+
s.specification_version = 2
|
99
|
+
|
100
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
101
|
+
else
|
102
|
+
end
|
103
|
+
else
|
104
|
+
end
|
105
|
+
end
|
data/test/config.yml
ADDED
data/test/test_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'mocha'
|
5
|
+
require File.dirname(__FILE__) + '/../lib/refinery'
|
6
|
+
|
7
|
+
class Test::Unit::TestCase
|
8
|
+
def setup_default_config
|
9
|
+
Refinery::Config.stubs(:default).returns(Refinery::Config.new(
|
10
|
+
{
|
11
|
+
'aws' => {
|
12
|
+
'credentials' => {
|
13
|
+
'access_key_id' => 'aki',
|
14
|
+
'secret_access_key' => 'sak'
|
15
|
+
}
|
16
|
+
},
|
17
|
+
'processors' => []
|
18
|
+
}
|
19
|
+
))
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class ConfigTest < Test::Unit::TestCase
|
4
|
+
context "the config class" do
|
5
|
+
should "provide a default configuration" do
|
6
|
+
assert_not_nil Refinery::Config.default
|
7
|
+
end
|
8
|
+
|
9
|
+
context "default configuration" do
|
10
|
+
setup do
|
11
|
+
@config = Refinery::Config.default
|
12
|
+
end
|
13
|
+
should "provide an empty aws credentials hash" do
|
14
|
+
assert_equal Hash.new, @config['aws']['credentials']
|
15
|
+
end
|
16
|
+
should "provide an empty processors hash" do
|
17
|
+
assert_equal Hash.new, @config['processors']
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "after loading configuration from a YAML file" do
|
22
|
+
setup do
|
23
|
+
@config_file = File.dirname(__FILE__) + '/../config.yml'
|
24
|
+
@config = Refinery::Config.new
|
25
|
+
@config.load_file(@config_file)
|
26
|
+
end
|
27
|
+
should "have aws credentials" do
|
28
|
+
assert_equal 'aaa', @config['aws']['credentials']['access_key_id']
|
29
|
+
assert_equal 'bbb', @config['aws']['credentials']['secret_access_key']
|
30
|
+
end
|
31
|
+
should "reload the file when changed" do
|
32
|
+
`touch #{@config_file}`
|
33
|
+
YAML.expects(:load_file).once
|
34
|
+
@config.refresh
|
35
|
+
end
|
36
|
+
should "not reload the file when not changed" do
|
37
|
+
YAML.expects(:load_file).never
|
38
|
+
@config.refresh
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
class ConfigureMe
|
3
|
+
include Refinery::Configurable
|
4
|
+
end
|
5
|
+
class ConfigurableTest < Test::Unit::TestCase
|
6
|
+
context "a class with the configurable module" do
|
7
|
+
should "provide a config" do
|
8
|
+
assert_not_nil ConfigureMe.new.config
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
class DaemonTest < Test::Unit::TestCase
|
3
|
+
context "a daemon" do
|
4
|
+
setup do
|
5
|
+
@server = stub('Server')
|
6
|
+
@waiting_queue = stub('Queue(waiting)')
|
7
|
+
@waiting_queue.stubs(:receive)
|
8
|
+
@error_queue = stub('Queue(error)')
|
9
|
+
@done_queue = stub('Queue(done)')
|
10
|
+
end
|
11
|
+
should "be startable" do
|
12
|
+
assert_nothing_raised do
|
13
|
+
daemon = Refinery::Daemon.new(@server, 'sample', @waiting_queue, @error_queue, @done_queue)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
should "have logging" do
|
17
|
+
daemon = Refinery::Daemon.new(@server, 'sample', @waiting_queue, @error_queue, @done_queue)
|
18
|
+
assert_not_nil daemon.logger
|
19
|
+
end
|
20
|
+
context "that is started" do
|
21
|
+
setup do
|
22
|
+
@daemon = Refinery::Daemon.new(@server, 'sample', @waiting_queue, @error_queue, @done_queue)
|
23
|
+
end
|
24
|
+
should "have a state of running" do
|
25
|
+
assert @daemon.running?
|
26
|
+
end
|
27
|
+
context "after calling stop" do
|
28
|
+
setup do
|
29
|
+
@daemon.stop
|
30
|
+
end
|
31
|
+
should "not be running" do
|
32
|
+
assert !@daemon.running?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
class EventPublisherTest < Test::Unit::TestCase
|
3
|
+
context "an event publisher" do
|
4
|
+
should "raise an error if credentials are not set" do
|
5
|
+
publishing_settings = {'sample' => {'delay' => 10}}
|
6
|
+
Refinery::Config.any_instance.stubs(:publishing).returns(publishing_settings)
|
7
|
+
event_publisher = Refinery::EventPublisher.new
|
8
|
+
event_publisher.run
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
class HeartbeatTest < Test::Unit::TestCase
|
3
|
+
context "a heartbeat" do
|
4
|
+
setup do
|
5
|
+
setup_default_config
|
6
|
+
|
7
|
+
@server = stub('server')
|
8
|
+
@server.stubs(:daemons).returns([])
|
9
|
+
|
10
|
+
heartbeat_queue = stub('heartbeat queue')
|
11
|
+
heartbeat_queue.stubs(:send_message)
|
12
|
+
queue_provider = stub('queue provider')
|
13
|
+
queue_provider.expects(:queue).with('heartbeat').returns(heartbeat_queue)
|
14
|
+
RightAws::SqsGen2.stubs(:new).with(
|
15
|
+
'aki', 'sak', {:multi_thread => true}
|
16
|
+
).returns(queue_provider)
|
17
|
+
end
|
18
|
+
should "be initializable" do
|
19
|
+
Refinery::Heartbeat.new(@server)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
class LogMe
|
3
|
+
include Refinery::Loggable
|
4
|
+
end
|
5
|
+
class LoggableTest < Test::Unit::TestCase
|
6
|
+
context "a class with Loggable mixed in" do
|
7
|
+
should "have a logger" do
|
8
|
+
assert_not_nil LogMe.new.logger
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class SamplePublisher < Refinery::Publisher
|
4
|
+
end
|
5
|
+
|
6
|
+
class PublisherTest < Test::Unit::TestCase
|
7
|
+
context "a publisher" do
|
8
|
+
should "be instantiable" do
|
9
|
+
waiting_queue = stub('waiting queue')
|
10
|
+
SamplePublisher.new(waiting_queue)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class QueueMe
|
4
|
+
include Refinery::Configurable
|
5
|
+
include Refinery::Queueable
|
6
|
+
end
|
7
|
+
|
8
|
+
class QueueableTest < Test::Unit::TestCase
|
9
|
+
context "a class with the Queuable module" do
|
10
|
+
should "provide a queue" do
|
11
|
+
setup_default_config
|
12
|
+
|
13
|
+
queue = stub('queue')
|
14
|
+
queue_provider = stub('queue provider')
|
15
|
+
queue_provider.expects(:queue).with('a_queue').returns(queue)
|
16
|
+
RightAws::SqsGen2.expects(:new).with(
|
17
|
+
'aki', 'sak', {:multi_thread => true}
|
18
|
+
).returns(queue_provider)
|
19
|
+
|
20
|
+
queueable = QueueMe.new
|
21
|
+
assert_not_nil queueable.queue('a_queue')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
class ServerTest < Test::Unit::TestCase
|
3
|
+
context "the server class" do
|
4
|
+
should "provide a logger" do
|
5
|
+
assert_not_nil Refinery::Server.logger
|
6
|
+
end
|
7
|
+
context "logger" do
|
8
|
+
should "default to WARN level" do
|
9
|
+
assert_equal Logger::WARN, Refinery::Server.logger.level
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
context "a server instance" do
|
14
|
+
setup do
|
15
|
+
@server = Refinery::Server.new
|
16
|
+
end
|
17
|
+
should "have a config" do
|
18
|
+
assert_not_nil @server.config
|
19
|
+
end
|
20
|
+
should "be runnable" do
|
21
|
+
setup_default_config
|
22
|
+
|
23
|
+
heartbeat_queue = stub('heartbeat queue')
|
24
|
+
heartbeat_queue.stubs(:send_message)
|
25
|
+
queue_provider = stub('queue provider')
|
26
|
+
queue_provider.expects(:queue).with('heartbeat').returns(heartbeat_queue)
|
27
|
+
RightAws::SqsGen2.expects(:new).with(
|
28
|
+
'aki', 'sak', {:multi_thread => true}
|
29
|
+
).returns(queue_provider)
|
30
|
+
|
31
|
+
assert_nothing_raised do
|
32
|
+
thread = Thread.new do
|
33
|
+
@server.run
|
34
|
+
end
|
35
|
+
@server.stop
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class StatisticsTest < Test::Unit::TestCase
|
4
|
+
context "a statistics instance" do
|
5
|
+
should "record a done message" do
|
6
|
+
dataset = stub('dataset')
|
7
|
+
dataset.expects(:<<) # TODO: improve this expectation
|
8
|
+
|
9
|
+
db = stub('db')
|
10
|
+
db.stubs(:table_exists?).returns(true)
|
11
|
+
db.stubs(:[]).with(:completed_jobs).returns(dataset)
|
12
|
+
|
13
|
+
Sequel.expects(:connect).with('sqlite://stats.db').returns(db)
|
14
|
+
|
15
|
+
message = {
|
16
|
+
'host_info' => {'hostname' => 'test', 'pid' => 1},
|
17
|
+
'run_time' => 1,
|
18
|
+
'original' => ''
|
19
|
+
}
|
20
|
+
Refinery::Statistics.new.record_done(message)
|
21
|
+
end
|
22
|
+
|
23
|
+
should "record an error message" do
|
24
|
+
dataset = stub('dataset')
|
25
|
+
dataset.expects(:<<) # TODO: improve this expectation
|
26
|
+
|
27
|
+
db = stub('db')
|
28
|
+
db.stubs(:table_exists?).returns(true)
|
29
|
+
db.stubs(:[]).with(:errors).returns(dataset)
|
30
|
+
|
31
|
+
Sequel.expects(:connect).with('sqlite://stats.db').returns(db)
|
32
|
+
|
33
|
+
message = {
|
34
|
+
'host_info' => {'hostname' => 'test', 'pid' => 1},
|
35
|
+
'error' => {'class' => 'Error', 'message' => 'An error occurred.'},
|
36
|
+
'original' => ''
|
37
|
+
}
|
38
|
+
Refinery::Statistics.new.record_error(message)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class UtilitiesIncluded
|
4
|
+
include Refinery::Utilities
|
5
|
+
end
|
6
|
+
|
7
|
+
class UtilitiesTest < Test::Unit::TestCase
|
8
|
+
context "a class with utilities included" do
|
9
|
+
setup do
|
10
|
+
@o = UtilitiesIncluded.new
|
11
|
+
end
|
12
|
+
should "camelize a word" do
|
13
|
+
|
14
|
+
assert_equal 'ClassName', @o.camelize('class_name')
|
15
|
+
end
|
16
|
+
should "encode and decode message" do
|
17
|
+
message = {'some' => 'message'}
|
18
|
+
assert_equal message, @o.decode_message(@o.encode_message(message))
|
19
|
+
end
|
20
|
+
should "provide host info" do
|
21
|
+
assert_not_nil @o.host_info['pid']
|
22
|
+
assert_not_nil @o.host_info['hostname']
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class ValidatedWorker < Refinery::Worker
|
4
|
+
include Refinery::Validations
|
5
|
+
validate_with do |message|
|
6
|
+
raise Refinery::InvalidMessageError, "A message is required" unless message
|
7
|
+
end
|
8
|
+
validates_key_exists :test
|
9
|
+
|
10
|
+
def execute(message)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
class ValidationsTest < Test::Unit::TestCase
|
14
|
+
context "a validated worker" do
|
15
|
+
setup do
|
16
|
+
daemon = stub('daemon')
|
17
|
+
@worker = ValidatedWorker.new(daemon)
|
18
|
+
end
|
19
|
+
should "raise a validation error if the key does not exist" do
|
20
|
+
message = {}
|
21
|
+
assert_raise Refinery::InvalidMessageError do
|
22
|
+
@worker.run(message)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
should "not raise a validation error if the key does exist" do
|
26
|
+
message = {:test => 'ding!'}
|
27
|
+
assert_nothing_raised do
|
28
|
+
@worker.run(message)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
should "raise a validation error if the message is nil" do
|
32
|
+
assert_raise Refinery::InvalidMessageError do
|
33
|
+
@worker.run(nil)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class SampleWorker < Refinery::Worker
|
4
|
+
attr_reader :message
|
5
|
+
def execute(message)
|
6
|
+
@message = message
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class WorkerTest < Test::Unit::TestCase
|
11
|
+
context "a worker" do
|
12
|
+
setup do
|
13
|
+
daemon = stub('daemon')
|
14
|
+
@worker = SampleWorker.new(daemon)
|
15
|
+
@message = {'test' => 'value'}
|
16
|
+
end
|
17
|
+
should "run" do
|
18
|
+
@worker.run(@message)
|
19
|
+
assert_equal @message, @worker.message
|
20
|
+
end
|
21
|
+
should "provide a data store" do
|
22
|
+
options = {:bucket => 'bucket'}
|
23
|
+
|
24
|
+
data_store = stub('data store')
|
25
|
+
|
26
|
+
Moneta::S3.expects(:new).with(
|
27
|
+
:access_key_id => 'aki',
|
28
|
+
:secret_access_key => 'sak',
|
29
|
+
:bucket => options[:bucket],
|
30
|
+
:multi_thread => true
|
31
|
+
).returns(data_store)
|
32
|
+
|
33
|
+
setup_default_config
|
34
|
+
assert_not_nil @worker.data_store(options)
|
35
|
+
end
|
36
|
+
should "provide a queue" do
|
37
|
+
queue = stub('queue')
|
38
|
+
queue_provider = stub('queue provider')
|
39
|
+
queue_provider.expects(:queue).with('a_queue').returns(queue)
|
40
|
+
@worker.expects(:queue_provider).returns(queue_provider)
|
41
|
+
assert_not_nil @worker.queue('a_queue')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|