queueing_proxy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'ext/gem_rake'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require 'queueing_proxy'
6
+
7
+ QueueingProxy::CLI.start
8
+
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,17 @@
1
+ require 'thor'
2
+
3
+ module QueueingProxy
4
+ class CLI < Thor
5
+
6
+ def initialize
7
+ super
8
+ end
9
+
10
+ default_task :start
11
+
12
+ desc "start", "Start a proxy"
13
+ def start(config = '/etc/queueing_proxy.yml')
14
+
15
+ end
16
+ end
17
+ 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,3 @@
1
+ module QueueingProxy
2
+ VERSION = '0.0.1'
3
+ 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
+