refinery 0.12.2 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/lib/refinery.rb +1 -99
  2. data/refinery.gemspec +16 -117
  3. metadata +39 -118
  4. data/.gitignore +0 -6
  5. data/CHANGELOG +0 -2
  6. data/LICENSE +0 -21
  7. data/README.rdoc +0 -58
  8. data/README.textile +0 -58
  9. data/Rakefile +0 -43
  10. data/VERSION +0 -1
  11. data/bin/epub +0 -64
  12. data/bin/monitor +0 -47
  13. data/bin/pubnow +0 -61
  14. data/bin/refinery +0 -64
  15. data/config/config.example.yml +0 -21
  16. data/lib/refinery/beanstalk_queue.rb +0 -36
  17. data/lib/refinery/beanstalk_queue_provider.rb +0 -18
  18. data/lib/refinery/config.rb +0 -48
  19. data/lib/refinery/configurable.rb +0 -15
  20. data/lib/refinery/daemon.rb +0 -148
  21. data/lib/refinery/event_publisher.rb +0 -131
  22. data/lib/refinery/heartbeat.rb +0 -33
  23. data/lib/refinery/loggable.rb +0 -9
  24. data/lib/refinery/monitor.rb +0 -113
  25. data/lib/refinery/processor.rb +0 -55
  26. data/lib/refinery/publisher.rb +0 -42
  27. data/lib/refinery/queueable.rb +0 -48
  28. data/lib/refinery/server.rb +0 -88
  29. data/lib/refinery/statistics.rb +0 -61
  30. data/lib/refinery/stats_server.rb +0 -135
  31. data/lib/refinery/utilities.rb +0 -33
  32. data/lib/refinery/validations.rb +0 -48
  33. data/lib/refinery/worker.rb +0 -65
  34. data/logs/README +0 -1
  35. data/publishers/error.rb +0 -6
  36. data/publishers/sample.rb +0 -6
  37. data/publishers/sleep.rb +0 -5
  38. data/test/config.yml +0 -10
  39. data/test/test_helper.rb +0 -21
  40. data/test/unit/config_test.rb +0 -42
  41. data/test/unit/configurable_test.rb +0 -13
  42. data/test/unit/daemon_test.rb +0 -63
  43. data/test/unit/event_publisher_test.rb +0 -12
  44. data/test/unit/heartbeat_test.rb +0 -25
  45. data/test/unit/loggable_test.rb +0 -12
  46. data/test/unit/processor_test.rb +0 -34
  47. data/test/unit/publisher_test.rb +0 -13
  48. data/test/unit/queueable_test.rb +0 -26
  49. data/test/unit/server_test.rb +0 -34
  50. data/test/unit/statistics_test.rb +0 -44
  51. data/test/unit/utilities_test.rb +0 -25
  52. data/test/unit/validations_test.rb +0 -37
  53. data/test/unit/worker_test.rb +0 -44
  54. data/workers/error.rb +0 -8
  55. data/workers/sample.rb +0 -8
  56. data/workers/sleep.rb +0 -7
