homeq 1.1.4

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 (63) hide show
  1. data/CHANGELOG +103 -0
  2. data/COPYING +348 -0
  3. data/README.rdoc +64 -0
  4. data/Rakefile +131 -0
  5. data/bin/hq +6 -0
  6. data/config/boot.rb +224 -0
  7. data/config/databases/frontbase.yml +28 -0
  8. data/config/databases/mysql.yml +54 -0
  9. data/config/databases/oracle.yml +39 -0
  10. data/config/databases/postgresql.yml +48 -0
  11. data/config/databases/sqlite2.yml +16 -0
  12. data/config/databases/sqlite3.yml +19 -0
  13. data/config/environment.rb +20 -0
  14. data/config/environments/development.cfg +35 -0
  15. data/config/environments/production.cfg +35 -0
  16. data/config/environments/test.cfg +35 -0
  17. data/config/generators/job/templates/job.rb.erb +20 -0
  18. data/config/generators/message/templates/messages/MESSAGE.proto.erb +12 -0
  19. data/config/generators/model/templates/models/MODEL.rb.erb +3 -0
  20. data/config/generators/service/templates/services/SERVICE.rb.erb +43 -0
  21. data/config/homeq.cfg +35 -0
  22. data/extras/consumer.rb +85 -0
  23. data/extras/homeq.cfg +49 -0
  24. data/extras/hqd.rb +33 -0
  25. data/extras/producer.rb +79 -0
  26. data/extras/simple_consumer.rb +53 -0
  27. data/lib/homeq/base/base.rb +44 -0
  28. data/lib/homeq/base/commando.rb +81 -0
  29. data/lib/homeq/base/config.rb +99 -0
  30. data/lib/homeq/base/exception.rb +48 -0
  31. data/lib/homeq/base/histogram.rb +141 -0
  32. data/lib/homeq/base/logger.rb +185 -0
  33. data/lib/homeq/base/ohash.rb +297 -0
  34. data/lib/homeq/base/options.rb +171 -0
  35. data/lib/homeq/base/poolable.rb +100 -0
  36. data/lib/homeq/base/system.rb +446 -0
  37. data/lib/homeq/cli.rb +35 -0
  38. data/lib/homeq/cp/commands.rb +71 -0
  39. data/lib/homeq/cp/connection.rb +97 -0
  40. data/lib/homeq/cp/cp.rb +30 -0
  41. data/lib/homeq/cp/server.rb +105 -0
  42. data/lib/homeq/sobs/client.rb +119 -0
  43. data/lib/homeq/sobs/connection.rb +635 -0
  44. data/lib/homeq/sobs/foreman.rb +237 -0
  45. data/lib/homeq/sobs/job.rb +66 -0
  46. data/lib/homeq/sobs/message.rb +49 -0
  47. data/lib/homeq/sobs/queue.rb +224 -0
  48. data/lib/homeq/sobs/sender.rb +150 -0
  49. data/lib/homeq/sobs/server.rb +654 -0
  50. data/lib/homeq/sobs/sobs.rb +45 -0
  51. data/lib/homeq/sobs/topology.rb +111 -0
  52. data/lib/homeq.rb +106 -0
  53. data/lib/tasks/Rakefile +49 -0
  54. data/lib/tasks/database.rake +387 -0
  55. data/lib/tasks/gem.rake +9 -0
  56. data/lib/tasks/generate.rake +192 -0
  57. data/lib/tasks/hq.rake +171 -0
  58. data/lib/tasks/testing.rake +95 -0
  59. data/lib/tasks/utility.rb +17 -0
  60. data/script/console.rb +45 -0
  61. data/script/generate +7 -0
  62. data/test/unittest.rb +51 -0
  63. metadata +222 -0
