queueing_proxy 0.0.1
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/Gemfile +3 -0
- data/Rakefile +2 -0
- data/bin/queueing_proxy +8 -0
- data/ext/gem_rake.rb +126 -0
- data/lib/queueing_proxy/cli.rb +17 -0
- data/lib/queueing_proxy/dispatcher.rb +56 -0
- data/lib/queueing_proxy/dsl.rb +48 -0
- data/lib/queueing_proxy/queuer.rb +57 -0
- data/lib/queueing_proxy/version.rb +3 -0
- data/lib/queueing_proxy.rb +22 -0
- data/queueing_proxy.gemspec +39 -0
- metadata +132 -0
data/Gemfile
ADDED
data/Rakefile
ADDED
data/bin/queueing_proxy
ADDED
data/ext/gem_rake.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
module Bundler
|
2
|
+
class GemHelper
|
3
|
+
|
4
|
+
def self.install_tasks
|
5
|
+
dir = caller.find{|c| /Rakefile:/}[/^(.*?)\/Rakefile:/, 1]
|
6
|
+
GemHelper.new(dir).install
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :spec_path, :base, :name
|
10
|
+
|
11
|
+
def initialize(base, name = nil)
|
12
|
+
@base = base
|
13
|
+
@name = name || interpolate_name
|
14
|
+
@spec_path = File.join(@base, "#{@name}.gemspec")
|
15
|
+
end
|
16
|
+
|
17
|
+
def install
|
18
|
+
desc 'Build your gem into the pkg directory'
|
19
|
+
task 'build' do
|
20
|
+
build_gem
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'Install your gem into the pkg directory'
|
24
|
+
task 'install' do
|
25
|
+
install_gem
|
26
|
+
end
|
27
|
+
|
28
|
+
desc 'Push your gem to rubygems'
|
29
|
+
task 'push' do
|
30
|
+
push_gem
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def build_gem
|
35
|
+
file_name = nil
|
36
|
+
sh("gem build #{spec_path}") {
|
37
|
+
file_name = File.basename(built_gem_path)
|
38
|
+
FileUtils.mkdir_p(File.join(base, 'pkg'))
|
39
|
+
FileUtils.mv(built_gem_path, 'pkg')
|
40
|
+
}
|
41
|
+
File.join(base, 'pkg', file_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def install_gem
|
45
|
+
built_gem_path = build_gem
|
46
|
+
sh("gem install #{built_gem_path}")
|
47
|
+
end
|
48
|
+
|
49
|
+
def push_gem
|
50
|
+
guard_clean
|
51
|
+
guard_already_tagged
|
52
|
+
tag_version {
|
53
|
+
git_push
|
54
|
+
rubygem_push(build_gem)
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
def rubygem_push(path)
|
60
|
+
sh("gem push #{path}")
|
61
|
+
end
|
62
|
+
|
63
|
+
def built_gem_path
|
64
|
+
Dir[File.join(base, "#{name}-*.gem")].sort_by{|f| File.mtime(f)}.last
|
65
|
+
end
|
66
|
+
|
67
|
+
def interpolate_name
|
68
|
+
gemspecs = Dir[File.join(base, "*.gemspec")]
|
69
|
+
raise "Unable to determine name from existing gemspec." unless gemspecs.size == 1
|
70
|
+
|
71
|
+
File.basename(gemspecs.first)[/^(.*)\.gemspec$/, 1]
|
72
|
+
end
|
73
|
+
|
74
|
+
def git_push
|
75
|
+
sh "git push --all"
|
76
|
+
sh "git push --tags"
|
77
|
+
end
|
78
|
+
|
79
|
+
def guard_already_tagged
|
80
|
+
sh('git tag').split(/\n/).include?(current_version_tag) and raise("This tag has already been committed to the repo.")
|
81
|
+
end
|
82
|
+
|
83
|
+
def guard_clean
|
84
|
+
clean? or raise("There are files that need to be committed first.")
|
85
|
+
end
|
86
|
+
|
87
|
+
def clean?
|
88
|
+
sh("git ls-files -dm").split("\n").size.zero?
|
89
|
+
end
|
90
|
+
|
91
|
+
def tag_version
|
92
|
+
sh "git tag #{current_version_tag}"
|
93
|
+
yield if block_given?
|
94
|
+
rescue
|
95
|
+
sh "git tag -d #{current_version_tag}"
|
96
|
+
raise
|
97
|
+
end
|
98
|
+
|
99
|
+
def current_version
|
100
|
+
raise("Version file could not be found at #{version_file_path}") unless File.exist?(version_file_path)
|
101
|
+
File.read(version_file_path)[/V(ERSION|ersion)\s*=\s*(["'])(.*?)\2/, 3]
|
102
|
+
end
|
103
|
+
|
104
|
+
def version_file_path
|
105
|
+
File.join(base, 'lib', name, 'version.rb')
|
106
|
+
end
|
107
|
+
|
108
|
+
def current_version_tag
|
109
|
+
"v#{current_version}"
|
110
|
+
end
|
111
|
+
|
112
|
+
def sh(cmd, &block)
|
113
|
+
output, code = sh_with_code(cmd, &block)
|
114
|
+
code == 0 ? output : raise(output)
|
115
|
+
end
|
116
|
+
|
117
|
+
def sh_with_code(cmd, &block)
|
118
|
+
output = ''
|
119
|
+
Dir.chdir(base) {
|
120
|
+
output = `#{cmd}`
|
121
|
+
block.call if block and $? == 0
|
122
|
+
}
|
123
|
+
[output, $?]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module QueueingProxy
|
2
|
+
class Dispatcher
|
3
|
+
attr_reader :logger
|
4
|
+
|
5
|
+
def initialize(logger, to_host, to_port, beanstalk_host, tube)
|
6
|
+
@logger, @to_host, @to_port, @beanstalk_host, @tube = logger, to_host, to_port, beanstalk_host, tube
|
7
|
+
@beanstalk = EMJack::Connection.new(:host => @beanstalk_host, :tube => @tube)
|
8
|
+
@beanstalk.watch(@tube)
|
9
|
+
logger.info "Starting dispatcher on #{to_host}:#{to_port} using beanstalk at #{tube}@#{beanstalk_host}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
@beanstalk.reserve do |job|
|
14
|
+
logger.info "Dispatching #{job.jobid}"
|
15
|
+
parsed_job = JSON.parse(job.body)
|
16
|
+
begin
|
17
|
+
EventMachine.connect(@to_host, @to_port, DispatchClient) { |c|
|
18
|
+
c.payload = parsed_job['data']
|
19
|
+
c.dispatcher = self
|
20
|
+
c.logger = logger
|
21
|
+
c.job = job
|
22
|
+
c.dispatcher = self
|
23
|
+
}
|
24
|
+
rescue EventMachine::ConnectionError
|
25
|
+
job.release(:delay => 5)
|
26
|
+
logger.info("Problem connecting")
|
27
|
+
EM.add_timer(5){ run }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class DispatchClient < EventMachine::Connection
|
33
|
+
attr_accessor :payload, :dispatcher, :logger, :dispatcher, :job
|
34
|
+
|
35
|
+
def connection_completed
|
36
|
+
send_data(payload)
|
37
|
+
end
|
38
|
+
|
39
|
+
def receive_data(data)
|
40
|
+
status = Integer(data[/^HTTP\/(1\.1|1\.0) (\d+)/, 2])
|
41
|
+
close_connection
|
42
|
+
if status == 200
|
43
|
+
logger.info "Done dispatching #{job.jobid}"
|
44
|
+
job.delete
|
45
|
+
else
|
46
|
+
logger.info "Error #{status}"
|
47
|
+
job.release(:delay => 5)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def unbind
|
52
|
+
dispatcher.run
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module QueueingProxy
|
4
|
+
class DSL
|
5
|
+
def initialize(&block)
|
6
|
+
@dispatcher_count = 1
|
7
|
+
@logger = Logger.new(STDOUT)
|
8
|
+
instance_eval(&block) if block
|
9
|
+
end
|
10
|
+
|
11
|
+
def to(host, port)
|
12
|
+
@to_host = host
|
13
|
+
@to_port = port
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def from(host, port)
|
18
|
+
@from_host = host
|
19
|
+
@from_port = port
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def times(count)
|
24
|
+
@dispatcher_count = count
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def queue_with(beanstalk_host, tube)
|
29
|
+
@beanstalk_host = beanstalk_host
|
30
|
+
@tube = tube
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def logger(logger)
|
35
|
+
@logger = logger
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def run
|
40
|
+
unless EM.reactor_running?
|
41
|
+
EM.run{ run }
|
42
|
+
else
|
43
|
+
Queuer.new(@logger, @from_host, @from_port, @beanstalk_host, @tube).run
|
44
|
+
@dispatcher_count.times { Dispatcher.new(@logger, @to_host, @to_port, @beanstalk_host, @tube).run }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module QueueingProxy
|
2
|
+
class Queuer
|
3
|
+
attr_reader :logger
|
4
|
+
|
5
|
+
def initialize(logger, host, port, beanstalk_host, tube)
|
6
|
+
@logger, @host, @port, @beanstalk_host, @tube = logger, host, port, beanstalk_host, tube
|
7
|
+
logger.info "Starting queuer on #{host}:#{port} using beanstalk at #{tube}@#{beanstalk_host}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
beanstalk = EMJack::Connection.new(:host => @beanstalk_host, :tube => @tube)
|
12
|
+
app = proc do |env|
|
13
|
+
logger.info "Queueing #{env['HTTP_VERSION']} #{env['PATH_INFO']} #{env['REQUEST_METHOD']}"
|
14
|
+
[200, {}, []]
|
15
|
+
end
|
16
|
+
backend = FakeBackend.new
|
17
|
+
EM.start_server(@host, @port, QueuerConnection) do |conn|
|
18
|
+
conn.beanstalk = beanstalk
|
19
|
+
conn.app = app
|
20
|
+
conn.backend = backend
|
21
|
+
conn.logger = logger
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class FakeBackend
|
26
|
+
def connection_finished(conn)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class QueuerConnection < Thin::Connection
|
31
|
+
attr_accessor :beanstalk, :logger
|
32
|
+
|
33
|
+
def post_init
|
34
|
+
@data = ''
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
def receive_data(data)
|
39
|
+
@data << data
|
40
|
+
super(data)
|
41
|
+
end
|
42
|
+
|
43
|
+
def unbind
|
44
|
+
queue_data
|
45
|
+
super
|
46
|
+
end
|
47
|
+
|
48
|
+
def queue_data
|
49
|
+
if @data != ''
|
50
|
+
beanstalk.put({:data => @data, :time => Time.new.to_i}.to_json) { |id|
|
51
|
+
logger.info "Job queued #{id}"
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'thin'
|
2
|
+
require 'eventmachine'
|
3
|
+
require 'em-jack'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
require 'queueing_proxy/cli'
|
7
|
+
require 'queueing_proxy/dsl'
|
8
|
+
require 'queueing_proxy/queuer'
|
9
|
+
require 'queueing_proxy/version'
|
10
|
+
require 'queueing_proxy/dispatcher'
|
11
|
+
|
12
|
+
module QueueingProxy
|
13
|
+
|
14
|
+
def self.from(host, port)
|
15
|
+
DSL.new.from(host, port)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
def QueueingProxy(&blk)
|
21
|
+
QueueingProxy::DSL.new(&blk)
|
22
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'lib', 'queueing_proxy', 'version')
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'queueing_proxy'
|
7
|
+
s.version = QueueingProxy::VERSION
|
8
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
9
|
+
s.authors = ["Joshua Hull"]
|
10
|
+
s.date = '2010-07-21'
|
11
|
+
s.summary = "Queueing proxy backed by EM/Beanstalk for a very weird purpose."
|
12
|
+
s.description = "Queueing proxy backed by EM/Beanstalk for a very weird purpose."
|
13
|
+
s.email = %q{joshbuddy@gmail.com}
|
14
|
+
s.extra_rdoc_files = []
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.homepage = %q{http://github.com/joshbuddy/queueing_proxy}
|
17
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
s.rubygems_version = %q{1.3.7}
|
20
|
+
s.test_files = `git ls-files`.split("\n").select{|f| f =~ /^spec/}
|
21
|
+
s.rubyforge_project = 'queueing_proxy'
|
22
|
+
|
23
|
+
# dependencies
|
24
|
+
s.add_runtime_dependency 'eventmachine'
|
25
|
+
s.add_runtime_dependency 'em-jack'
|
26
|
+
s.add_runtime_dependency 'thin'
|
27
|
+
s.add_runtime_dependency 'json'
|
28
|
+
|
29
|
+
if s.respond_to? :specification_version then
|
30
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
31
|
+
s.specification_version = 3
|
32
|
+
|
33
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
34
|
+
else
|
35
|
+
end
|
36
|
+
else
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
metadata
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: queueing_proxy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Joshua Hull
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-07-21 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: eventmachine
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: em-jack
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: thin
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :runtime
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: json
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
type: :runtime
|
76
|
+
version_requirements: *id004
|
77
|
+
description: Queueing proxy backed by EM/Beanstalk for a very weird purpose.
|
78
|
+
email: joshbuddy@gmail.com
|
79
|
+
executables: []
|
80
|
+
|
81
|
+
extensions: []
|
82
|
+
|
83
|
+
extra_rdoc_files: []
|
84
|
+
|
85
|
+
files:
|
86
|
+
- Gemfile
|
87
|
+
- Rakefile
|
88
|
+
- bin/queueing_proxy
|
89
|
+
- ext/gem_rake.rb
|
90
|
+
- lib/queueing_proxy.rb
|
91
|
+
- lib/queueing_proxy/cli.rb
|
92
|
+
- lib/queueing_proxy/dispatcher.rb
|
93
|
+
- lib/queueing_proxy/dsl.rb
|
94
|
+
- lib/queueing_proxy/queuer.rb
|
95
|
+
- lib/queueing_proxy/version.rb
|
96
|
+
- queueing_proxy.gemspec
|
97
|
+
has_rdoc: true
|
98
|
+
homepage: http://github.com/joshbuddy/queueing_proxy
|
99
|
+
licenses: []
|
100
|
+
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options:
|
103
|
+
- --charset=UTF-8
|
104
|
+
require_paths:
|
105
|
+
- lib
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
hash: 3
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
version: "0"
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
hash: 3
|
121
|
+
segments:
|
122
|
+
- 0
|
123
|
+
version: "0"
|
124
|
+
requirements: []
|
125
|
+
|
126
|
+
rubyforge_project: queueing_proxy
|
127
|
+
rubygems_version: 1.3.7
|
128
|
+
signing_key:
|
129
|
+
specification_version: 3
|
130
|
+
summary: Queueing proxy backed by EM/Beanstalk for a very weird purpose.
|
131
|
+
test_files: []
|
132
|
+
|