@@ -1,18 +0,0 @@
1
- module Refinery #:nodoc:
2
- # A queue provider for beanstalk
3
- class BeanstalkQueueProvider
4
- include Refinery::Loggable
5
-
6
- attr_reader :queues
7
-
8
- # Initialize the queue provider
9
- def initialize(hosts=nil)
10
- @hosts = hosts
11
- @queues = {}
12
- end
13
- # Get the named queue
14
- def queue(name)
15
- queues[name] ||= Refinery::BeanstalkQueue.new(name, @hosts)
16
- end
17
- end
18
- end
@@ -1,48 +0,0 @@
1
- module Refinery #:nodoc:
2
- # Configuration class.
3
- class Config
4
- # Get a shared configuration
5
- def self.default
6
- @default ||= new({
7
- 'aws' => {
8
- 'credentials' => {}
9
- },
10
- 'processors' => {}
11
- })
12
- end
13
-
14
- # Initialize the config with the given data
15
- def initialize(data={})
16
- @data = data
17
- end
18
-
19
- # Get the configuration value
20
- def [](key)
21
- data[key.to_s]
22
- end
23
-
24
- # Set the configuration value
25
- def []=(key, value)
26
- data[key.to_s] = value
27
- end
28
-
29
- # Load configuration from a YAML file
30
- def load_file(file)
31
- @file = file
32
- @data = YAML::load_file(@file)
33
- @last_load = File.mtime(@file)
34
- end
35
-
36
- # Refresh the configuration from the YAML file if necessary.
37
- def refresh
38
- if File.mtime(@file) != @last_load
39
- @data = YAML::load_file(@file)
40
- end
41
- end
42
-
43
- private
44
- def data
45
- @data ||= {}
46
- end
47
- end
48
- end
@@ -1,15 +0,0 @@
1
- module Refinery #:nodoc:
2
- # Include this module to get access to a shared configuration
3
- module Configurable
4
- # Get the configuration. If the config is nil then this will use
5
- # the default shared configuration.
6
- def config
7
- @config ||= Refinery::Config.default
8
- end
9
-
10
- # Set the configuration.
11
- def config=(config)
12
- @config = config
13
- end
14
- end
15
- end
@@ -1,148 +0,0 @@
1
- module Refinery #:nodoc:
2
- # A daemon provides a thread to run workers in.
3
- class Daemon < Thread
4
- include Refinery::Loggable
5
- include Refinery::Configurable
6
- include Refinery::Utilities
7
- include Refinery::Queueable
8
-
9
- RUNNING = 'running'
10
- STOPPED = 'stopped'
11
-
12
- # The name of the daemon
13
- attr_reader :name
14
- # The settings for the daemon
15
- attr_reader :settings
16
- # The base queue name
17
- attr_reader :queue_name
18
-
19
- # Stop the daemon
20
- def stop
21
- self.state = STOPPED
22
- end
23
-
24
- # Return the daemon state
25
- def state
26
- @state ||= RUNNING
27
- end
28
-
29
- # Set the daemon state.
30
- def state=(state)
31
- @state = state
32
- end
33
- protected :state
34
-
35
- # Return true if the daemon state is running.
36
- def running?
37
- state == RUNNING
38
- end
39
-
40
- # Initialize the daemon.
41
- #
42
- # * <tt>processor</tt>: The processor instance
43
- # * <tt>name</tt>: The processor name
44
- # * <tt>waiting_queue</tt>: The waiting queue that provides messages to be processed
45
- # * <tt>error_queue</tt>: The queue where errors are posted.
46
- # * <tt>done_queue</tt>: The queue for messages that have been processed.
47
- # * <tt>settings</tt>: The settings hash from the config.
48
- #
49
- # The settings hash may contain the following options:
50
- # * <tt>visibility</tt>: The time in seconds that the message is hidden
51
- # in the queue.
52
- def initialize(processor, name, queue_prefix='', settings={})
53
- logger.debug "Starting daemon"
54
-
55
- @processor = processor
56
- @name = name
57
- @settings = settings
58
-
59
- queue_name = settings['queue'] || name
60
- queue_name = "#{queue_prefix}#{queue_name}"
61
- logger.debug "Using queue #{queue_name}"
62
- @queue_name = queue_name
63
-
64
- super do
65
- begin
66
- execute
67
- rescue Exception => e
68
- logger.error e
69
- end
70
- end
71
- end
72
-
73
- private
74
- def execute
75
- logger.debug "Running daemon thread: #{name} (settings: #{settings.inspect})"
76
-
77
- if defined?(java.lang.Thread)
78
- java.lang.Thread.current_thread.name = "#{name} Daemon"
79
- end
80
-
81
- while(running?)
82
- #logger.debug "Checking #{queue_name}_waiting"
83
- with_queue("#{queue_name}_waiting") do |waiting_queue|
84
- while (message = waiting_queue.receive(settings['visibility']))
85
- worker = load_worker_class(name).new(self)
86
- begin
87
- result, run_time = worker.run(decode_message(message.body))
88
- if result
89
- with_queue("#{queue_name}_done") do |done_queue|
90
- done_message = {
91
- 'host_info' => host_info,
92
- 'original' => message.body,
93
- 'run_time' => run_time
94
- }
95
- logger.debug "Sending 'done' message to #{done_queue.name}"
96
- done_queue.send_message(encode_message(done_message))
97
- end
98
-
99
- logger.debug "Deleting message from queue"
100
- message.delete()
101
- end
102
- rescue Exception => e
103
- with_queue("#{queue_name}_error") do |error_queue|
104
- error_message = {
105
- 'error' => {
106
- 'message' => e.message,
107
- 'class' => e.class.name,
108
- 'backtrace' => e.backtrace
109
- },
110
- 'host_info' => host_info,
111
- 'original' => message.body
112
- }
113
- logger.error "Sending 'error' message to #{error_queue.name}: #{e.message}"
114
- error_queue.send_message(encode_message(error_message))
115
- end
116
- message.delete()
117
- end
118
- end
119
- sleep(settings['sleep'] || 5)
120
- end
121
- end
122
- logger.debug "Exiting daemon thread"
123
- end
124
-
125
- # A hash of worker classes
126
- def workers
127
- @workers ||= {}
128
- end
129
-
130
- private
131
- # Load the appropriate worker class
132
- def load_worker_class(name)
133
- source_file = "#{@processor.server.workers_directory}/#{name}.rb"
134
- if File.exist?(source_file)
135
- modified_at = File.mtime(source_file)
136
- if workers[name] != modified_at
137
- logger.debug "Loading #{source_file}"
138
- load(source_file)
139
- workers[name] = modified_at
140
- end
141
- else
142
- raise SourceFileNotFound, "Source file not found: #{source_file}"
143
- end
144
-
145
- Object.const_get(camelize("#{name}_worker"))
146
- end
147
- end
148
- end
@@ -1,131 +0,0 @@
1
- module Refinery #:nodoc:
2
- # Publish events.
3
- class EventPublisher
4
- include Refinery::Loggable
5
- include Refinery::Configurable
6
- include Refinery::Queueable
7
- include Refinery::Utilities
8
-
9
- STARTING = 'starting' #:nodoc:
10
- RUNNING = 'running' #:nodoc:
11
- STOPPED = 'stopped' #:nodoc:
12
-
13
- attr_accessor :publishers_directory
14
-
15
- # Initialize the event publisher
16
- #
17
- # Options:
18
- # * <tt>:debug</tt>: Set to true to enable debug logging
19
- # * <tt>:config</tt>: Provide a file path to load that config
20
- def initialize(options={})
21
- logger.level = Logger::INFO if options[:verbose]
22
- logger.level = Logger::DEBUG if options[:debug]
23
- config.load_file(options[:config]) if options[:config]
24
- self.publishers_directory = options[:publishers] if options[:publishers]
25
- end
26
-
27
- # Get the event publisher state
28
- def state
29
- @state ||= STARTING
30
- end
31
-
32
- # Return true if the event publisher is running
33
- def running?
34
- state == RUNNING
35
- end
36
-
37
- # The directory where publishers are found. Defaults to ./publishers
38
- def publishers_directory
39
- @publishers_directory ||= './publishers'
40
- end
41
-
42
- # A hash of all publisher classes mapped to last modified timestamps.
43
- def publishers
44
- @publishers ||= {}
45
- end
46
-
47
- # Run the specified publisher once and return
48
- def run_once(key)
49
- prefix = config['prefix'] || ''
50
- settings = config['processors'][key]
51
- raise RuntimeError, "No processor configuration found for #{key}" unless settings
52
- queue_name = settings['queue'] || key
53
- queue_name = "#{prefix}#{queue_name}"
54
- waiting_queue_name = "#{queue_name}_waiting"
55
- logger.debug "Using queue #{waiting_queue_name}"
56
- load_publisher_class(key).new(waiting_queue_name).execute
57
- end
58
-
59
- # Run the event publisher
60
- def run
61
- @state = RUNNING
62
- logger.info "Starting event publisher"
63
- config['processors'].each do |key, settings|
64
- run_publisher(key, settings)
65
- end
66
-
67
- begin
68
- threads.each { |thread| thread.join }
69
- rescue Interrupt => e
70
- end
71
-
72
- logger.info "Exiting event publisher"
73
- end
74
-
75
- private
76
- # An array of threads, one for each publisher instance
77
- def threads
78
- @threads ||= []
79
- end
80
-
81
- # Run the publisher for the given key
82
- def run_publisher(key, settings)
83
- if File.exists?(source_file(key))
84
- prefix = config['prefix'] || ''
85
- logger.info "Creating publisher for #{key}"
86
- queue_name = settings['queue'] || key
87
- queue_name = "#{prefix}#{queue_name}"
88
- waiting_queue_name = "#{queue_name}_waiting"
89
- logger.debug "Using queue #{waiting_queue_name}"
90
-
91
- threads << Thread.new(waiting_queue_name, settings) do |waiting_queue_name, settings|
92
- while(running?)
93
- begin
94
- load_publisher_class(key).new(waiting_queue_name).execute
95
- rescue Exception => e
96
- logger.error "Error running publisher: #{e.message}"
97
- end
98
-
99
- delay = settings['publishers']['delay'] || 60
100
- logger.debug "Sleeping #{delay} seconds"
101
- sleep delay
102
-
103
- end
104
- end
105
- else
106
- logger.warn "No publisher found for #{key}"
107
- end
108
- end
109
-
110
- def source_file(key)
111
- source_file = "#{publishers_directory}/#{key}.rb"
112
- end
113
-
114
- def load_publisher_class(key)
115
- source_file = source_file(key)
116
- if File.exist?(source_file)
117
- modified_at = File.mtime(source_file)
118
- if publishers[key] != modified_at
119
- logger.debug "Loading #{source_file}"
120
- load(source_file)
121
- publishers[key] = modified_at
122
- end
123
- else
124
- raise SourceFileNotFound, "Source file not found: #{source_file}"
125
- end
126
-
127
- Object.const_get(camelize("#{key}_publisher"))
128
- end
129
-
130
- end
131
- end
@@ -1,33 +0,0 @@
1
- module Refinery #:nodoc:
2
- # A heartbeat publisher that indicates a server is alive.
3
- class Heartbeat
4
- include Refinery::Loggable
5
- include Refinery::Configurable
6
- include Refinery::Queueable
7
- include Refinery::Utilities
8
-
9
- # Initialize the heartbeat for the given server.
10
- def initialize(server)
11
- queue_prefix = config['prefix'] || ''
12
- @server = server
13
- @thread = Thread.new do
14
- if defined?(java.lang.Thread)
15
- java.lang.Thread.current_thread.name = 'Heartbeat'
16
- end
17
-
18
- loop do
19
- with_queue("#{queue_prefix}heartbeat") do |heartbeat_queue|
20
- logger.debug "Send heartbeat"
21
- message = {
22
- 'host_info' => host_info,
23
- 'timestamp' => Time.now.utc,
24
- 'running_daemons' => @server.daemons.length
25
- }
26
- heartbeat_queue.send_message(Base64.encode64(message.to_json))
27
- sleep(60)
28
- end
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,9 +0,0 @@
1
- module Refinery
2
- # Include this module to get access to the server logger
3
- module Loggable
4
- # Get the logger.
5
- def logger
6
- @logger ||= Refinery::Server.logger
7
- end
8
- end
9
- end
@@ -1,113 +0,0 @@
1
- module Refinery #:nodoc:
2
- # The monitor is responsible for monitoring the health of the various
3
- # components of refinery.
4
- class Monitor
5
- include Refinery::Loggable
6
- include Refinery::Configurable
7
- include Refinery::Queueable
8
- include Refinery::Utilities
9
-
10
- # Initialize the monitor.
11
- #
12
- # Options:
13
- # * <tt>:verbose</tt>: Enable INFO level logging
14
- # * <tt>:debug</tt>: Enable DEBUG level logging
15
- # * <tt>:config</tt>: The config file
16
- def initialize(options)
17
- logger.level = Logger::INFO if options[:verbose]
18
- logger.level = Logger::DEBUG if options[:debug]
19
- config.load_file(options[:config]) if options[:config]
20
- @queue_prefix = config['prefix'] || ''
21
- end
22
-
23
- # Execute the monitor. The monitor will start one heartbeat
24
- # monitor thread and one thread for each done queue and error
25
- # queue as specified in the configuration.
26
- def run
27
- logger.info "Starting up monitor"
28
- heartbeat_monitor_thread = run_heartbeat_monitor
29
- done_monitor_threads = run_done_monitors
30
- error_monitor_threads = run_error_monitors
31
-
32
- logger.info "Monitor running"
33
-
34
- Refinery::StatsServer.new.run
35
-
36
- begin
37
- heartbeat_monitor_thread.join
38
- done_monitor_threads.each { |t| t.join }
39
- error_monitor_threads.each { |t| t.join }
40
- rescue Interrupt => e
41
- end
42
-
43
- logger.info "Monitor is exiting"
44
- end
45
-
46
- private
47
- def statistics
48
- @statistics ||= Refinery::Statistics.new
49
- end
50
-
51
- def run_heartbeat_monitor
52
- logger.info "Starting #{@queue_prefix}heartbeat monitor"
53
- Thread.new("#{@queue_prefix}heartbeat") do |heartbeat_queue_name|
54
- loop do
55
- with_queue(heartbeat_queue_name) do |heartbeat_queue|
56
- while (message = heartbeat_queue.receive)
57
- logger.debug "#{heartbeat_queue.name}: #{decode_message(message.body).inspect}"
58
- message.delete()
59
- end
60
- end
61
- sleep(5)
62
- end
63
- end
64
- end
65
-
66
- def run_done_monitors
67
- config['processors'].collect do |key, settings|
68
- queue_name = settings['queue'] || key
69
- done_queue_name = "#{@queue_prefix}#{queue_name}_done"
70
- logger.debug "Starting monitor for queue #{done_queue_name}"
71
- Thread.new(done_queue_name) do |done_queue_name|
72
- loop do
73
- with_queue(done_queue_name) do |done_queue|
74
- while (message = done_queue.receive)
75
- done_message = decode_message(message.body)
76
- logger.debug "#{done_queue.name}: #{done_message.pretty_inspect}"
77
- processed = decode_message(done_message['original'])
78
- logger.info "Done: #{queue_name} #{processed.inspect}"
79
- message.delete()
80
- statistics.record_done(done_message)
81
- end
82
- sleep(5)
83
- end
84
- end
85
- end
86
- end
87
- end
88
-
89
- def run_error_monitors
90
- config['processors'].collect do |key, settings|
91
- queue_name = settings['queue'] || key
92
- error_queue_name = "#{@queue_prefix}#{queue_name}_error"
93
- logger.info "Starting error monitor for queue #{error_queue_name}"
94
- Thread.new(error_queue_name) do |error_queue_name|
95
- loop do
96
- with_queue(error_queue_name) do |error_queue|
97
- while (message = error_queue.receive)
98
- error_message = decode_message(message.body)
99
- logger.debug "#{error_queue.name}: #{error_message.pretty_inspect}"
100
- processed = decode_message(error_message['original'])
101
- logger.info "Error: #{queue_name} #{processed.inspect}"
102
- message.delete()
103
- statistics.record_error(error_message)
104
- end
105
- end
106
- sleep(5)
107
- end
108
- end
109
- end
110
- end
111
-
112
- end
113
- end