queue_dispatcher 1.1.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.
Files changed (47) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +55 -0
  5. data/Rakefile +2 -0
  6. data/app/assets/images/icon_acquire_lock.png +0 -0
  7. data/app/assets/images/icon_error.png +0 -0
  8. data/app/assets/images/icon_init_queue.gif +0 -0
  9. data/app/assets/images/icon_pending.gif +0 -0
  10. data/app/assets/images/icon_running.gif +0 -0
  11. data/app/assets/images/icon_successful.png +0 -0
  12. data/app/assets/images/icon_warning.gif +0 -0
  13. data/app/assets/images/lock.png +0 -0
  14. data/app/assets/javascript/tasks.js.coffee +8 -0
  15. data/app/helpers/tasks_helper.rb +28 -0
  16. data/app/models/task_dependency.rb +2 -0
  17. data/app/views/queue_dispatcher_views/_search_results_events.html.haml +4 -0
  18. data/app/views/queue_dispatcher_views/_search_results_my_events.html.haml +4 -0
  19. data/app/views/queue_dispatcher_views/_task_event.html.haml +24 -0
  20. data/app/views/queue_dispatcher_views/_task_footer.html.erb +1 -0
  21. data/app/views/queue_dispatcher_views/_task_header.html.erb +12 -0
  22. data/app/views/queue_dispatcher_views/_task_my_event.html.haml +24 -0
  23. data/app/views/queue_dispatcher_views/expand_event.js.rjs +1 -0
  24. data/app/views/queue_dispatcher_views/my_events.html.haml +7 -0
  25. data/app/views/queue_dispatcher_views/my_events.js.erb +6 -0
  26. data/app/views/queue_dispatcher_views/update_events.js.erb +15 -0
  27. data/lib/generators/queue_dispatcher/migration/migration_generator.rb +51 -0
  28. data/lib/generators/queue_dispatcher/migration/templates/task_dependencies.rb +16 -0
  29. data/lib/generators/queue_dispatcher/migration/templates/task_queues.rb +18 -0
  30. data/lib/generators/queue_dispatcher/migration/templates/tasks.rb +25 -0
  31. data/lib/queue_dispatcher/acts_as_task.rb +194 -0
  32. data/lib/queue_dispatcher/acts_as_task_controller.rb +95 -0
  33. data/lib/queue_dispatcher/acts_as_task_queue.rb +447 -0
  34. data/lib/queue_dispatcher/deserialization_error.rb +4 -0
  35. data/lib/queue_dispatcher/message_sending.rb +31 -0
  36. data/lib/queue_dispatcher/psych_ext.rb +127 -0
  37. data/lib/queue_dispatcher/qd_logger.rb +15 -0
  38. data/lib/queue_dispatcher/rc_and_msg.rb +60 -0
  39. data/lib/queue_dispatcher/serialization/active_record.rb +20 -0
  40. data/lib/queue_dispatcher/syck_ext.rb +34 -0
  41. data/lib/queue_dispatcher/version.rb +3 -0
  42. data/lib/queue_dispatcher/yaml_ext.rb +10 -0
  43. data/lib/queue_dispatcher.rb +20 -0
  44. data/lib/tasks/queue_dispatcher.rake +7 -0
  45. data/queue_dispatcher.gemspec +26 -0
  46. data/script/queue_worker_dispatcher +259 -0
  47. metadata +187 -0
