gemerald_beanstalk 0.0.1 → 0.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.
- checksums.yaml +7 -0
- data/.travis.yml +2 -0
- data/.yardopts +7 -0
- data/Gemfile +0 -1
- data/README.md +4 -1
- data/Rakefile +5 -4
- data/gemerald_beanstalk.gemspec +3 -0
- data/lib/gemerald_beanstalk.rb +7 -1
- data/lib/gemerald_beanstalk/beanstalk.rb +1 -15
- data/lib/gemerald_beanstalk/beanstalk_helper.rb +15 -1
- data/lib/gemerald_beanstalk/event_server.rb +36 -0
- data/lib/gemerald_beanstalk/plugins/direct_connection.rb +11 -0
- data/lib/gemerald_beanstalk/plugins/direct_connection/client.rb +38 -0
- data/lib/gemerald_beanstalk/plugins/introspection.rb +19 -0
- data/lib/gemerald_beanstalk/server.rb +118 -33
- data/lib/gemerald_beanstalk/tube.rb +1 -1
- data/lib/gemerald_beanstalk/version.rb +1 -1
- data/test/test_helper.rb +9 -1
- data/test/unit/beanstalk_test.rb +23 -0
- data/test/unit/plugins/direct_connection/client_test.rb +90 -0
- data/test/unit/plugins/direct_connection_test.rb +36 -0
- data/test/unit/plugins/introspection_test.rb +52 -0
- data/test/unit/server_test.rb +152 -0
- metadata +74 -28
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 41a9a36dce59da44d721a91e44b7198756fa55a7
|
4
|
+
data.tar.gz: 7fec76d5aa209abc2dd69cd9c4b826e2e1025646
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 15a963ae599e27e9df6a908b284eecbca492c08193e78c5ab824741a81c82214134766a70b76a3a769d2311f0f51397f450374b9bf2314b28b8387affb564867
|
7
|
+
data.tar.gz: 00d797ae54d95b37c161c40ec8fb3eb414e9d8f88cabf96200a4dc19d45be43c14a6d515de87ecc5ddb52eff4d2276a931ca28718d087cb9f6837c37d77cb384
|
data/.travis.yml
CHANGED
data/.yardopts
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# GemeraldBeanstalk
|
2
|
+
[](http://badge.fury.io/rb/gemerald_beanstalk)
|
2
3
|
[](https://travis-ci.org/gemeraldbeanstalk/gemerald_beanstalk)
|
3
4
|
[](https://coveralls.io/r/gemeraldbeanstalk/gemerald_beanstalk)
|
4
5
|
[](https://codeclimate.com/github/gemeraldbeanstalk/gemerald_beanstalk)
|
@@ -27,7 +28,9 @@ The internals of GemeraldBeanstalk are undocumented at this point, with the
|
|
27
28
|
expectation being that it should be interacted with strictly via the [beanstalkd
|
28
29
|
protocol](https://github.com/kr/beanstalkd/blob/master/doc/protocol.md). This
|
29
30
|
will likely change in the future, allowing more programatic access directly to
|
30
|
-
the GemeraldBeanstalk::Beanstalk.
|
31
|
+
the GemeraldBeanstalk::Beanstalk. If you think better documentation is needed
|
32
|
+
pronto, create an issue and I will add docs.
|
33
|
+
|
31
34
|
|
32
35
|
## Installation
|
33
36
|
|
data/Rakefile
CHANGED
@@ -10,10 +10,11 @@ end
|
|
10
10
|
|
11
11
|
task :start_gemerald_beanstalk_test_server do
|
12
12
|
Thread.abort_on_exception = true
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
server = GemeraldBeanstalk::Server.new(ENV['BIND_ADDRESS'], ENV['PORT'])
|
14
|
+
event_reactor = GemeraldBeanstalk::Server.event_reactor_thread
|
15
|
+
trap("SIGINT") { event_reactor.kill }
|
16
|
+
puts "GemeraldBeanstalk listening on #{server.full_address}"
|
17
|
+
event_reactor.join
|
17
18
|
end
|
18
19
|
|
19
20
|
task :default => :test
|
data/gemerald_beanstalk.gemspec
CHANGED
@@ -22,4 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_dependency 'thread_safe'
|
23
23
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
24
24
|
spec.add_development_dependency 'rake'
|
25
|
+
spec.add_development_dependency 'beanstalk_integration_tests', '~> 0.0.8'
|
26
|
+
spec.add_development_dependency 'minitest_should'
|
27
|
+
spec.add_development_dependency 'mocha'
|
25
28
|
end
|
data/lib/gemerald_beanstalk.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
require 'set'
|
2
|
-
require 'gemerald_beanstalk/version'
|
3
2
|
require 'thread_safe'
|
3
|
+
require 'gemerald_beanstalk/version'
|
4
4
|
require 'gemerald_beanstalk/job'
|
5
5
|
require 'gemerald_beanstalk/beanstalk'
|
6
6
|
require 'gemerald_beanstalk/connection'
|
7
7
|
require 'gemerald_beanstalk/command'
|
8
8
|
require 'gemerald_beanstalk/jobs'
|
9
9
|
require 'gemerald_beanstalk/tube'
|
10
|
+
require 'gemerald_beanstalk/event_server'
|
10
11
|
require 'gemerald_beanstalk/server'
|
12
|
+
|
13
|
+
module GemeraldBeanstalk
|
14
|
+
module Plugin
|
15
|
+
end
|
16
|
+
end
|
@@ -4,25 +4,11 @@ require 'gemerald_beanstalk/beanstalk_helper'
|
|
4
4
|
|
5
5
|
class GemeraldBeanstalk::Beanstalk
|
6
6
|
|
7
|
-
# contains functionality supporting core commands
|
8
7
|
include GemeraldBeanstalk::BeanstalkHelper
|
9
8
|
|
10
|
-
|
11
|
-
# running on.
|
12
|
-
attr_reader :address
|
9
|
+
attr_reader :address, :max_job_size
|
13
10
|
|
14
|
-
# The maximum size in bytes that a job can be. Jobs exceeding this threshold
|
15
|
-
# will result in JOB_TOO_BIG responses.
|
16
|
-
attr_reader :max_job_size
|
17
11
|
|
18
|
-
|
19
|
-
# Initializes a new Beanstalk instance with the given +address+ and
|
20
|
-
# +maximum_job_size+. +address+ is a string identifying the host and port
|
21
|
-
# that the Beanstalk instance is running on. +maximum_job_size+ is the
|
22
|
-
# maximum size in bytes that a job can be. Jobs exceeding this threshold will
|
23
|
-
# result in JOB_TOO_BIG responses.
|
24
|
-
#
|
25
|
-
# beanstalk = GemeraldBeanstalk::Beanstalk.new('localhost:11300')
|
26
12
|
def initialize(address, maximum_job_size = 2**16)
|
27
13
|
@max_job_size = maximum_job_size
|
28
14
|
@address = address
|
@@ -19,6 +19,21 @@ module GemeraldBeanstalk::BeanstalkHelper
|
|
19
19
|
JOB_INACTIVE_STATES = GemeraldBeanstalk::Job::INACTIVE_STATES
|
20
20
|
JOB_RESERVED_STATES = GemeraldBeanstalk::Job::RESERVED_STATES
|
21
21
|
|
22
|
+
|
23
|
+
def self.included(beanstalk)
|
24
|
+
beanstalk.extend(ClassMethods)
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
module ClassMethods
|
29
|
+
|
30
|
+
def load_plugin(plugin_name)
|
31
|
+
include(GemeraldBeanstalk::Plugin.const_get(plugin_name))
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
|
22
37
|
# ease handling of odd case where put can return BAD_FORMAT but increment stats
|
23
38
|
def adjust_stats_cmd_put
|
24
39
|
adjust_stats_key(:'cmd-put')
|
@@ -296,5 +311,4 @@ module GemeraldBeanstalk::BeanstalkHelper
|
|
296
311
|
return "OK #{response.bytesize}\r\n#{response}\r\n"
|
297
312
|
end
|
298
313
|
|
299
|
-
|
300
314
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module GemeraldBeanstalk::EventServer
|
2
|
+
|
3
|
+
def beanstalk
|
4
|
+
return @beanstalk
|
5
|
+
end
|
6
|
+
|
7
|
+
|
8
|
+
def initialize(beanstalk)
|
9
|
+
@beanstalk = beanstalk
|
10
|
+
@partial_message = ''
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def post_init
|
16
|
+
@connection = beanstalk.connect(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def receive_data(data)
|
21
|
+
if data[-2, 2] == "\r\n"
|
22
|
+
message = @partial_message + data
|
23
|
+
@partial_message = ''
|
24
|
+
EventMachine.defer(proc { @connection.execute(message) })
|
25
|
+
else
|
26
|
+
@partial_message += data
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def unbind
|
32
|
+
beanstalk.disconnect(@connection)
|
33
|
+
@connection.close_connection
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'gemerald_beanstalk/plugins/direct_connection/client'
|
2
|
+
|
3
|
+
module GemeraldBeanstalk::Plugin::DirectConnection
|
4
|
+
|
5
|
+
def direct_connection_client
|
6
|
+
return GemeraldBeanstalk::Plugin::DirectConnection::Client.new(self)
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
GemeraldBeanstalk::Beanstalk.load_plugin(:DirectConnection)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module GemeraldBeanstalk::Plugin::DirectConnection
|
2
|
+
class Client
|
3
|
+
|
4
|
+
attr_reader :beanstalk, :connection
|
5
|
+
|
6
|
+
def close_connection
|
7
|
+
return unless connection.alive?
|
8
|
+
connection.close_connection
|
9
|
+
beanstalk.disconnect(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
def initialize(beanstalk)
|
14
|
+
@beanstalk = beanstalk
|
15
|
+
@connection = beanstalk.connect(self)
|
16
|
+
@async_response = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def transmit(message)
|
21
|
+
message += "\r\n" unless message[-2, 2] == "\r\n"
|
22
|
+
connection.execute(message)
|
23
|
+
while (async_response = @async_response).nil?
|
24
|
+
sleep 0.1
|
25
|
+
end
|
26
|
+
@async_response = nil
|
27
|
+
return async_response
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def send_data(message)
|
32
|
+
@async_response = message
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module GemeraldBeanstalk::Plugin::Introspection
|
2
|
+
|
3
|
+
def connections
|
4
|
+
return @connections
|
5
|
+
end
|
6
|
+
|
7
|
+
|
8
|
+
def jobs
|
9
|
+
return @jobs.compact
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
def tubes
|
14
|
+
return active_tubes
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
GemeraldBeanstalk::Beanstalk.load_plugin(:Introspection)
|
@@ -1,54 +1,139 @@
|
|
1
1
|
require 'eventmachine'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
3
|
+
class GemeraldBeanstalk::Server
|
4
|
+
|
5
|
+
# The default address to bind a server to. Matches beanstalkd.
|
6
|
+
DEFAULT_BIND_ADDRESS = '0.0.0.0'
|
7
|
+
|
8
|
+
# The default port that a server should listen on. Matches beanstalkd.
|
9
|
+
DEFAULT_PORT = 11300
|
10
|
+
|
11
|
+
# The address or hostname of the host the server is bound to
|
12
|
+
attr_reader :bind_address
|
13
|
+
|
14
|
+
# The port the server should listen on
|
15
|
+
attr_reader :port
|
16
|
+
|
17
|
+
# The bind_address and port of the server
|
18
|
+
attr_reader :full_address
|
19
|
+
|
20
|
+
# The beanstalk instance the server provides an interface for
|
21
|
+
attr_reader :beanstalk
|
22
|
+
|
23
|
+
# Index of existing servers
|
24
|
+
@@servers = ThreadSafe::Cache.new
|
25
|
+
|
26
|
+
|
27
|
+
# Returns the thread that the EventMachine event reactor is running in.
|
28
|
+
#
|
29
|
+
# @return [Thread] the thread the event reactor is running in.
|
30
|
+
def self.event_reactor_thread
|
31
|
+
return @@event_reactor_thread
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
# Create a new GemeraldBeanstalk::Server at the given `bind_address` and
|
36
|
+
# `port`. `start_on_init` controls whether the server is immediately started
|
37
|
+
# or starting the server should be deferred.
|
38
|
+
#
|
39
|
+
# @param bind_address [String] IP or hostname of the host the server is bound
|
40
|
+
# to
|
41
|
+
# @param port [Integer, String] The port the server should listen on
|
42
|
+
# @param start_on_init [Boolean] A boolean indicating whether or not the
|
43
|
+
# server should be started immediately or deferred.
|
44
|
+
# @example Start a new server immediately at 0.0.0.0:11300
|
45
|
+
# GemeraldBeanstalk::Server.new
|
46
|
+
# @example Create a new server at 127.0.0.1:11301 to be started later
|
47
|
+
# GemeraldBeanstalk::Server.new('127.0.0.1', 11301, false)
|
48
|
+
def initialize(bind_address = nil, port = nil, start_on_init = true)
|
49
|
+
@bind_address = bind_address || DEFAULT_BIND_ADDRESS
|
50
|
+
@port = port.nil? ? DEFAULT_PORT : Integer(port)
|
51
|
+
@full_address = "#{@bind_address}:#{@port}"
|
52
|
+
@started = false
|
53
|
+
start if start_on_init
|
18
54
|
end
|
19
55
|
|
20
56
|
|
21
|
-
|
22
|
-
|
57
|
+
# Flag indicating whether the server has been started and is currently
|
58
|
+
# running
|
59
|
+
def running?
|
60
|
+
return @started
|
23
61
|
end
|
24
62
|
|
25
63
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
64
|
+
# Adds the server to the EventMachine reactor, effectively starting the
|
65
|
+
# server. If the EventMachine reactor has not been started, it is started in
|
66
|
+
# a new thread. In the process create a new GemeraldBeanstalk::Beanstalk that
|
67
|
+
# the server provides the interface for. Returns after the server is open for
|
68
|
+
# connections.
|
69
|
+
#
|
70
|
+
# Currently changes $PROGRAM_NAME, however this behavior is likely to change.
|
71
|
+
#
|
72
|
+
# @raise RuntimeError if a server is already registered at the server's full
|
73
|
+
# address
|
74
|
+
# @return [GemeraldBeanstalk::Server] returns self
|
75
|
+
def start
|
76
|
+
raise RuntimeError, "Server already exists for address #{full_address}" if @@servers.put_if_absent(full_address, self)
|
77
|
+
@beanstalk = GemeraldBeanstalk::Beanstalk.new(full_address)
|
78
|
+
start_event_reactor
|
79
|
+
EventMachine.run do
|
80
|
+
@event_server = EventMachine.start_server(bind_address, port, GemeraldBeanstalk::EventServer, beanstalk)
|
81
|
+
EventMachine.add_periodic_timer(0.01, beanstalk.method(:update_state))
|
82
|
+
end
|
83
|
+
$PROGRAM_NAME = "gemerald_beanstalk:#{full_address}"
|
84
|
+
wait_for_action(:start)
|
85
|
+
@started = true
|
86
|
+
return self
|
30
87
|
end
|
31
88
|
|
32
89
|
|
33
|
-
|
34
|
-
|
90
|
+
# Stops the server by removing it from the EventMachine reactor. Returns when
|
91
|
+
# the server is no longer available for connections.
|
92
|
+
#
|
93
|
+
# @raise RuntimeError if no server is registered at the server's full address.
|
94
|
+
# @return [GemeraldBeanstalk::Server] returns self
|
95
|
+
def stop
|
96
|
+
registered_server = @@servers[full_address]
|
97
|
+
raise "Server with address #{full_address} does not appear to have been started" unless registered_server
|
98
|
+
EventMachine.stop_server(@event_server)
|
99
|
+
wait_for_action(:stop)
|
100
|
+
@@servers.delete(full_address)
|
101
|
+
@started = false
|
102
|
+
return self
|
35
103
|
end
|
36
104
|
|
37
105
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
106
|
+
private
|
107
|
+
|
108
|
+
|
109
|
+
# Starts the EventMachine reactor in a new thread.
|
110
|
+
def start_event_reactor
|
111
|
+
return true if EventMachine.reactor_running?
|
112
|
+
unless EventMachine.reactor_running?
|
113
|
+
@@event_reactor_thread = Thread.new { EventMachine.run }
|
114
|
+
while !EventMachine.reactor_running?
|
115
|
+
sleep 0.1
|
116
|
+
end
|
45
117
|
end
|
118
|
+
return true
|
46
119
|
end
|
47
120
|
|
48
121
|
|
49
|
-
|
50
|
-
|
51
|
-
|
122
|
+
# Handles waiting for a server instance to start or stop by repeatedly
|
123
|
+
# attempting to open TCPSocket connections.
|
124
|
+
def wait_for_action(action)
|
125
|
+
action = action.to_sym
|
126
|
+
loop do
|
127
|
+
begin
|
128
|
+
TCPSocket.new(bind_address, port)
|
129
|
+
rescue Errno::ECONNREFUSED
|
130
|
+
next if action == :start
|
131
|
+
break if action == :stop
|
132
|
+
rescue Errno::ECONNRESET
|
133
|
+
break if action == :stop
|
134
|
+
end
|
135
|
+
break if action == :start
|
136
|
+
end
|
52
137
|
end
|
53
138
|
|
54
139
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
require 'coveralls'
|
2
2
|
Coveralls.wear!
|
3
3
|
|
4
|
+
require 'test/unit'
|
5
|
+
require 'mocha/setup'
|
6
|
+
require 'minitest/autorun'
|
7
|
+
require 'minitest/should'
|
8
|
+
|
4
9
|
lib = File.expand_path('../../lib', __FILE__)
|
5
10
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
11
|
|
7
12
|
require 'gemerald_beanstalk'
|
8
|
-
$server ||= GemeraldBeanstalk::Server.
|
13
|
+
$server ||= GemeraldBeanstalk::Server.new(ENV['BIND_ADDRESS'], ENV['PORT'])
|
14
|
+
|
15
|
+
class GemeraldBeanstalkTest < MiniTest::Should::TestCase
|
16
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class BeanstalkTest < GemeraldBeanstalkTest
|
4
|
+
|
5
|
+
context '::load_plugin' do
|
6
|
+
|
7
|
+
should 'raise NameError if unknown plugin' do
|
8
|
+
assert_raises(NameError) do
|
9
|
+
GemeraldBeanstalk::Beanstalk.load_plugin(:Foo)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
should 'include the given plugin' do
|
15
|
+
GemeraldBeanstalk::Beanstalk.load_plugin(:Dummy)
|
16
|
+
assert GemeraldBeanstalk::Beanstalk.included_modules.include?(GemeraldBeanstalk::Plugin::Dummy)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
module GemeraldBeanstalk::Plugin::Dummy; end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'gemerald_beanstalk/plugins/direct_connection'
|
3
|
+
|
4
|
+
class DirectConnectionClientTest < GemeraldBeanstalkTest
|
5
|
+
|
6
|
+
setup do
|
7
|
+
@beanstalk = GemeraldBeanstalk::Beanstalk.new('localhost:11300')
|
8
|
+
@beanstalk.extend(GemeraldBeanstalk::Plugin::DirectConnection)
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
context '#transmit' do
|
13
|
+
|
14
|
+
should 'connect directly to Gemerald server' do
|
15
|
+
GemeraldBeanstalk::EventServer.expects(:new).never
|
16
|
+
|
17
|
+
current_connections = @beanstalk.send(:stats_connections)['current-connections']
|
18
|
+
client = @beanstalk.direct_connection_client
|
19
|
+
assert_equal "WATCHING 2\r\n", client.transmit("watch foo\r\n")
|
20
|
+
assert_equal "WATCHING 1\r\n", client.transmit("ignore default\r\n")
|
21
|
+
response = client.transmit("list-tubes-watched\r\n")
|
22
|
+
assert_equal "OK 9\r\n---\n- foo\r\n", response
|
23
|
+
assert_equal current_connections + 1, @beanstalk.send(:stats_connections)['current-connections']
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
should 'reset @async_response after receiving message' do
|
28
|
+
message = 'foo'
|
29
|
+
client = @beanstalk.direct_connection_client
|
30
|
+
connection = client.instance_variable_get(:@connection)
|
31
|
+
connection.expects(:execute)
|
32
|
+
client.instance_variable_set(:@async_response, message)
|
33
|
+
assert_equal message, client.transmit("stats\r\n")
|
34
|
+
assert_nil client.instance_variable_get(:@async_response)
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
should 'wait for and return response' do
|
39
|
+
client = @beanstalk.direct_connection_client
|
40
|
+
|
41
|
+
# Overwrite send_data to sleep to ensure delay
|
42
|
+
client.instance_eval do
|
43
|
+
def self.send_data(*)
|
44
|
+
sleep 1
|
45
|
+
@async_response = 'foo'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
assert_equal 'foo', client.transmit("stats\r\n")
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
context '#close_connection' do
|
56
|
+
|
57
|
+
setup do
|
58
|
+
@client = @beanstalk.direct_connection_client
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
should 'only execute when connection is alive to avoid stack overflow' do
|
63
|
+
@client.instance_variable_get(:@beanstalk).expects(:disconnect).never
|
64
|
+
@client.instance_variable_get(:@connection).expects(:alive?).returns(false)
|
65
|
+
@client.close_connection
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
should 'close connection connection and disconnect from beanstalk' do
|
70
|
+
@client.instance_variable_get(:@connection).expects(:close_connection)
|
71
|
+
@client.instance_variable_get(:@beanstalk).expects(:disconnect)
|
72
|
+
@client.close_connection
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
context '#send_data' do
|
79
|
+
|
80
|
+
should 'set @async_response to argument' do
|
81
|
+
assert_equal nil, @client.instance_variable_get(:@async_response)
|
82
|
+
@client = @beanstalk.direct_connection_client
|
83
|
+
message = 'foo'
|
84
|
+
@client.send_data(message)
|
85
|
+
assert_equal message, @client.instance_variable_get(:@async_response)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class DirectConnectionTest < GemeraldBeanstalkTest
|
4
|
+
|
5
|
+
context 'autoload' do
|
6
|
+
|
7
|
+
should 'automatically load plugin' do
|
8
|
+
GemeraldBeanstalk::Beanstalk.expects(:load_plugin).with(:DirectConnection)
|
9
|
+
load 'gemerald_beanstalk/plugins/direct_connection.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
context 'instance methods' do
|
16
|
+
|
17
|
+
setup do
|
18
|
+
@beanstalk = GemeraldBeanstalk::Beanstalk.new('localhost:11300')
|
19
|
+
@beanstalk.extend(GemeraldBeanstalk::Plugin::DirectConnection)
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
context '#direct_connection_client' do
|
24
|
+
|
25
|
+
should 'return a new GemeraldBeanstalk::DirrectConnection' do
|
26
|
+
assert_kind_of(
|
27
|
+
GemeraldBeanstalk::Plugin::DirectConnection::Client,
|
28
|
+
@beanstalk.direct_connection_client
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class IntrospectionTest < GemeraldBeanstalkTest
|
4
|
+
|
5
|
+
context 'autoload' do
|
6
|
+
|
7
|
+
should 'automatically load plugin' do
|
8
|
+
GemeraldBeanstalk::Beanstalk.expects(:load_plugin).with(:Introspection)
|
9
|
+
load 'gemerald_beanstalk/plugins/introspection.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
context 'instance methods' do
|
16
|
+
|
17
|
+
setup do
|
18
|
+
@beanstalk = GemeraldBeanstalk::Beanstalk.new('localhost:11300')
|
19
|
+
@beanstalk.extend(GemeraldBeanstalk::Plugin::Introspection)
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
context '#connections' do
|
24
|
+
|
25
|
+
should 'return the beanstalk instance connections object' do
|
26
|
+
assert_equal @beanstalk.instance_variable_get(:@connections), @beanstalk.connections
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
context '#jobs' do
|
33
|
+
|
34
|
+
should 'return the compacted beanstalk instance jobs object' do
|
35
|
+
assert_equal @beanstalk.instance_variable_get(:@jobs).compact, @beanstalk.jobs
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
context '#tubes' do
|
42
|
+
|
43
|
+
should 'return the beanstalk instance active_tubes' do
|
44
|
+
@beanstalk.expects(:active_tubes).once.returns({})
|
45
|
+
@beanstalk.tubes
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ServerTest < GemeraldBeanstalkTest
|
4
|
+
|
5
|
+
context '#new' do
|
6
|
+
|
7
|
+
should 'use defaults if specific values are not provided' do
|
8
|
+
default_bind_address = GemeraldBeanstalk::Server::DEFAULT_BIND_ADDRESS
|
9
|
+
default_port = GemeraldBeanstalk::Server::DEFAULT_PORT
|
10
|
+
GemeraldBeanstalk::Server.any_instance.expects(:start)
|
11
|
+
server = GemeraldBeanstalk::Server.new
|
12
|
+
assert_equal default_bind_address, server.bind_address
|
13
|
+
assert_equal default_port, server.port
|
14
|
+
assert_equal "#{default_bind_address}:#{default_port}", server.full_address
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
should 'take a bind_address, port, and auto start value' do
|
19
|
+
GemeraldBeanstalk::Server.any_instance.expects(:start).never
|
20
|
+
bind_address = '127.0.0.1'
|
21
|
+
port = 11301
|
22
|
+
server = GemeraldBeanstalk::Server.new(bind_address, port, false)
|
23
|
+
assert_equal bind_address, server.bind_address
|
24
|
+
assert_equal port, server.port
|
25
|
+
assert_equal "#{bind_address}:#{port}", server.full_address
|
26
|
+
assert_equal false, server.running?
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
should 'raise ArgumentError if port is not a valid integer' do
|
31
|
+
assert_raises(ArgumentError) do
|
32
|
+
GemeraldBeanstalk::Server.new('0.0.0.0', 'xxx', false)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
context '#start' do
|
40
|
+
|
41
|
+
setup do
|
42
|
+
@bind_address = '0.0.0.0'
|
43
|
+
@port = 11400
|
44
|
+
@full_address = "#{@bind_address}:#{@port}"
|
45
|
+
@server = GemeraldBeanstalk::Server.new(@bind_address, @port, false)
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
teardown do
|
50
|
+
@server.stop if @server.running?
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
should 'raise RuntimeError if a server is already registered at given address' do
|
55
|
+
@server.start
|
56
|
+
assert_raises(RuntimeError) do
|
57
|
+
GemeraldBeanstalk::Server.new(@bind_address, @port)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
should 'create a beanstalk with correct address for the server' do
|
63
|
+
beanstalk = GemeraldBeanstalk::Beanstalk.new(@full_address)
|
64
|
+
GemeraldBeanstalk::Beanstalk.expects(:new).with(@full_address).returns(beanstalk)
|
65
|
+
@server.start
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
should 'wait for server to start and set started to true' do
|
70
|
+
@server.start
|
71
|
+
begin
|
72
|
+
socket = TCPSocket.new(@bind_address, @port)
|
73
|
+
socket.close
|
74
|
+
started = true
|
75
|
+
rescue
|
76
|
+
started = false
|
77
|
+
end
|
78
|
+
assert_equal true, @server.running?
|
79
|
+
assert started, 'Expected to be able to open TCP connection to started server'
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
should 'register the server' do
|
84
|
+
@server.start
|
85
|
+
assert_equal GemeraldBeanstalk::Server.class_variable_get(:@@servers)[@full_address], @server
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
context '#stop' do
|
92
|
+
|
93
|
+
setup do
|
94
|
+
@bind_address = '0.0.0.0'
|
95
|
+
@port = 11400
|
96
|
+
@full_address = "#{@bind_address}:#{@port}"
|
97
|
+
@server = GemeraldBeanstalk::Server.new(@bind_address, @port, false)
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
should 'raise an error if the server is not registered' do
|
102
|
+
assert_raises(RuntimeError) do
|
103
|
+
@server.stop
|
104
|
+
end
|
105
|
+
@server.start
|
106
|
+
@server.stop
|
107
|
+
assert_equal false, @server.running?
|
108
|
+
assert_raises(RuntimeError) do
|
109
|
+
@server.stop
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
should 'kill the server and wait for its death' do
|
115
|
+
@server.start
|
116
|
+
@server.stop
|
117
|
+
assert_equal false, @server.running?
|
118
|
+
begin
|
119
|
+
socket = TCPSocket.new(@bind_address, @port)
|
120
|
+
socket.close
|
121
|
+
stopped = false
|
122
|
+
rescue
|
123
|
+
stopped = true
|
124
|
+
end
|
125
|
+
assert stopped, 'Did not expect to be able to open TCP connection to stopped server'
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
context '#start_event_reactor' do
|
132
|
+
|
133
|
+
setup do
|
134
|
+
@server = GemeraldBeanstalk::Server.new(nil, nil, false)
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
should 'start the EventMachine reactor' do
|
139
|
+
@server.send(:start_event_reactor)
|
140
|
+
assert EventMachine.reactor_running?
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
should 'not try to start EventMachine reactor if already running' do
|
145
|
+
@server.send(:start_event_reactor)
|
146
|
+
Thread.expects(:new).never
|
147
|
+
@server.send(:start_event_reactor)
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
metadata
CHANGED
@@ -1,78 +1,111 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gemerald_beanstalk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Freewrite.org
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-01-26 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: eventmachine
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: thread_safe
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: bundler
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- - ~>
|
45
|
+
- - "~>"
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '1.3'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- - ~>
|
52
|
+
- - "~>"
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '1.3'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: rake
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - ">="
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: '0'
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: beanstalk_integration_tests
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.0.8
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.0.8
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: minitest_should
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mocha
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
76
109
|
- !ruby/object:Gem::Version
|
77
110
|
version: '0'
|
78
111
|
description: RubyGem implementation of beanstalkd
|
@@ -82,8 +115,9 @@ executables: []
|
|
82
115
|
extensions: []
|
83
116
|
extra_rdoc_files: []
|
84
117
|
files:
|
85
|
-
- .gitignore
|
86
|
-
- .travis.yml
|
118
|
+
- ".gitignore"
|
119
|
+
- ".travis.yml"
|
120
|
+
- ".yardopts"
|
87
121
|
- Gemfile
|
88
122
|
- LICENSE
|
89
123
|
- README.md
|
@@ -94,40 +128,52 @@ files:
|
|
94
128
|
- lib/gemerald_beanstalk/beanstalk_helper.rb
|
95
129
|
- lib/gemerald_beanstalk/command.rb
|
96
130
|
- lib/gemerald_beanstalk/connection.rb
|
131
|
+
- lib/gemerald_beanstalk/event_server.rb
|
97
132
|
- lib/gemerald_beanstalk/job.rb
|
98
133
|
- lib/gemerald_beanstalk/jobs.rb
|
134
|
+
- lib/gemerald_beanstalk/plugins/direct_connection.rb
|
135
|
+
- lib/gemerald_beanstalk/plugins/direct_connection/client.rb
|
136
|
+
- lib/gemerald_beanstalk/plugins/introspection.rb
|
99
137
|
- lib/gemerald_beanstalk/server.rb
|
100
138
|
- lib/gemerald_beanstalk/tube.rb
|
101
139
|
- lib/gemerald_beanstalk/version.rb
|
102
140
|
- test/beanstalk_integration_tests_test.rb
|
103
141
|
- test/test_helper.rb
|
142
|
+
- test/unit/beanstalk_test.rb
|
143
|
+
- test/unit/plugins/direct_connection/client_test.rb
|
144
|
+
- test/unit/plugins/direct_connection_test.rb
|
145
|
+
- test/unit/plugins/introspection_test.rb
|
146
|
+
- test/unit/server_test.rb
|
104
147
|
homepage: https://github.com/gemeraldbeanstalk/gemerald_beanstalk
|
105
148
|
licenses:
|
106
149
|
- MIT
|
150
|
+
metadata: {}
|
107
151
|
post_install_message:
|
108
152
|
rdoc_options: []
|
109
153
|
require_paths:
|
110
154
|
- lib
|
111
155
|
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
-
none: false
|
113
156
|
requirements:
|
114
|
-
- -
|
157
|
+
- - ">="
|
115
158
|
- !ruby/object:Gem::Version
|
116
159
|
version: '0'
|
117
160
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
-
none: false
|
119
161
|
requirements:
|
120
|
-
- -
|
162
|
+
- - ">="
|
121
163
|
- !ruby/object:Gem::Version
|
122
164
|
version: '0'
|
123
165
|
requirements: []
|
124
166
|
rubyforge_project:
|
125
|
-
rubygems_version:
|
167
|
+
rubygems_version: 2.2.1
|
126
168
|
signing_key:
|
127
|
-
specification_version:
|
169
|
+
specification_version: 4
|
128
170
|
summary: Gemerald Beanstalk offers a Ruby implementation of beanstalkd for testing
|
129
171
|
and other uses.
|
130
172
|
test_files:
|
131
173
|
- test/beanstalk_integration_tests_test.rb
|
132
174
|
- test/test_helper.rb
|
133
|
-
|
175
|
+
- test/unit/beanstalk_test.rb
|
176
|
+
- test/unit/plugins/direct_connection/client_test.rb
|
177
|
+
- test/unit/plugins/direct_connection_test.rb
|
178
|
+
- test/unit/plugins/introspection_test.rb
|
179
|
+
- test/unit/server_test.rb
|