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 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
@@ -3,6 +3,7 @@ language: ruby
3
3
  rvm:
4
4
  - 1.9.3
5
5
  - 2.0.0
6
+ - 2.1.0
6
7
  - jruby-19mode
7
8
  - rbx-19mode
8
9
 
@@ -25,3 +26,4 @@ script:
25
26
  matrix:
26
27
  allow_failures:
27
28
  - rvm: jruby-19mode
29
+ - rvm: rbx-19mode
data/.yardopts ADDED
@@ -0,0 +1,7 @@
1
+ --output-dir doc/
2
+ --readme README.md
3
+ --title GemeraldBeanstalk
4
+ --markup=markdown
5
+ --protected
6
+ --private
7
+ lib/gemerald_beanstalk/**/*.rb
data/Gemfile CHANGED
@@ -3,6 +3,5 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :test do
6
- gem 'beanstalk_integration_tests', '~> 0.0.8'
7
6
  gem 'coveralls', :require => false
8
7
  end
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # GemeraldBeanstalk
2
+ [![Gem Version](https://badge.fury.io/rb/gemerald_beanstalk.png)](http://badge.fury.io/rb/gemerald_beanstalk)
2
3
  [![Build Status](https://travis-ci.org/gemeraldbeanstalk/gemerald_beanstalk.png?branch=master)](https://travis-ci.org/gemeraldbeanstalk/gemerald_beanstalk)
3
4
  [![Coverage Status](https://coveralls.io/repos/gemeraldbeanstalk/gemerald_beanstalk/badge.png)](https://coveralls.io/r/gemeraldbeanstalk/gemerald_beanstalk)
4
5
  [![Code Climate](https://codeclimate.com/github/gemeraldbeanstalk/gemerald_beanstalk.png)](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
- server_thread, beanstalk = GemeraldBeanstalk::Server.start(ENV['BIND_ADDRESS'], ENV['PORT'])
14
- trap("SIGINT") { server_thread.kill }
15
- puts "GemeraldBeanstalk listening on #{beanstalk.address}"
16
- server_thread.join
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
@@ -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
@@ -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
- # Colon-separated host and port of the Server the Beanstalk instance is
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
- module GemeraldBeanstalk::Server
4
-
5
- def self.start(bind_address = nil, port = nil)
6
- bind_address ||= '0.0.0.0'
7
- port ||= 11300
8
- full_address = "#{bind_address}:#{port}"
9
- beanstalk = GemeraldBeanstalk::Beanstalk.new(full_address)
10
- thread = Thread.new do
11
- EventMachine.run do
12
- EventMachine.start_server(bind_address, port, GemeraldBeanstalk::Server, beanstalk)
13
- EventMachine.add_periodic_timer(0.01, beanstalk.method(:update_state))
14
- end
15
- end
16
- $PROGRAM_NAME = "gemerald_beanstalk:#{full_address}"
17
- return [thread, beanstalk]
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
- def beanstalk
22
- return @beanstalk
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
- def initialize(beanstalk)
27
- @beanstalk = beanstalk
28
- @partial_message = ''
29
- super
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
- def post_init
34
- @connection = beanstalk.connect(self)
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
- def receive_data(data)
39
- if data[-2, 2] == "\r\n"
40
- message = @partial_message + data
41
- @partial_message = ''
42
- EventMachine.defer(proc { @connection.execute(message) })
43
- else
44
- @partial_message += data
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
- def unbind
50
- beanstalk.disconnect(@connection)
51
- @connection.close_connection
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
@@ -1,6 +1,6 @@
1
1
  class GemeraldBeanstalk::Tube
2
2
 
3
- attr_reader :jobs, :name, :reservartions
3
+ attr_reader :jobs, :name, :reservations
4
4
 
5
5
 
6
6
  def active?
@@ -1,3 +1,3 @@
1
1
  module GemeraldBeanstalk
2
- VERSION = '0.0.1'
2
+ VERSION = '0.1.0'
3
3
  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.start(ENV['BIND_ADDRESS'], ENV['PORT']).first
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.1
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: 2013-12-20 00:00:00.000000000 Z
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: 1.8.25
167
+ rubygems_version: 2.2.1
126
168
  signing_key:
127
- specification_version: 3
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
- has_rdoc:
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