@@ -0,0 +1,20 @@
1
+ if defined?(ActiveRecord)
2
+ class ActiveRecord::Base
3
+ yaml_as "tag:ruby.yaml.org,2002:ActiveRecord"
4
+
5
+ def self.yaml_new(klass, tag, val)
6
+ if ActiveRecord::VERSION::MAJOR == 3
7
+ klass.unscoped.find(val['attributes'][klass.primary_key])
8
+ else # Rails 2
9
+ klass.with_exclusive_scope { klass.find(val['attributes'][klass.primary_key]) }
10
+ end
11
+ rescue ActiveRecord::RecordNotFound
12
+ #raise QueueDispatcher::DeserializationError, "ActiveRecord::RecordNotFound, class: #{klass} , primary key: #{val['attributes'][klass.primary_key]} "
13
+ '----- QueueDispatcher::DeserializationError -----'
14
+ end
15
+
16
+ def to_yaml_properties
17
+ ['@attributes']
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ class Module
2
+ yaml_as "tag:ruby.yaml.org,2002:module"
3
+
4
+ def self.yaml_new(klass, tag, val)
5
+ val.constantize
6
+ end
7
+
8
+ def to_yaml(options = {})
9
+ YAML.quick_emit(nil, options) do |out|
10
+ out.scalar(taguri, name, :plain)
11
+ end
12
+ end
13
+
14
+ def yaml_tag_read_class(name)
15
+ # Constantize the object so that ActiveSupport can attempt
16
+ # its auto loading magic. Will raise LoadError if not successful.
17
+ name.constantize
18
+ name
19
+ end
20
+ end
21
+
22
+ class Class
23
+ yaml_as "tag:ruby.yaml.org,2002:class"
24
+ remove_method :to_yaml if respond_to?(:to_yaml) && method(:to_yaml).owner == Class # use Module's to_yaml
25
+ end
26
+
27
+ class Struct
28
+ def self.yaml_tag_read_class(name)
29
+ # Constantize the object so that ActiveSupport can attempt
30
+ # its auto loading magic. Will raise LoadError if not successful.
31
+ name.constantize
32
+ "Struct::#{ name }"
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module QueueDispatcher
2
+ VERSION = "1.1.0"
3
+ end
@@ -0,0 +1,10 @@
1
+ # These extensions allow properly serializing and autoloading of
2
+ # Classes, Modules and Structs
3
+
4
+ require 'yaml'
5
+ if YAML.parser.class.name =~ /syck|yecht/i
6
+ require File.expand_path('../syck_ext', __FILE__)
7
+ require File.expand_path('../serialization/active_record', __FILE__)
8
+ else
9
+ require File.expand_path('../psych_ext', __FILE__)
10
+ end
@@ -0,0 +1,20 @@
1
+ require 'rails'
2
+ require 'queue_dispatcher'
3
+ require 'queue_dispatcher/acts_as_task'
4
+ require 'queue_dispatcher/acts_as_task_queue'
5
+ require 'queue_dispatcher/acts_as_task_controller'
6
+ require 'queue_dispatcher/deserialization_error'
7
+ require 'queue_dispatcher/message_sending'
8
+ require 'queue_dispatcher/qd_logger'
9
+ require 'queue_dispatcher/rc_and_msg'
10
+ require 'queue_dispatcher/yaml_ext'
11
+
12
+ module QueueDispatcher
13
+ class Engine < ::Rails::Engine
14
+ end
15
+ end
16
+
17
+ ActiveRecord::Base.send(:include, QueueDispatcher::ActsAsTask)
18
+ ActiveRecord::Base.send(:include, QueueDispatcher::ActsAsTaskQueue)
19
+ ActionController::Base.send(:include, QueueDispatcher::ActsAsTaskController)
20
+ Object.send(:include, QueueDispatcher::MessageSending)
@@ -0,0 +1,7 @@
1
+ namespace :queue_dispatcher do
2
+ desc "Sync extra files from QueueDispatcher gem."
3
+ task :sync do
4
+ system "rsync -ruv #{File.dirname(__FILE__)}/../../script #{Rails.root}"
5
+ system "rsync -ruv #{File.dirname(__FILE__)}/../../rgloader #{Rails.root}"
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "queue_dispatcher/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "queue_dispatcher"
7
+ s.version = QueueDispatcher::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Philip Kurmann"]
10
+ s.email = ["philip.kurmann@inwork.ch"]
11
+ s.homepage = ""
12
+ s.summary = %q{This Gem installs a queue dispatcher for handling asynchronous tasks}
13
+ s.description = %q{The QueueDispatcher let you execute queues as workers.}
14
+
15
+ s.add_dependency "sys-proctable", '>= 0.9.1'
16
+ s.add_dependency "deadlock_retry"
17
+ s.add_dependency "spawn", '>= 1.0.0'
18
+ s.add_dependency "haml"
19
+ s.add_dependency "will_paginate"
20
+ s.add_dependency "jquery-rails"
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+ end
@@ -0,0 +1,259 @@
1
+ #!/usr/bin/env ruby
2
+ # BEGIN - rails runner… with a relative path
3
+ DAEMON_ARGV = ARGV.clone
4
+ ARGV.clear
5
+ ARGV << 'runner'
6
+ ARGV << '/dev/null'
7
+ $: << File.dirname(__FILE__)
8
+ load 'rails'
9
+ # END - rails runner… with a relative path
10
+
11
+ require 'sys/proctable'
12
+ include Sys
13
+ include Spawn
14
+ include IwLogger
15
+
16
+
17
+ # Stop Active Record Logging
18
+ ActiveRecord::Base.logger = Logger.new(nil)
19
+ ActiveRecord::Base.clear_active_connections!
20
+
21
+ # ---------------------------------------------------------------------
22
+ # CONFIGURATION
23
+ # ---------------------------------------------------------------------
24
+ $daemon = {
25
+ :name => "--- - Worker Dispatcher", # daemon name
26
+ :process_prefix => "---", # Prefix for process name
27
+ :copyright => "(c) 2011 In&Work AG", # daemon copyright
28
+ :author => "Philip Kurmann", # dameon author
29
+ :version => "1.0", # actual version
30
+ :log_file => "#{File.expand_path(Rails.root)}/log/queue_dispatcher.log", # log path
31
+ :pid_file => "#{File.expand_path(Rails.root)}/tmp/pids/queue_worker_dispatcher.pid", # process id path
32
+ :task_queue_model => TaskQueue, # TaskQueue
33
+ :monitoring_sleep => 30, # seconds
34
+ :worker_sleep => 15, # seconds
35
+ :worker_count => AppConfig.max_task_queue_workers, # Worker_count
36
+ :background => false, # background mode
37
+ :work => true, # daemon work flag
38
+ :logger_msg_prefix => nil, # Prefix for logging
39
+ :worker_pids => [] # Remember PIDs
40
+ }
41
+
42
+ $worker = {
43
+ :name => "--- - Queue Worker", # Worker name
44
+ :process_prefix => "---", # Prefix for process name
45
+ :work => true, # Worker work flag
46
+ :task_queue => nil # Remember TaskQueue of worker, nil means idle
47
+ }
48
+
49
+
50
+ # Write a log message
51
+ def daemon_log args = {}
52
+ msg = args[:msg]
53
+ msg = "#{$daemon[:logger_msg_prefix]}: #{msg}" unless $daemon[:logger_msg_prefix].blank?
54
+ sev = args[:sev] || :info
55
+ log :msg => msg, :sev => sev, :print_log => (! $daemon[:background] || sev == :error)
56
+ end
57
+
58
+
59
+ # Set process name
60
+ def daemon_set_process_name name
61
+ $0 = name
62
+ end
63
+
64
+
65
+ # Write PID-File
66
+ def daemon_write_pid_file
67
+ begin
68
+ File.open($daemon[:pid_file], "w") { |f| f.write(Process.pid) }
69
+ rescue Errno::EACCES
70
+ daemon_log :msg => "Cannot create PID file!", :sev => :error
71
+ exit
72
+ end
73
+ end
74
+
75
+
76
+ # Clean up before a daemon terminates
77
+ def daemon_clean_up
78
+ File.delete($daemon[:pid_file])
79
+ end
80
+
81
+
82
+ # Install signal handler
83
+ def install_signal_handler signals, args = {}
84
+ sigtrap = proc do
85
+ daemon_log :msg => args[:trap_msg] if args[:trap_msg]
86
+ yield
87
+ end
88
+ signals.each { |signal| trap signal, sigtrap }
89
+ args[:ignore_signals].each { |signal| trap signal, 'IGNORE' } if args[:ignore_signals]
90
+ end
91
+
92
+
93
+ # Install signal handler for daemon
94
+ def daemon_install_signal_handler
95
+ install_signal_handler(['TERM', 'INT', 'HUP'], :trap_msg => "Caught trap signal. Shutdown workers...") do
96
+ $daemon[:worker_pids].each do |pid|
97
+ begin
98
+ Process.kill('TERM', pid)
99
+ rescue => exception
100
+ end
101
+ end
102
+ $daemon[:work] = false
103
+ end
104
+ end
105
+
106
+
107
+ # Install signal handler for worker
108
+ def worker_install_signal_handler
109
+ install_signal_handler(['TERM'], :trap_msg => "Caught trap signal. Shutdown...", :ignore_signals => ['HUP', 'INT']) do
110
+ # Shutdown task_queue
111
+ $worker[:task_queue].update_attributes :state => 'shutdown' if $worker[:task_queue]
112
+ $worker[:work] = false
113
+ end
114
+ end
115
+
116
+
117
+ def daemon_runner
118
+ Lock.release_all
119
+ daemon_set_process_name "#{$daemon[:process_prefix]}_WorkerDispatcher"
120
+ daemon_write_pid_file
121
+ daemon_install_signal_handler
122
+ spawn_and_monitor_workers
123
+ # Wait for all children (workers) to be finished
124
+ Process.waitall
125
+ daemon_clean_up
126
+ end
127
+
128
+
129
+ # Start running
130
+ def daemon_start
131
+ @logger = Logger.new($daemon[:log_file], 'weekly')
132
+ $daemon[:logger_msg_prefix] = 'TaskQueueDispatcher'
133
+
134
+ if File.exist?($daemon[:pid_file]) then
135
+ old_pid = IO.read($daemon[:pid_file]).to_i rescue nil
136
+ ps = Sys::ProcTable.ps(old_pid)
137
+
138
+ # Asume, that if the command of the 'ps'-output is 'ruby', the process is still running
139
+ if ps && (ps.comm == 'ruby')
140
+ daemon_log :msg => "Process already running!", :sev => :error
141
+ exit
142
+ else
143
+ File.delete($daemon[:pid_file])
144
+ end
145
+ end
146
+
147
+ daemon_log :msg => "Starting process..."
148
+ if $daemon[:background]
149
+ spawn_block { daemon_runner }
150
+ else
151
+ daemon_runner
152
+ end
153
+ end
154
+
155
+
156
+ # Start an amount of workers
157
+ def spawn_and_monitor_workers
158
+ daemon_log :msg => "Spawning #{$daemon[:worker_count]} workers..."
159
+
160
+ while $daemon[:work]
161
+ # (Re)start workers
162
+ while $daemon[:worker_pids].count < $daemon[:worker_count] do
163
+ sp = spawn_block(:argv => $worker[:process_prefix]) do
164
+ worker_runner
165
+ end
166
+ $daemon[:worker_pids] << sp.handle
167
+ end
168
+
169
+ sleep $daemon[:monitoring_sleep]
170
+
171
+ # Delete PIDs from the array child_pids which don't exists anymore
172
+ $daemon[:worker_pids].each do |ch_pid|
173
+ begin
174
+ ps = ProcTable.ps(ch_pid)
175
+ rescue
176
+ ps = nil
177
+ daemon_log :msg => "Error in ProcTable.ps: #{$!}", :sev => :error
178
+ end
179
+ $daemon[:worker_pids].delete ch_pid unless ps && ps.comm == 'ruby'
180
+ end
181
+ end
182
+ end
183
+
184
+
185
+ # Start the task_list dispatcher, which is permanentely looking for task_lists to start
186
+ def worker_runner
187
+ $daemon[:logger_msg_prefix] = 'TaskQueueWorker'
188
+
189
+ worker_install_signal_handler
190
+ daemon_log :msg => "Start working..."
191
+
192
+ # Fetch pending task queues and start working
193
+ while $worker[:work] do
194
+ $worker[:task_queue] = $daemon[:task_queue_model].get_next_pending
195
+
196
+ if $worker[:task_queue]
197
+ # Set Process Name and execute tasks
198
+ $0 = "#{$worker[:process_prefix]}_#{$worker[:task_queue].id}"
199
+ $worker[:task_queue].run!(:print_log => ! $daemon[:background])
200
+ else
201
+ # Set Process Name and sleep
202
+ $0 = "#{$worker[:process_prefix]}_idle"
203
+ sleep 15
204
+ end
205
+ end
206
+
207
+ daemon_log :msg => "Ended!"
208
+ rescue => exception
209
+ daemon_log :msg => "Fatal error in method 'worker_runner': #{$!}\n#{exception.backtrace}", :sev => :error
210
+ end
211
+
212
+
213
+ # Show version
214
+ def daemon_show_version
215
+ puts "#{$daemon[:name]} v#{$daemon[:version]}"
216
+ puts $daemon[:copyright]
217
+ end
218
+
219
+
220
+ # Show help on command line
221
+ def daemon_show_usage
222
+ daemon_show_version
223
+ puts "\nUsage:"
224
+ puts " -b, --background work in background mode"
225
+ puts " -v, --version view version of daemon"
226
+ puts " -h, --help view this help"
227
+ end
228
+
229
+
230
+ # Parse command line options
231
+ def daemon_parse_opts
232
+ start = true
233
+
234
+ unless DAEMON_ARGV.length == 0
235
+ case DAEMON_ARGV[0]
236
+ when '-b', '--background'
237
+ $daemon[:background] = true;
238
+
239
+ when '-v', '--version'
240
+ daemon_show_version
241
+ start = false
242
+
243
+ when '-h', '--help'
244
+ daemon_show_usage
245
+ start = false
246
+
247
+ else
248
+ puts "Invalid argument: #{DAEMON_ARGV[0]}" if !DAEMON_ARGV[0].nil?
249
+ daemon_show_usage
250
+ start = false
251
+ end
252
+ end
253
+
254
+ start
255
+ end
256
+
257
+
258
+ ################# MAIN #####################
259
+ daemon_start if daemon_parse_opts
metadata ADDED
@@ -0,0 +1,187 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: queue_dispatcher
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Philip Kurmann
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sys-proctable
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.9.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.9.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: deadlock_retry
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: spawn
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 1.0.0
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.0.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: haml
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: will_paginate
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: jquery-rails
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: The QueueDispatcher let you execute queues as workers.
111
+ email:
112
+ - philip.kurmann@inwork.ch
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - .gitignore
118
+ - Gemfile
119
+ - LICENSE
120
+ - README.rdoc
121
+ - Rakefile
122
+ - app/assets/images/icon_acquire_lock.png
123
+ - app/assets/images/icon_error.png
124
+ - app/assets/images/icon_init_queue.gif
125
+ - app/assets/images/icon_pending.gif
126
+ - app/assets/images/icon_running.gif
127
+ - app/assets/images/icon_successful.png
128
+ - app/assets/images/icon_warning.gif
129
+ - app/assets/images/lock.png
130
+ - app/assets/javascript/tasks.js.coffee
131
+ - app/helpers/tasks_helper.rb
132
+ - app/models/task_dependency.rb
133
+ - app/views/queue_dispatcher_views/_search_results_events.html.haml
134
+ - app/views/queue_dispatcher_views/_search_results_my_events.html.haml
135
+ - app/views/queue_dispatcher_views/_task_event.html.haml
136
+ - app/views/queue_dispatcher_views/_task_footer.html.erb
137
+ - app/views/queue_dispatcher_views/_task_header.html.erb
138
+ - app/views/queue_dispatcher_views/_task_my_event.html.haml
139
+ - app/views/queue_dispatcher_views/expand_event.js.rjs
140
+ - app/views/queue_dispatcher_views/my_events.html.haml
141
+ - app/views/queue_dispatcher_views/my_events.js.erb
142
+ - app/views/queue_dispatcher_views/update_events.js.erb
143
+ - lib/generators/queue_dispatcher/migration/migration_generator.rb
144
+ - lib/generators/queue_dispatcher/migration/templates/task_dependencies.rb
145
+ - lib/generators/queue_dispatcher/migration/templates/task_queues.rb
146
+ - lib/generators/queue_dispatcher/migration/templates/tasks.rb
147
+ - lib/queue_dispatcher.rb
148
+ - lib/queue_dispatcher/acts_as_task.rb
149
+ - lib/queue_dispatcher/acts_as_task_controller.rb
150
+ - lib/queue_dispatcher/acts_as_task_queue.rb
151
+ - lib/queue_dispatcher/deserialization_error.rb
152
+ - lib/queue_dispatcher/message_sending.rb
153
+ - lib/queue_dispatcher/psych_ext.rb
154
+ - lib/queue_dispatcher/qd_logger.rb
155
+ - lib/queue_dispatcher/rc_and_msg.rb
156
+ - lib/queue_dispatcher/serialization/active_record.rb
157
+ - lib/queue_dispatcher/syck_ext.rb
158
+ - lib/queue_dispatcher/version.rb
159
+ - lib/queue_dispatcher/yaml_ext.rb
160
+ - lib/tasks/queue_dispatcher.rake
161
+ - queue_dispatcher.gemspec
162
+ - script/queue_worker_dispatcher
163
+ homepage: ''
164
+ licenses: []
165
+ post_install_message:
166
+ rdoc_options: []
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ none: false
171
+ requirements:
172
+ - - ! '>='
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ required_rubygems_version: !ruby/object:Gem::Requirement
176
+ none: false
177
+ requirements:
178
+ - - ! '>='
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ requirements: []
182
+ rubyforge_project:
183
+ rubygems_version: 1.8.24
184
+ signing_key:
185
+ specification_version: 3
186
+ summary: This Gem installs a queue dispatcher for handling asynchronous tasks
187
+ test_files: []