@@ -0,0 +1,192 @@
1
+ #############################################################################
2
+ #
3
+ # $Id$
4
+ #
5
+ # Author:: Colin Steele (colin@colinsteele.org)
6
+ # Homepage::
7
+ #
8
+ #----------------------------------------------------------------------------
9
+ #
10
+ # Copyright (C) 2008 by Colin Steele. All Rights Reserved.
11
+ # colin@colinsteele.org
12
+ #
13
+ # This program is free software; you can redistribute it and/or modify
14
+ # it under the terms of either: 1) the GNU General Public License
15
+ # as published by the Free Software Foundation; either version 2 of the
16
+ # License, or (at your option) any later version; or 2) Ruby's License.
17
+ #
18
+ # See the file COPYING for complete licensing information.
19
+ #
20
+ #---------------------------------------------------------------------------
21
+ #
22
+ #
23
+ #############################################################################
24
+
25
+ require 'rubygems'
26
+ require 'homeq'
27
+ require 'rake'
28
+ require 'rake/testtask'
29
+ require 'rake/rdoctask'
30
+ require 'activesupport'
31
+ require 'erb'
32
+ require 'date'
33
+ require 'rbconfig'
34
+
35
+ require 'utility'
36
+
37
+
38
+ # Redefine the way rake works so we can have special stuff like
39
+ # arguments. TODO: Yes, this is hacky.
40
+
41
+ module Rake
42
+
43
+ class Application
44
+ def top_level
45
+ standard_exception_handling do
46
+ if options.show_tasks
47
+ display_tasks_and_comments
48
+ elsif options.show_prereqs
49
+ display_prerequisites
50
+ else
51
+ found_tasks = top_level_tasks.find_all { |task_name|
52
+ @tasks[task_name] != nil
53
+ }
54
+ if found_tasks.length == 0
55
+ fail "No matching tasks for '#{top_level_tasks.join(', ')}'"
56
+ end
57
+ top_level_tasks.reverse.each { |task_name| invoke_task(task_name) }
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ module TaskManager
64
+
65
+ attr :parameters, true
66
+ attr :unknown_tasks, true
67
+
68
+ # Find a matching task for +task_name+.
69
+ def [](task_name, scopes=nil)
70
+ task_name = task_name.to_s
71
+ self.lookup(task_name, scopes) or
72
+ enhance_with_matching_rule(task_name) or
73
+ synthesize_file_task(task_name) or
74
+ # parameter_task(task_name) or
75
+ unknown_task(task_name) or
76
+ fail "Cannot find task called '#{task_name}'"
77
+ end
78
+
79
+ def parameter_task(task_name)
80
+ return nil unless task_name =~ /([a-z_0-9-]+):([a-z_0-9-]+)/i
81
+ @parameters ||= {}
82
+ @parameters[$1] = $2
83
+ # return a do nothing task
84
+ Rake::Task.new($1, self)
85
+ end
86
+
87
+ def unknown_task(task_name)
88
+ # return a do nothing task
89
+ t = Rake::Task.new(task_name, self)
90
+ @unknown_tasks ||= []
91
+ @unknown_tasks << t
92
+ t
93
+ end
94
+
95
+ end
96
+ end
97
+
98
+ DESTINATION = ENV['HOMEQ_CLI_DEST']
99
+
100
+ raise "ENV['HOMEQ_CLI_DEST'] is not set" unless DESTINATION
101
+
102
+ Dir.chdir(HOMEQ_ROOT)
103
+
104
+ task :default => [:usage]
105
+
106
+ task :usage do |t|
107
+ puts "usage: generate <#{STANDARD_TASKS.join('|')}>"
108
+ end
109
+
110
+ def create_standard_generator_task(task_name)
111
+ task task_name do |t|
112
+
113
+ # Add some special sauce to our task
114
+ class << t
115
+ attr :args, true
116
+ def mk_template_dirs(dirs, dest_dir)
117
+ dirs.each { |d|
118
+ mkdir_p File.join(dest_dir, d.gsub(/.*templates/, ''))
119
+ }
120
+ end
121
+ def copy_interpolate_files(files, dest_dir)
122
+ eval("#{self.name}_name = @args[0]")
123
+ ruby_path = system_ruby_path
124
+ task = self
125
+ files.each { |template|
126
+ path = File.join(dest_dir,
127
+ template.gsub(/.*templates/, ''))
128
+ path.gsub!(/#{self.name.to_s.upcase}/, args[0])
129
+ path.gsub!(/\.erb/, '')
130
+ File.open(File.expand_path(path), 'w') { |f|
131
+ f.write ERB.new(IO.read(template), nil, '-').result(binding)
132
+ }
133
+ if File.executable?(template)
134
+ chmod 0755, File.expand_path(path)
135
+ end
136
+ }
137
+ end
138
+ def files_from_path(paths)
139
+ paths.find_all { |path|
140
+ File.file?(path)
141
+ }
142
+ end
143
+ def dirs_from_path(paths)
144
+ paths.find_all { |path|
145
+ File.directory?(path)
146
+ }
147
+ end
148
+ def copy_dirs_and_files(paths, dest)
149
+ mk_template_dirs(dirs_from_path(paths), dest)
150
+ copy_interpolate_files(files_from_path(paths), dest)
151
+ end
152
+ end
153
+
154
+ if t.application.unknown_tasks
155
+ t.args = t.application.unknown_tasks.collect { |ut|
156
+ ut.name
157
+ }.reverse
158
+ end
159
+
160
+ unless t.args && t.args[0]
161
+ puts "usage: generate #{task_name} <#{task_name} name> [args ...]"
162
+ exit(-1)
163
+ end
164
+
165
+ t.copy_dirs_and_files(Dir["config/generators/#{t.name}/templates/**/*"],
166
+ "#{DESTINATION}/app/")
167
+ end
168
+ end
169
+
170
+ STANDARD_TASKS = [:service, :message, :model]
171
+ tasks = {}
172
+ STANDARD_TASKS.each { |sym|
173
+ tasks[sym] = create_standard_generator_task(sym)
174
+ }
175
+
176
+ # Add the service-specific include dir and add a job def to it.
177
+ # TODO: create a migration file
178
+ t = tasks[:service]
179
+ t.enhance {
180
+ dir = t.args[0].downcase + "_service"
181
+ t.mk_template_dirs([dir], "#{DESTINATION}/app/services/")
182
+ dir = File.join("#{DESTINATION}/app/services/", dir)
183
+ t.copy_interpolate_files(Dir["config/generators/job/templates/**/*"], dir)
184
+ }
185
+
186
+ # Create a ruby class from the protocol definition
187
+ tasks[:message].enhance {
188
+ t = tasks[:message]
189
+ file = File.expand_path("#{DESTINATION}/app/messages/#{t.args[0]}.proto")
190
+ sh "cd #{File.dirname(file)};rprotoc -o 'wire' #{t.args[0]}.proto"
191
+ }
192
+
data/lib/tasks/hq.rake ADDED
@@ -0,0 +1,171 @@
1
+ #############################################################################
2
+ #
3
+ # $Id$
4
+ #
5
+ # Author:: Colin Steele (colin@colinsteele.org)
6
+ # Homepage::
7
+ #
8
+ #----------------------------------------------------------------------------
9
+ #
10
+ # Copyright (C) 2008 by Colin Steele. All Rights Reserved.
11
+ # colin@colinsteele.org
12
+ #
13
+ # This program is free software; you can redistribute it and/or modify
14
+ # it under the terms of either: 1) the GNU General Public License
15
+ # as published by the Free Software Foundation; either version 2 of the
16
+ # License, or (at your option) any later version; or 2) Ruby's License.
17
+ #
18
+ # See the file COPYING for complete licensing information.
19
+ #
20
+ #---------------------------------------------------------------------------
21
+ #
22
+ #
23
+ #############################################################################
24
+
25
+ require 'rubygems'
26
+ require 'homeq'
27
+ require 'rake'
28
+ require 'rake/testtask'
29
+ require 'rake/rdoctask'
30
+
31
+ require 'erb'
32
+ require 'date'
33
+ require 'rbconfig'
34
+
35
+ require 'utility'
36
+
37
+ DESTINATION = ENV['HOMEQ_CLI_DEST']
38
+ unless DESTINATION
39
+ raise 'No destination install dir set via ENV["HOMEQ_CLI_DEST"]'
40
+ end
41
+
42
+ Dir.chdir(HOMEQ_ROOT)
43
+
44
+ task :default => [:setup_hq_app]
45
+
46
+ task :setup_hq_app => [
47
+ :base_directories,
48
+ :root_files, :bin_files, :config_files, :script_files, :task_files
49
+ ]
50
+
51
+ BASE_DIRS = %w(
52
+ app
53
+ app/models
54
+ app/messages
55
+ app/messages/wire
56
+ app/services
57
+ bin
58
+ config
59
+ config/environments
60
+ db
61
+ db/migrate
62
+ doc
63
+ log
64
+ lib
65
+ lib/tasks
66
+ script
67
+ test
68
+ vendor
69
+ tmp/cache
70
+ tmp/pids
71
+ )
72
+
73
+ BASE_DIRS.each do |d|
74
+ base_dir = File.expand_path(File.join(DESTINATION, d))
75
+ task :base_directories => base_dir
76
+ directory base_dir
77
+ end
78
+
79
+ ROOT_FILES = ["README", "CHANGELOG"]
80
+ ROOT_FILES.each { |f|
81
+ dest_file = "#{DESTINATION}/#{f}"
82
+ task :root_files => dest_file
83
+ file dest_file => f do |t|
84
+ cp f, dest_file
85
+ end
86
+ }
87
+
88
+ task :root_files => "#{DESTINATION}/Rakefile"
89
+ file "#{DESTINATION}/Rakefile" => 'lib/tasks/Rakefile' do |t|
90
+ t.prerequisites.each { |f|
91
+ cp f, File.join(DESTINATION, File.basename(f))
92
+ }
93
+ end
94
+
95
+ BIN_FILES = ['bin/hq']
96
+ BIN_FILES.each { |f|
97
+ dest_file = "#{DESTINATION}/#{f}"
98
+ task :bin_files => dest_file
99
+ file dest_file => f do |t|
100
+ copy_with_rewritten_ruby_path(f, dest_file)
101
+ chmod 0755, dest_file
102
+ end
103
+ }
104
+
105
+ CONFIG_FILES = [
106
+ 'config/boot.rb',
107
+ 'config/environment.rb',
108
+ 'config/homeq.cfg',
109
+ 'config/environments/development.cfg',
110
+ 'config/environments/test.cfg',
111
+ 'config/environments/production.cfg',
112
+ ]
113
+ CONFIG_FILES.each { |f|
114
+ dest_file = "#{DESTINATION}/#{f}"
115
+ task :config_files => dest_file
116
+ file dest_file => f do |t|
117
+ cp f, dest_file
118
+ end
119
+ }
120
+
121
+ SCRIPT_FILES = [
122
+ 'script/generate',
123
+ ]
124
+ SCRIPT_FILES.each { |f|
125
+ dest_file = "#{DESTINATION}/#{f}"
126
+ task :script_files => dest_file
127
+ file dest_file => f do |t|
128
+ copy_with_rewritten_ruby_path(f, dest_file)
129
+ chmod 0755, dest_file
130
+ end
131
+ }
132
+
133
+ TASK_FILES = FileList['lib/tasks/*.rake']
134
+ TASK_FILES.each { |f|
135
+ dest_file = "#{DESTINATION}/#{f}"
136
+ task :task_files => dest_file
137
+ file dest_file => f do |t|
138
+ copy_with_rewritten_ruby_path(f, dest_file)
139
+ chmod 0755, dest_file
140
+ end
141
+ }
142
+
143
+ file "config/database.yml" => 'config/databases/mysql.yml' do |t|
144
+ app_name = File.basename(DESTINATION)
145
+ socket = nil
146
+ File.open("#{DESTINATION}/config/database.yml", 'w') { |f|
147
+ f.write ERB.new(IO.read("config/databases/mysql.yml"),
148
+ nil,
149
+ '-').result(binding)
150
+ }
151
+ end
152
+ task :config_files => "config/database.yml"
153
+
154
+ # TODO: Need task for copying all hq package files to vendor like
155
+ # 'rails freeze'
156
+
157
+ # Initialize file stubs
158
+
159
+ desc "Initialize empty file stubs (such as for logging)"
160
+ task :initialize_file_stubs => [ :initialize_log_files ]
161
+
162
+ task :initialize_log_files do
163
+ log_dir = File.join(DESTINATION, 'log')
164
+ chmod 0777, log_dir
165
+ LOG_FILES.each do |log_file|
166
+ log_path = File.join(log_dir, log_file)
167
+ touch log_path
168
+ chmod 0666, log_path
169
+ end
170
+ end
171
+
@@ -0,0 +1,95 @@
1
+ TEST_CHANGES_SINCE = Time.now - 600
2
+
3
+ rule('') do |t|
4
+ ENV['TEST_NAME'] = t.name
5
+ Rake::Task['test'].invoke
6
+ end
7
+
8
+ # Look up tests for recently modified sources.
9
+ def recent_tests(source_pattern, test_path, touched_since = 10.minutes.ago)
10
+ FileList[source_pattern].map do |path|
11
+ if File.mtime(path) > touched_since
12
+ tests = []
13
+ source_dir = File.dirname(path).split("/")
14
+ source_file = File.basename(path, '.rb')
15
+
16
+ # Support subdirs in app/models and app/controllers
17
+ modified_test_path = source_dir.length > 2 ? "#{test_path}/" << source_dir[1..source_dir.length].join('/') : test_path
18
+
19
+ # For modified files in app/ run the tests for it. ex. /test/functional/account_controller.rb
20
+ test = "#{modified_test_path}/#{source_file}_test.rb"
21
+ tests.push test if File.exist?(test)
22
+
23
+ # For modified files in app, run tests in subdirs too. ex. /test/functional/account/*_test.rb
24
+ test = "#{modified_test_path}/#{File.basename(path, '.rb').sub("_controller","")}"
25
+ FileList["#{test}/*_test.rb"].each { |f| tests.push f } if File.exist?(test)
26
+
27
+ return tests
28
+
29
+ end
30
+ end.flatten.compact
31
+ end
32
+
33
+
34
+ # Recreated here from ActiveSupport because :uncommitted needs it before Rails is available
35
+ module Kernel
36
+ def silence_stderr
37
+ old_stderr = STDERR.dup
38
+ STDERR.reopen(RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'NUL:' : '/dev/null')
39
+ STDERR.sync = true
40
+ yield
41
+ ensure
42
+ STDERR.reopen(old_stderr)
43
+ end
44
+ end
45
+
46
+ desc 'Run all tests'
47
+ task :test do
48
+ errors = %w(test:units).collect do |task|
49
+ begin
50
+ Rake::Task[task].invoke
51
+ nil
52
+ rescue => e
53
+ task
54
+ end
55
+ end.compact
56
+ abort "Errors running #{errors.to_sentence}!" if errors.any?
57
+ end
58
+
59
+ namespace :test do
60
+ Rake::TestTask.new(:recent => "db:test:prepare") do |t|
61
+ since = TEST_CHANGES_SINCE
62
+ touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } +
63
+ recent_tests('app/models/**/*.rb', 'test/unit', since)
64
+
65
+ t.libs << 'test'
66
+ t.verbose = true
67
+ t.test_files = touched.uniq
68
+ end
69
+ Rake::Task['test:recent'].comment = "Test recent changes"
70
+
71
+ Rake::TestTask.new(:uncommitted => "db:test:prepare") do |t|
72
+ def t.file_list
73
+ changed_since_checkin = silence_stderr { `svn status` }.map { |path| path.chomp[7 .. -1] }
74
+
75
+ models = changed_since_checkin.select { |path| path =~ /app[\\\/]models[\\\/].*\.rb/ }
76
+ controllers = changed_since_checkin.select { |path| path =~ /app[\\\/]controllers[\\\/].*\.rb/ }
77
+
78
+ unit_tests = models.map { |model| "test/unit/#{File.basename(model, '.rb')}_test.rb" }
79
+
80
+ unit_tests.uniq
81
+ end
82
+
83
+ t.libs << 'test'
84
+ t.verbose = true
85
+ end
86
+ Rake::Task['test:uncommitted'].comment = "Test changes since last checkin (only Subversion)"
87
+
88
+ Rake::TestTask.new(:units => "db:test:prepare") do |t|
89
+ t.libs << "test"
90
+ t.pattern = 'test/unittest.rb'
91
+ t.verbose = true
92
+ end
93
+ Rake::Task['test:units'].comment = "Run the unit tests in test/unit"
94
+
95
+ end
@@ -0,0 +1,17 @@
1
+ def copy_with_rewritten_ruby_path(src_file, dest_file)
2
+ File.open(dest_file, 'w') do |df|
3
+ File.open(src_file) do |sf|
4
+ line = sf.gets
5
+ if (line =~ /#!.+ruby\s*/) != nil
6
+ df.puts("#!#{system_ruby_path}")
7
+ else
8
+ df.puts(line)
9
+ end
10
+ df.write(sf.read)
11
+ end
12
+ end
13
+ end
14
+
15
+ def system_ruby_path
16
+ File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
17
+ end
data/script/console.rb ADDED
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ##############################################################################
4
+ #
5
+ # Console app
6
+ #
7
+ ##############################################################################
8
+
9
+ require 'irb'
10
+ require File.join(File.dirname(__FILE__), '../config/environment')
11
+
12
+ # Gives us easy access to log, system and config.
13
+ include HomeQ
14
+
15
+ #############################################################################
16
+ # Command line options
17
+ #############################################################################
18
+
19
+ parser = HomeQ::Base::Options::Options.instance.parser
20
+ options = HomeQ::Base::Options::Options.instance.options
21
+
22
+ options.filename = nil
23
+
24
+ parser.separator ""
25
+ parser.separator "CONSOLE SPECIFIC options:"
26
+ parser.on("-e --execute-filename FILE", "Run this script in the console") { |o|
27
+ options.filename = o
28
+ }
29
+
30
+ options.foreground = true
31
+ config.queue_name('__console__')
32
+
33
+ #############################################################################
34
+ # Prep for and run HQ
35
+ #############################################################################
36
+
37
+ sys.start {
38
+ if options.filename
39
+ load(options.filename)
40
+ else
41
+ IRB.start
42
+ Kernel::exit(0)
43
+ end
44
+ }
45
+
data/script/generate ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'homeq'
5
+ require 'homeq/cli'
6
+ dest = File.expand_path(File.join(File.dirname(__FILE__), '..'))
7
+ HomeQ::CLI.execute(dest, File.join(HOMEQ_ROOT, 'lib/tasks/generate.rake'))
data/test/unittest.rb ADDED
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ##############################################################################
4
+ #
5
+ # Unit tester
6
+ #
7
+ ##############################################################################
8
+
9
+ HOMEQ_ENV = 'test'
10
+ require File.join(File.dirname(__FILE__), '../config/environment')
11
+ require 'test/unit'
12
+ require 'test/test_helper'
13
+
14
+
15
+ # Gives us easy access to log, system and config.
16
+ include HomeQ
17
+
18
+ #############################################################################
19
+ # Command line options
20
+ #############################################################################
21
+
22
+ parser = HomeQ::Base::Options::Options.instance.parser
23
+ options = HomeQ::Base::Options::Options.instance.options
24
+
25
+ options.filename = nil
26
+
27
+ parser.separator ""
28
+ parser.separator "UNITTEST SPECIFIC options:"
29
+
30
+ options.foreground = true
31
+ config.queue_name('__unittest__')
32
+
33
+ #############################################################################
34
+ # Prep for and run HQ
35
+ #############################################################################
36
+
37
+ sys.start {
38
+ if ENV['TEST_NAME']
39
+ files = Dir["test/unit/#{ENV['TEST_NAME']}.rb"]
40
+ end
41
+ files = Dir['test/unit/*.rb'] if !files || files.empty?
42
+
43
+ files.each do |filename|
44
+ next if File.basename(filename) == File.basename(__FILE__)
45
+ path = File.join(HOMEQ_APP_ROOT,
46
+ 'test/unit/',
47
+ File.basename(filename))
48
+ require path
49
+ end
50
+ EventMachine::stop
51
+ }