em-twitter 0.1.4 → 0.2.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.
- data/.travis.yml +0 -4
- data/CONTRIBUTING.md +3 -0
- data/README.md +16 -5
- data/em-twitter.gemspec +5 -5
- data/lib/em-twitter.rb +4 -0
- data/lib/em-twitter/client.rb +8 -2
- data/lib/em-twitter/connection.rb +35 -12
- data/lib/em-twitter/version.rb +1 -1
- data/spec/em-twitter/client_spec.rb +16 -13
- data/spec/em-twitter/connection_error_handling_spec.rb +2 -1
- data/spec/em-twitter/connection_reconnect_spec.rb +92 -1
- data/spec/em-twitter/connection_spec.rb +66 -19
- data/spec/spec_helper.rb +2 -2
- metadata +78 -27
    
        data/.travis.yml
    CHANGED
    
    
    
        data/CONTRIBUTING.md
    ADDED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -1,8 +1,13 @@ | |
| 1 | 
            -
            # EM-Twitter | 
| 1 | 
            +
            # EM-Twitter
         | 
| 2 | 
            +
            [][travis]
         | 
| 3 | 
            +
            [][gemnasium]
         | 
| 4 | 
            +
            [][codeclimate]
         | 
| 5 | 
            +
             | 
| 2 6 | 
             
            EM-Twitter is an EventMachine-based ruby client for the [Twitter Streaming API](https://dev.twitter.com/docs/streaming-api).
         | 
| 3 7 |  | 
| 4 8 | 
             
            [travis]: http://travis-ci.org/spagalloco/em-twitter
         | 
| 5 9 | 
             
            [gemnasium]: https://gemnasium.com/spagalloco/em-twitter
         | 
| 10 | 
            +
            [codeclimate]: https://codeclimate.com/github/spagalloco/em-twitter
         | 
| 6 11 |  | 
| 7 12 | 
             
            ## Usage
         | 
| 8 13 |  | 
| @@ -99,6 +104,16 @@ client.on_max_reconnects do |timeout, count| | |
| 99 104 | 
             
            end
         | 
| 100 105 | 
             
            ```
         | 
| 101 106 |  | 
| 107 | 
            +
            ## Stream Processing
         | 
| 108 | 
            +
             | 
| 109 | 
            +
            We recommend using [TweetStream](https://github.com/intridea/tweetstream) for a higher abstraction level interface.
         | 
| 110 | 
            +
             | 
| 111 | 
            +
            ## REST
         | 
| 112 | 
            +
             | 
| 113 | 
            +
            To access the Twitter REST API, we recommend the [Twitter][] gem.
         | 
| 114 | 
            +
             | 
| 115 | 
            +
            [twitter]: https://github.com/sferik/twitter
         | 
| 116 | 
            +
             | 
| 102 117 | 
             
            ## Todo
         | 
| 103 118 |  | 
| 104 119 | 
             
            * Gzip encoding support (see [issue #1](https://github.com/spagalloco/em-twitter/issues/1) for more information)
         | 
| @@ -110,10 +125,6 @@ EM-Twitter is heavily inspired by Vladimir Kolesnikov's [twitter-stream](https:/ | |
| 110 125 |  | 
| 111 126 | 
             
            Testing with EM can be a challenge, but was made incredibly easy through the use of Hayes Davis' awesome [mockingbird](https://github.com/hayesdavis/mockingbird) gem.
         | 
| 112 127 |  | 
| 113 | 
            -
            ## Contributing
         | 
| 114 | 
            -
             | 
| 115 | 
            -
            Pull requests welcome: fork, make a topic branch, commit (squash when possible) *with tests* and I'll happily consider.
         | 
| 116 | 
            -
             | 
| 117 128 | 
             
            ## Copyright
         | 
| 118 129 |  | 
| 119 130 | 
             
            Copyright (c) 2012 Steve Agalloco. See [LICENSE](https://github.com/spagalloco/em-twitter/blob/master/LICENSE.md) for details.
         | 
    
        data/em-twitter.gemspec
    CHANGED
    
    | @@ -11,16 +11,16 @@ Gem::Specification.new do |gem| | |
| 11 11 | 
             
              gem.description = %q{Twitter Streaming API client for EventMachine}
         | 
| 12 12 | 
             
              gem.summary     = %q{Twitter Streaming API client for EventMachine}
         | 
| 13 13 |  | 
| 14 | 
            -
              gem.add_dependency  | 
| 15 | 
            -
              gem.add_dependency  | 
| 16 | 
            -
              gem.add_dependency  | 
| 14 | 
            +
              gem.add_dependency 'eventmachine', '~> 1.0'
         | 
| 15 | 
            +
              gem.add_dependency 'http_parser.rb', '~> 0.5'
         | 
| 16 | 
            +
              gem.add_dependency 'simple_oauth', '~> 0.1'
         | 
| 17 17 |  | 
| 18 18 | 
             
              gem.add_development_dependency 'rake'
         | 
| 19 19 | 
             
              gem.add_development_dependency 'rdiscount'
         | 
| 20 | 
            -
              gem.add_development_dependency 'rspec'
         | 
| 20 | 
            +
              gem.add_development_dependency 'rspec', '>= 2.11'
         | 
| 21 21 | 
             
              gem.add_development_dependency 'simplecov'
         | 
| 22 22 | 
             
              gem.add_development_dependency 'yard'
         | 
| 23 | 
            -
              gem.add_development_dependency 'mockingbird', '>= 0. | 
| 23 | 
            +
              gem.add_development_dependency 'mockingbird', '>= 0.2'
         | 
| 24 24 | 
             
              gem.add_development_dependency 'guard-rspec'
         | 
| 25 25 |  | 
| 26 26 | 
             
              gem.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)}
         | 
    
        data/lib/em-twitter.rb
    CHANGED
    
    
    
        data/lib/em-twitter/client.rb
    CHANGED
    
    | @@ -17,7 +17,8 @@ module EventMachine | |
| 17 17 | 
             
                    :reconnect_callback,
         | 
| 18 18 | 
             
                    :max_reconnects_callback,
         | 
| 19 19 | 
             
                    :close_callback,
         | 
| 20 | 
            -
                    :no_data_callback
         | 
| 20 | 
            +
                    :no_data_callback,
         | 
| 21 | 
            +
                    :service_unavailable_callback
         | 
| 21 22 | 
             
                  ].freeze unless defined?(CALLBACKS)
         | 
| 22 23 |  | 
| 23 24 | 
             
                  attr_accessor :connection, :options, :host, :port
         | 
| @@ -32,6 +33,7 @@ module EventMachine | |
| 32 33 |  | 
| 33 34 | 
             
                  def initialize(options = {})
         | 
| 34 35 | 
             
                    @options = DEFAULT_CONNECTION_OPTIONS.merge(options)
         | 
| 36 | 
            +
                    @options[:params].merge!(EM::Twitter::DEFAULT_REQUEST_PARAMETERS)
         | 
| 35 37 |  | 
| 36 38 | 
             
                    validate_client
         | 
| 37 39 |  | 
| @@ -87,6 +89,10 @@ module EventMachine | |
| 87 89 | 
             
                  end
         | 
| 88 90 | 
             
                  alias :on_rate_limited :on_enhance_your_calm
         | 
| 89 91 |  | 
| 92 | 
            +
                  def on_service_unavailable(&block)
         | 
| 93 | 
            +
                    @service_unavailable_callback = block
         | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
             | 
| 90 96 | 
             
                  def on_reconnect(&block)
         | 
| 91 97 | 
             
                    @reconnect_callback = block
         | 
| 92 98 | 
             
                  end
         | 
| @@ -123,4 +129,4 @@ module EventMachine | |
| 123 129 |  | 
| 124 130 | 
             
                end
         | 
| 125 131 | 
             
              end
         | 
| 126 | 
            -
            end
         | 
| 132 | 
            +
            end
         | 
| @@ -35,6 +35,9 @@ module EventMachine | |
| 35 35 | 
             
                      @certificate_store  = OpenSSL::X509::Store.new
         | 
| 36 36 | 
             
                      @certificate_store.add_file(@options[:ssl][:cert_chain_file])
         | 
| 37 37 | 
             
                    end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    @network_reconnector     = EM::Twitter::Reconnectors::NetworkFailure.new
         | 
| 40 | 
            +
                    @application_reconnector = EM::Twitter::Reconnectors::ApplicationFailure.new
         | 
| 38 41 | 
             
                  end
         | 
| 39 42 |  | 
| 40 43 | 
             
                  # Called after the connection to the server is completed. Initiates a
         | 
| @@ -49,8 +52,8 @@ module EventMachine | |
| 49 52 | 
             
                  end
         | 
| 50 53 |  | 
| 51 54 | 
             
                  def post_init
         | 
| 52 | 
            -
                    @headers | 
| 53 | 
            -
                    @reconnector | 
| 55 | 
            +
                    @headers     = {}
         | 
| 56 | 
            +
                    @reconnector = @network_reconnector
         | 
| 54 57 |  | 
| 55 58 | 
             
                    @stall_timer = EM::PeriodicTimer.new(STALL_TIMER) do
         | 
| 56 59 | 
             
                      if gracefully_closed?
         | 
| @@ -73,20 +76,21 @@ module EventMachine | |
| 73 76 |  | 
| 74 77 | 
             
                  # Close the connection gracefully, without reconnecting
         | 
| 75 78 | 
             
                  def stop
         | 
| 76 | 
            -
                    @ | 
| 79 | 
            +
                    @auto_reconnect     = false
         | 
| 80 | 
            +
                    @gracefully_closed  = true
         | 
| 77 81 | 
             
                    close_connection
         | 
| 78 82 | 
             
                  end
         | 
| 79 83 |  | 
| 80 84 | 
             
                  # Immediately reconnects the connection
         | 
| 81 85 | 
             
                  def immediate_reconnect
         | 
| 82 | 
            -
                    @immediate_reconnect | 
| 83 | 
            -
                    @gracefully_closed | 
| 86 | 
            +
                    @immediate_reconnect  = true
         | 
| 87 | 
            +
                    @gracefully_closed    = false
         | 
| 84 88 | 
             
                    close_connection
         | 
| 85 89 | 
             
                  end
         | 
| 86 90 |  | 
| 87 91 | 
             
                  # Called when a connection is disconnected
         | 
| 88 92 | 
             
                  def unbind
         | 
| 89 | 
            -
                    schedule_reconnect if  | 
| 93 | 
            +
                    schedule_reconnect if auto_reconnect_on_close?
         | 
| 90 94 | 
             
                    invoke_callback(@client.close_callback)
         | 
| 91 95 | 
             
                  end
         | 
| 92 96 |  | 
| @@ -110,6 +114,16 @@ module EventMachine | |
| 110 114 | 
             
                    @immediate_reconnect
         | 
| 111 115 | 
             
                  end
         | 
| 112 116 |  | 
| 117 | 
            +
                  # Determines if the connection should reconnect if the connection closes
         | 
| 118 | 
            +
                  def auto_reconnect_on_close?
         | 
| 119 | 
            +
                    auto_reconnect? && !gracefully_closed?
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                  # Returns the current state of the auto_reconnect flag.
         | 
| 123 | 
            +
                  def auto_reconnect?
         | 
| 124 | 
            +
                    @auto_reconnect
         | 
| 125 | 
            +
                  end
         | 
| 126 | 
            +
             | 
| 113 127 | 
             
                  def stalled?
         | 
| 114 128 | 
             
                    @last_response ||= Response.new
         | 
| 115 129 | 
             
                    @last_response.older_than?(STALL_TIMEOUT)
         | 
| @@ -146,12 +160,16 @@ module EventMachine | |
| 146 160 | 
             
                    #   BaseDecoder.new
         | 
| 147 161 | 
             
                    # end
         | 
| 148 162 |  | 
| 149 | 
            -
                    # since we got a response use the application failure reconnector
         | 
| 150 | 
            -
                    # to handle redirects
         | 
| 151 | 
            -
                    @reconnector = EM::Twitter::Reconnectors::ApplicationFailure.new
         | 
| 152 | 
            -
             | 
| 153 163 | 
             
                    # everything below here is error handling so return if we got a 200
         | 
| 154 | 
            -
                     | 
| 164 | 
            +
                    if @response_code.to_i == 200
         | 
| 165 | 
            +
                      @network_reconnector.reset
         | 
| 166 | 
            +
                      @application_reconnector.reset
         | 
| 167 | 
            +
                      return
         | 
| 168 | 
            +
                    end
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                    # since we got a response use the application failure reconnector
         | 
| 171 | 
            +
                    # to handle reconnects
         | 
| 172 | 
            +
                    @reconnector = @application_reconnector
         | 
| 155 173 |  | 
| 156 174 | 
             
                    case @response_code
         | 
| 157 175 | 
             
                    when 401 then invoke_callback(@client.unauthorized_callback)
         | 
| @@ -161,6 +179,7 @@ module EventMachine | |
| 161 179 | 
             
                    when 413 then invoke_callback(@client.too_long_callback)
         | 
| 162 180 | 
             
                    when 416 then invoke_callback(@client.range_unacceptable_callback)
         | 
| 163 181 | 
             
                    when 420 then invoke_callback(@client.enhance_your_calm_callback)
         | 
| 182 | 
            +
                    when 503 then invoke_callback(@client.service_unavailable_callback)
         | 
| 164 183 | 
             
                    else
         | 
| 165 184 | 
             
                      msg = "Unhandled status code: #{@response_code}."
         | 
| 166 185 | 
             
                      invoke_callback(@client.error_callback, msg)
         | 
| @@ -262,6 +281,9 @@ module EventMachine | |
| 262 281 | 
             
                                    @reconnector.reconnect_timeout,
         | 
| 263 282 | 
             
                                    @reconnector.reconnect_count)
         | 
| 264 283 |  | 
| 284 | 
            +
                    # don't assume a successful reconnect so use the network reconnector
         | 
| 285 | 
            +
                    @reconnector = @network_reconnector
         | 
| 286 | 
            +
             | 
| 265 287 | 
             
                    if reconnect_timeout.zero?
         | 
| 266 288 | 
             
                      reconnect(@host, @port)
         | 
| 267 289 | 
             
                    else
         | 
| @@ -284,8 +306,9 @@ module EventMachine | |
| 284 306 |  | 
| 285 307 | 
             
                    @gracefully_closed    = false
         | 
| 286 308 | 
             
                    @immediate_reconnect  = false
         | 
| 309 | 
            +
                    @auto_reconnect       = @options[:auto_reconnect]
         | 
| 287 310 | 
             
                  end
         | 
| 288 311 |  | 
| 289 312 | 
             
                end
         | 
| 290 313 | 
             
              end
         | 
| 291 | 
            -
            end
         | 
| 314 | 
            +
            end
         | 
    
        data/lib/em-twitter/version.rb
    CHANGED
    
    
| @@ -9,6 +9,11 @@ describe EM::Twitter::Client do | |
| 9 9 | 
             
                    EM::Twitter::Client.new(opts)
         | 
| 10 10 | 
             
                  }.should raise_error(EM::Twitter::ConfigurationError)
         | 
| 11 11 | 
             
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                it 'merges default request parameters' do
         | 
| 14 | 
            +
                  client = EM::Twitter::Client.new(default_options)
         | 
| 15 | 
            +
                  client.options[:params].should include(:stall_warnings => 'true')
         | 
| 16 | 
            +
                end
         | 
| 12 17 | 
             
              end
         | 
| 13 18 |  | 
| 14 19 | 
             
              describe '.connect' do
         | 
| @@ -18,17 +23,15 @@ describe EM::Twitter::Client do | |
| 18 23 | 
             
                  EM.stub(:connect).and_return(conn)
         | 
| 19 24 | 
             
                end
         | 
| 20 25 |  | 
| 21 | 
            -
                 | 
| 22 | 
            -
                   | 
| 23 | 
            -
                     | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
                    EM::Twitter::Client.connect(default_options)
         | 
| 31 | 
            -
                  end
         | 
| 26 | 
            +
                it 'connects to the configured host/port' do
         | 
| 27 | 
            +
                  EventMachine.should_receive(:connect).with(
         | 
| 28 | 
            +
                    test_options[:host],
         | 
| 29 | 
            +
                    test_options[:port],
         | 
| 30 | 
            +
                    EventMachine::Twitter::Connection,
         | 
| 31 | 
            +
                    kind_of(EM::Twitter::Client),
         | 
| 32 | 
            +
                    test_options[:host],
         | 
| 33 | 
            +
                    test_options[:port])
         | 
| 34 | 
            +
                  EM::Twitter::Client.connect(default_options)
         | 
| 32 35 | 
             
                end
         | 
| 33 36 |  | 
| 34 37 | 
             
                context 'when using a proxy' do
         | 
| @@ -44,7 +47,7 @@ describe EM::Twitter::Client do | |
| 44 47 | 
             
                  end
         | 
| 45 48 | 
             
                end
         | 
| 46 49 |  | 
| 47 | 
            -
                it " | 
| 50 | 
            +
                it "doesn't trigger SSL until connection is established" do
         | 
| 48 51 | 
             
                  connection = stub('EventMachine::Connection')
         | 
| 49 52 | 
             
                  EM.should_receive(:connect).and_return(connection)
         | 
| 50 53 | 
             
                  EM.should_not_receive(:start_tls)
         | 
| @@ -61,4 +64,4 @@ describe EM::Twitter::Client do | |
| 61 64 | 
             
                end
         | 
| 62 65 | 
             
              end
         | 
| 63 66 |  | 
| 64 | 
            -
            end
         | 
| 67 | 
            +
            end
         | 
| @@ -9,4 +9,5 @@ describe 'EM::Twitter::Connection error handling' do | |
| 9 9 | 
             
              error_callback_invoked('on_range_unacceptable', 416, 'Range Unacceptable')
         | 
| 10 10 | 
             
              error_callback_invoked('on_enhance_your_calm', 420, 'Enhance Your Calm')
         | 
| 11 11 | 
             
              error_callback_invoked('on_error', 500, 'Internal Server Error', 'An error occurred.')
         | 
| 12 | 
            -
             | 
| 12 | 
            +
              error_callback_invoked('on_service_unavailable', 503, 'Service Unavailable')
         | 
| 13 | 
            +
            end
         | 
| @@ -4,6 +4,97 @@ include EM::Twitter | |
| 4 4 |  | 
| 5 5 | 
             
            describe 'EM::Twitter::Connection reconnections' do
         | 
| 6 6 |  | 
| 7 | 
            +
              describe 'reconnector setting' do
         | 
| 8 | 
            +
                context 'on connect' do
         | 
| 9 | 
            +
                  before do
         | 
| 10 | 
            +
                    Mockingbird.setup(test_options) do
         | 
| 11 | 
            +
                      status 200, 'Success'
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  after { Mockingbird.teardown }
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  it 'uses the network failure reconnector' do
         | 
| 18 | 
            +
                    EM.run_block do
         | 
| 19 | 
            +
                      client = Client.connect(default_options)
         | 
| 20 | 
            +
                      client.connection.reconnector.should be_kind_of(Reconnectors::NetworkFailure)
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                context 'after successful connect' do
         | 
| 26 | 
            +
                  before do
         | 
| 27 | 
            +
                    Mockingbird.setup(test_options) do
         | 
| 28 | 
            +
                      status 200, 'Success'
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  after { Mockingbird.teardown }
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  it 'resets the network failure reconnector' do
         | 
| 35 | 
            +
                    Reconnectors::NetworkFailure.any_instance.should_receive(:reset)
         | 
| 36 | 
            +
                    EM.run do
         | 
| 37 | 
            +
                      EM::Timer.new(1) { EM.stop }
         | 
| 38 | 
            +
                      client = Client.connect(default_options)
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  it 'resets the application failure reconnector' do
         | 
| 43 | 
            +
                    Reconnectors::ApplicationFailure.any_instance.should_receive(:reset)
         | 
| 44 | 
            +
                    EM.run do
         | 
| 45 | 
            +
                      EM::Timer.new(1) { EM.stop }
         | 
| 46 | 
            +
                      client = Client.connect(default_options)
         | 
| 47 | 
            +
                      # EM::Timer.new(1) { EM.stop }
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                context 'on 4xx responses' do
         | 
| 53 | 
            +
                  before do
         | 
| 54 | 
            +
                    Mockingbird.setup(test_options) do
         | 
| 55 | 
            +
                      status 401, 'Unauthorized'
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  after { Mockingbird.teardown }
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  it 'uses the application failure reconnector' do
         | 
| 62 | 
            +
                    EM.run do
         | 
| 63 | 
            +
                      client = Client.connect(default_options)
         | 
| 64 | 
            +
                      EM::Timer.new(1) do
         | 
| 65 | 
            +
                        client.connection.reconnector.should be_kind_of(Reconnectors::ApplicationFailure)
         | 
| 66 | 
            +
                        EM.stop
         | 
| 67 | 
            +
                      end
         | 
| 68 | 
            +
                    end
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                context 'on reconnects' do
         | 
| 73 | 
            +
                  before do
         | 
| 74 | 
            +
                    Mockingbird.setup(test_options) do
         | 
| 75 | 
            +
                      on_connection(1) do
         | 
| 76 | 
            +
                        status 401, 'Unauthorized'
         | 
| 77 | 
            +
                        disconnect!
         | 
| 78 | 
            +
                      end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                      wait(5)
         | 
| 81 | 
            +
                    end
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                  after { Mockingbird.teardown }
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                  it 'set the reconnector to the network failure reconnector' do
         | 
| 87 | 
            +
                    EM.run do
         | 
| 88 | 
            +
                      client = Client.connect(default_options)
         | 
| 89 | 
            +
                      EM::Timer.new(1) do
         | 
| 90 | 
            +
                        client.connection.reconnector.should be_kind_of(Reconnectors::NetworkFailure)
         | 
| 91 | 
            +
                        EM.stop
         | 
| 92 | 
            +
                      end
         | 
| 93 | 
            +
                    end
         | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
              end
         | 
| 97 | 
            +
             | 
| 7 98 | 
             
              describe '#reconnect' do
         | 
| 8 99 | 
             
                before do
         | 
| 9 100 | 
             
                  Mockingbird.setup(test_options) do
         | 
| @@ -136,4 +227,4 @@ describe 'EM::Twitter::Connection reconnections' do | |
| 136 227 | 
             
                  end
         | 
| 137 228 | 
             
                end
         | 
| 138 229 | 
             
              end
         | 
| 139 | 
            -
            end
         | 
| 230 | 
            +
            end
         | 
| @@ -25,13 +25,15 @@ describe EM::Twitter::Connection do | |
| 25 25 | 
             
                describe '#each with partial responses' do
         | 
| 26 26 | 
             
                  before do
         | 
| 27 27 | 
             
                    Mockingbird.setup(test_options) do
         | 
| 28 | 
            +
                      status '200', 'Success'
         | 
| 29 | 
            +
             | 
| 28 30 | 
             
                      on_connection('*') do
         | 
| 29 | 
            -
                        status '200', 'Success'
         | 
| 30 31 | 
             
                        100.times do
         | 
| 31 | 
            -
                          send  | 
| 32 | 
            -
                          send  | 
| 32 | 
            +
                          send %({"foo":"ba)
         | 
| 33 | 
            +
                          send %(r"}\r\n)
         | 
| 33 34 | 
             
                        end
         | 
| 34 35 | 
             
                      end
         | 
| 36 | 
            +
             | 
| 35 37 | 
             
                    end
         | 
| 36 38 | 
             
                  end
         | 
| 37 39 |  | 
| @@ -43,24 +45,28 @@ describe EM::Twitter::Connection do | |
| 43 45 | 
             
                    EM.run do
         | 
| 44 46 | 
             
                      client = EM::Twitter::Client.connect(default_options)
         | 
| 45 47 | 
             
                      client.each do |message|
         | 
| 46 | 
            -
                        count  | 
| 47 | 
            -
                         | 
| 48 | 
            +
                        count += 1
         | 
| 49 | 
            +
                        if count >= 100
         | 
| 50 | 
            +
                          client.stop
         | 
| 51 | 
            +
                          EM.stop
         | 
| 52 | 
            +
                        end
         | 
| 48 53 | 
             
                      end
         | 
| 49 54 |  | 
| 50 | 
            -
                      EM::Timer.new( | 
| 55 | 
            +
                      EM::Timer.new(10) { EM.stop }
         | 
| 51 56 | 
             
                    end
         | 
| 52 57 |  | 
| 53 | 
            -
                    count.should  | 
| 58 | 
            +
                    count.should >= 100
         | 
| 54 59 | 
             
                  end
         | 
| 55 60 | 
             
                end
         | 
| 56 61 |  | 
| 57 62 | 
             
                describe '#each with full responses' do
         | 
| 58 63 | 
             
                  before do
         | 
| 59 64 | 
             
                    Mockingbird.setup(test_options) do
         | 
| 65 | 
            +
                      status '200', 'Success'
         | 
| 66 | 
            +
             | 
| 60 67 | 
             
                      on_connection('*') do
         | 
| 61 | 
            -
                        status '200', 'Success'
         | 
| 62 68 | 
             
                        100.times do
         | 
| 63 | 
            -
                          send  | 
| 69 | 
            +
                          send %({"foo":"bar"}\r\n)
         | 
| 64 70 | 
             
                        end
         | 
| 65 71 | 
             
                      end
         | 
| 66 72 |  | 
| @@ -70,27 +76,28 @@ describe EM::Twitter::Connection do | |
| 70 76 | 
             
                  after { Mockingbird.teardown }
         | 
| 71 77 |  | 
| 72 78 | 
             
                  it 'emits each complete response chunk' do
         | 
| 73 | 
            -
                    count = 0
         | 
| 74 79 | 
             
                    responses = []
         | 
| 75 80 |  | 
| 76 81 | 
             
                    EM.run do
         | 
| 77 82 | 
             
                      client = EM::Twitter::Client.connect(default_options)
         | 
| 78 83 | 
             
                      client.each do |message|
         | 
| 79 | 
            -
                        count = count + 1
         | 
| 80 84 | 
             
                        responses << message
         | 
| 81 | 
            -
                        EM.stop if  | 
| 85 | 
            +
                        EM.stop if responses.size >= 100
         | 
| 82 86 | 
             
                      end
         | 
| 83 87 |  | 
| 84 | 
            -
                      EM::Timer.new( | 
| 88 | 
            +
                      EM::Timer.new(10) { EM.stop }
         | 
| 85 89 | 
             
                    end
         | 
| 86 90 |  | 
| 87 | 
            -
                     | 
| 91 | 
            +
                    responses.size.should >= 100
         | 
| 88 92 | 
             
                    responses.last.should eq('{"foo":"bar"}')
         | 
| 89 93 | 
             
                  end
         | 
| 90 94 | 
             
                end
         | 
| 91 95 |  | 
| 92 96 | 
             
                describe 'stall handling' do
         | 
| 93 97 | 
             
                  before do
         | 
| 98 | 
            +
                    stub_const("EM::Twitter::Connection::STALL_TIMEOUT", 5)
         | 
| 99 | 
            +
                    stub_const("EM::Twitter::Connection::STALL_TIMER", 1)
         | 
| 100 | 
            +
             | 
| 94 101 | 
             
                    Mockingbird.setup(test_options) do
         | 
| 95 102 | 
             
                      wait(10)
         | 
| 96 103 | 
             
                    end
         | 
| @@ -112,7 +119,7 @@ describe EM::Twitter::Connection do | |
| 112 119 | 
             
                    called.should be_true
         | 
| 113 120 | 
             
                  end
         | 
| 114 121 |  | 
| 115 | 
            -
                  it ' | 
| 122 | 
            +
                  it 'closes the connection when stalled to prompt a reconnect' do
         | 
| 116 123 | 
             
                    called = false
         | 
| 117 124 | 
             
                    EM.run do
         | 
| 118 125 | 
             
                      client = EM::Twitter::Client.connect(default_options)
         | 
| @@ -128,7 +135,7 @@ describe EM::Twitter::Connection do | |
| 128 135 | 
             
                  end
         | 
| 129 136 |  | 
| 130 137 | 
             
                  it 'invokes a no-data callback when stalled without a response' do
         | 
| 131 | 
            -
                     | 
| 138 | 
            +
                    stalled = false
         | 
| 132 139 | 
             
                    EM.run do
         | 
| 133 140 | 
             
                      client = EM::Twitter::Client.connect(default_options)
         | 
| 134 141 | 
             
                      # this is kind of sneaky, using a stub on gracefully_closed?
         | 
| @@ -140,12 +147,12 @@ describe EM::Twitter::Connection do | |
| 140 147 | 
             
                        false
         | 
| 141 148 | 
             
                      end
         | 
| 142 149 | 
             
                      client.on_no_data_received do
         | 
| 143 | 
            -
                         | 
| 150 | 
            +
                        stalled = client.connection.stalled?
         | 
| 144 151 | 
             
                        EM.stop
         | 
| 145 152 | 
             
                      end
         | 
| 146 153 | 
             
                    end
         | 
| 147 154 |  | 
| 148 | 
            -
                     | 
| 155 | 
            +
                    stalled.should be_true
         | 
| 149 156 | 
             
                  end
         | 
| 150 157 | 
             
                end
         | 
| 151 158 | 
             
              end
         | 
| @@ -179,6 +186,14 @@ describe EM::Twitter::Connection do | |
| 179 186 | 
             
                    client.should be_gracefully_closed
         | 
| 180 187 | 
             
                  end
         | 
| 181 188 | 
             
                end
         | 
| 189 | 
            +
             | 
| 190 | 
            +
                it "doesn't auto-reconnect" do
         | 
| 191 | 
            +
                  EM.run_block do
         | 
| 192 | 
            +
                    client = EM::Twitter::Client.connect(default_options)
         | 
| 193 | 
            +
                    client.stop
         | 
| 194 | 
            +
                    client.connection.auto_reconnect?.should be_false
         | 
| 195 | 
            +
                  end
         | 
| 196 | 
            +
                end
         | 
| 182 197 | 
             
              end
         | 
| 183 198 |  | 
| 184 199 | 
             
              describe '#update' do
         | 
| @@ -219,4 +234,36 @@ describe EM::Twitter::Connection do | |
| 219 234 | 
             
                end
         | 
| 220 235 | 
             
              end
         | 
| 221 236 |  | 
| 222 | 
            -
             | 
| 237 | 
            +
              describe '#auto_reconnect?' do
         | 
| 238 | 
            +
                before do
         | 
| 239 | 
            +
                  Mockingbird.setup(test_options) do
         | 
| 240 | 
            +
                    100.times do
         | 
| 241 | 
            +
                      send '{"foo":"bar"}'
         | 
| 242 | 
            +
                    end
         | 
| 243 | 
            +
                  end
         | 
| 244 | 
            +
                end
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                after { Mockingbird.teardown }
         | 
| 247 | 
            +
             | 
| 248 | 
            +
                it 'indicates the auto_reconnect setting' do
         | 
| 249 | 
            +
                  EM.run do
         | 
| 250 | 
            +
                    client = EM::Twitter::Client.connect(default_options)
         | 
| 251 | 
            +
                    EM::Timer.new(1) do
         | 
| 252 | 
            +
                      client.auto_reconnect?.should be_true
         | 
| 253 | 
            +
                      EM.stop
         | 
| 254 | 
            +
                    end
         | 
| 255 | 
            +
                  end
         | 
| 256 | 
            +
                end
         | 
| 257 | 
            +
             | 
| 258 | 
            +
                it 'indicates the auto_reconnect setting when false' do
         | 
| 259 | 
            +
                  EM.run do
         | 
| 260 | 
            +
                    client = EM::Twitter::Client.connect(default_options.merge(:auto_reconnect => false))
         | 
| 261 | 
            +
                    EM::Timer.new(1) do
         | 
| 262 | 
            +
                      client.auto_reconnect?.should be_false
         | 
| 263 | 
            +
                      EM.stop
         | 
| 264 | 
            +
                    end
         | 
| 265 | 
            +
                  end
         | 
| 266 | 
            +
                end
         | 
| 267 | 
            +
              end
         | 
| 268 | 
            +
             | 
| 269 | 
            +
            end
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    | @@ -12,7 +12,7 @@ require 'rspec' | |
| 12 12 | 
             
            require 'mockingbird'
         | 
| 13 13 |  | 
| 14 14 | 
             
            def test_options
         | 
| 15 | 
            -
              { :host => '127.0.0.1', :port => 9551, :quiet =>  | 
| 15 | 
            +
              { :host => '127.0.0.1', :port => 9551, :quiet => true }
         | 
| 16 16 | 
             
            end
         | 
| 17 17 |  | 
| 18 18 | 
             
            def default_options
         | 
| @@ -77,4 +77,4 @@ def error_callback_invoked(callback, code, desc, msg = nil) | |
| 77 77 | 
             
                  called.should be_true
         | 
| 78 78 | 
             
                end
         | 
| 79 79 | 
             
              end
         | 
| 80 | 
            -
            end
         | 
| 80 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: em-twitter
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.2.0
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -9,22 +9,27 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2012- | 
| 12 | 
            +
            date: 2012-10-07 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: eventmachine
         | 
| 16 | 
            -
              requirement:  | 
| 16 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 17 17 | 
             
                none: false
         | 
| 18 18 | 
             
                requirements:
         | 
| 19 | 
            -
                - -  | 
| 19 | 
            +
                - - ~>
         | 
| 20 20 | 
             
                  - !ruby/object:Gem::Version
         | 
| 21 | 
            -
                    version: 1.0 | 
| 21 | 
            +
                    version: '1.0'
         | 
| 22 22 | 
             
              type: :runtime
         | 
| 23 23 | 
             
              prerelease: false
         | 
| 24 | 
            -
              version_requirements:  | 
| 24 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 25 | 
            +
                none: false
         | 
| 26 | 
            +
                requirements:
         | 
| 27 | 
            +
                - - ~>
         | 
| 28 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 29 | 
            +
                    version: '1.0'
         | 
| 25 30 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 26 31 | 
             
              name: http_parser.rb
         | 
| 27 | 
            -
              requirement:  | 
| 32 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 28 33 | 
             
                none: false
         | 
| 29 34 | 
             
                requirements:
         | 
| 30 35 | 
             
                - - ~>
         | 
| @@ -32,10 +37,15 @@ dependencies: | |
| 32 37 | 
             
                    version: '0.5'
         | 
| 33 38 | 
             
              type: :runtime
         | 
| 34 39 | 
             
              prerelease: false
         | 
| 35 | 
            -
              version_requirements:  | 
| 40 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 41 | 
            +
                none: false
         | 
| 42 | 
            +
                requirements:
         | 
| 43 | 
            +
                - - ~>
         | 
| 44 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 45 | 
            +
                    version: '0.5'
         | 
| 36 46 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 37 47 | 
             
              name: simple_oauth
         | 
| 38 | 
            -
              requirement:  | 
| 48 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 39 49 | 
             
                none: false
         | 
| 40 50 | 
             
                requirements:
         | 
| 41 51 | 
             
                - - ~>
         | 
| @@ -43,10 +53,15 @@ dependencies: | |
| 43 53 | 
             
                    version: '0.1'
         | 
| 44 54 | 
             
              type: :runtime
         | 
| 45 55 | 
             
              prerelease: false
         | 
| 46 | 
            -
              version_requirements:  | 
| 56 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 57 | 
            +
                none: false
         | 
| 58 | 
            +
                requirements:
         | 
| 59 | 
            +
                - - ~>
         | 
| 60 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                    version: '0.1'
         | 
| 47 62 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 48 63 | 
             
              name: rake
         | 
| 49 | 
            -
              requirement:  | 
| 64 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 50 65 | 
             
                none: false
         | 
| 51 66 | 
             
                requirements:
         | 
| 52 67 | 
             
                - - ! '>='
         | 
| @@ -54,10 +69,15 @@ dependencies: | |
| 54 69 | 
             
                    version: '0'
         | 
| 55 70 | 
             
              type: :development
         | 
| 56 71 | 
             
              prerelease: false
         | 
| 57 | 
            -
              version_requirements:  | 
| 72 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 73 | 
            +
                none: false
         | 
| 74 | 
            +
                requirements:
         | 
| 75 | 
            +
                - - ! '>='
         | 
| 76 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 77 | 
            +
                    version: '0'
         | 
| 58 78 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 59 79 | 
             
              name: rdiscount
         | 
| 60 | 
            -
              requirement:  | 
| 80 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 61 81 | 
             
                none: false
         | 
| 62 82 | 
             
                requirements:
         | 
| 63 83 | 
             
                - - ! '>='
         | 
| @@ -65,21 +85,31 @@ dependencies: | |
| 65 85 | 
             
                    version: '0'
         | 
| 66 86 | 
             
              type: :development
         | 
| 67 87 | 
             
              prerelease: false
         | 
| 68 | 
            -
              version_requirements:  | 
| 88 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 89 | 
            +
                none: false
         | 
| 90 | 
            +
                requirements:
         | 
| 91 | 
            +
                - - ! '>='
         | 
| 92 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 93 | 
            +
                    version: '0'
         | 
| 69 94 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 70 95 | 
             
              name: rspec
         | 
| 71 | 
            -
              requirement:  | 
| 96 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 72 97 | 
             
                none: false
         | 
| 73 98 | 
             
                requirements:
         | 
| 74 99 | 
             
                - - ! '>='
         | 
| 75 100 | 
             
                  - !ruby/object:Gem::Version
         | 
| 76 | 
            -
                    version: ' | 
| 101 | 
            +
                    version: '2.11'
         | 
| 77 102 | 
             
              type: :development
         | 
| 78 103 | 
             
              prerelease: false
         | 
| 79 | 
            -
              version_requirements:  | 
| 104 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 105 | 
            +
                none: false
         | 
| 106 | 
            +
                requirements:
         | 
| 107 | 
            +
                - - ! '>='
         | 
| 108 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 109 | 
            +
                    version: '2.11'
         | 
| 80 110 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 81 111 | 
             
              name: simplecov
         | 
| 82 | 
            -
              requirement:  | 
| 112 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 83 113 | 
             
                none: false
         | 
| 84 114 | 
             
                requirements:
         | 
| 85 115 | 
             
                - - ! '>='
         | 
| @@ -87,10 +117,15 @@ dependencies: | |
| 87 117 | 
             
                    version: '0'
         | 
| 88 118 | 
             
              type: :development
         | 
| 89 119 | 
             
              prerelease: false
         | 
| 90 | 
            -
              version_requirements:  | 
| 120 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 121 | 
            +
                none: false
         | 
| 122 | 
            +
                requirements:
         | 
| 123 | 
            +
                - - ! '>='
         | 
| 124 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 125 | 
            +
                    version: '0'
         | 
| 91 126 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 92 127 | 
             
              name: yard
         | 
| 93 | 
            -
              requirement:  | 
| 128 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 94 129 | 
             
                none: false
         | 
| 95 130 | 
             
                requirements:
         | 
| 96 131 | 
             
                - - ! '>='
         | 
| @@ -98,21 +133,31 @@ dependencies: | |
| 98 133 | 
             
                    version: '0'
         | 
| 99 134 | 
             
              type: :development
         | 
| 100 135 | 
             
              prerelease: false
         | 
| 101 | 
            -
              version_requirements:  | 
| 136 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 137 | 
            +
                none: false
         | 
| 138 | 
            +
                requirements:
         | 
| 139 | 
            +
                - - ! '>='
         | 
| 140 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 141 | 
            +
                    version: '0'
         | 
| 102 142 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 103 143 | 
             
              name: mockingbird
         | 
| 104 | 
            -
              requirement:  | 
| 144 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 105 145 | 
             
                none: false
         | 
| 106 146 | 
             
                requirements:
         | 
| 107 147 | 
             
                - - ! '>='
         | 
| 108 148 | 
             
                  - !ruby/object:Gem::Version
         | 
| 109 | 
            -
                    version: 0. | 
| 149 | 
            +
                    version: '0.2'
         | 
| 110 150 | 
             
              type: :development
         | 
| 111 151 | 
             
              prerelease: false
         | 
| 112 | 
            -
              version_requirements:  | 
| 152 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 153 | 
            +
                none: false
         | 
| 154 | 
            +
                requirements:
         | 
| 155 | 
            +
                - - ! '>='
         | 
| 156 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 157 | 
            +
                    version: '0.2'
         | 
| 113 158 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 114 159 | 
             
              name: guard-rspec
         | 
| 115 | 
            -
              requirement:  | 
| 160 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 116 161 | 
             
                none: false
         | 
| 117 162 | 
             
                requirements:
         | 
| 118 163 | 
             
                - - ! '>='
         | 
| @@ -120,7 +165,12 @@ dependencies: | |
| 120 165 | 
             
                    version: '0'
         | 
| 121 166 | 
             
              type: :development
         | 
| 122 167 | 
             
              prerelease: false
         | 
| 123 | 
            -
              version_requirements:  | 
| 168 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 169 | 
            +
                none: false
         | 
| 170 | 
            +
                requirements:
         | 
| 171 | 
            +
                - - ! '>='
         | 
| 172 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 173 | 
            +
                    version: '0'
         | 
| 124 174 | 
             
            description: Twitter Streaming API client for EventMachine
         | 
| 125 175 | 
             
            email: steve.agalloco@gmail.com
         | 
| 126 176 | 
             
            executables: []
         | 
| @@ -132,6 +182,7 @@ files: | |
| 132 182 | 
             
            - .rspec
         | 
| 133 183 | 
             
            - .travis.yml
         | 
| 134 184 | 
             
            - .yardopts
         | 
| 185 | 
            +
            - CONTRIBUTING.md
         | 
| 135 186 | 
             
            - Gemfile
         | 
| 136 187 | 
             
            - Guardfile
         | 
| 137 188 | 
             
            - LICENSE.md
         | 
| @@ -184,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 184 235 | 
             
                  version: '0'
         | 
| 185 236 | 
             
            requirements: []
         | 
| 186 237 | 
             
            rubyforge_project: 
         | 
| 187 | 
            -
            rubygems_version: 1.8. | 
| 238 | 
            +
            rubygems_version: 1.8.23
         | 
| 188 239 | 
             
            signing_key: 
         | 
| 189 240 | 
             
            specification_version: 3
         | 
| 190 241 | 
             
            summary: Twitter Streaming API client for EventMachine
         |