gnip-stream 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.pryrc +2 -0
- data/.rvmrc +1 -0
- data/.travis.yml +1 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +44 -0
- data/Rakefile +1 -0
- data/gnip-stream.gemspec +24 -0
- data/lib/gnip-stream/data_buffer.rb +22 -0
- data/lib/gnip-stream/error_reconnect.rb +25 -0
- data/lib/gnip-stream/facebook_client.rb +22 -0
- data/lib/gnip-stream/json_stream.rb +11 -0
- data/lib/gnip-stream/powertrack_authentication.rb +27 -0
- data/lib/gnip-stream/powertrack_client.rb +31 -0
- data/lib/gnip-stream/stream.rb +58 -0
- data/lib/gnip-stream/stream_delegate.rb +15 -0
- data/lib/gnip-stream/version.rb +3 -0
- data/lib/gnip-stream/xml_stream.rb +10 -0
- data/lib/gnip-stream.rb +12 -0
- data/spec/gnip-stream/data_buffer_spec.rb +26 -0
- data/spec/gnip-stream/error_reconnect_spec.rb +23 -0
- data/spec/gnip-stream/facebook_client_spec.rb +28 -0
- data/spec/gnip-stream/json_stream_spec.rb +31 -0
- data/spec/gnip-stream/powertrack_authentication_spec.rb +34 -0
- data/spec/gnip-stream/powertrack_client_spec.rb +57 -0
- data/spec/gnip-stream/stream_spec.rb +59 -0
- data/spec/gnip-stream/xml_stream_spec.rb +30 -0
- data/spec/spec_helper.rb +4 -0
- metadata +105 -0
data/.gitignore
ADDED
data/.pryrc
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.2@gnip-stream --create
|
data/.travis.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
script: "bundle exec rspec spec/"
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) Sharethrough
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# gnip-stream
|
2
|
+
[![Build Status](https://secure.travis-ci.org/rweald/gnip-stream.png)](http://travis-ci.org/rweald/gnip-stream)
|
3
|
+
|
4
|
+
gnip-stream is a ruby library to connect and stream data from [GNIP](http://gnip.com/).
|
5
|
+
It utilizes EventMachine and threads under the hood to provide a true streaming
|
6
|
+
experience without you having to worry about writing non blocking code.
|
7
|
+
|
8
|
+
##Installation
|
9
|
+
|
10
|
+
Installing gnip-stream is easy. Simply add the following line to your
|
11
|
+
```Gemfile```:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'gnip-stream', :git => "https://github.com/rweald/gnip-stream"
|
15
|
+
```
|
16
|
+
|
17
|
+
##Simple Usage
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
require 'gnip-stream'
|
21
|
+
|
22
|
+
#To connect to the special twitter powertrack api
|
23
|
+
twitter_stream = GnipStream::PowertrackClient.new("http://yourstreamingurl.gnip.com", "someuser", "password")
|
24
|
+
twitter_stream.consume do |message|
|
25
|
+
#process the message however you want
|
26
|
+
puts message
|
27
|
+
end
|
28
|
+
|
29
|
+
#To Connect to the Facebook API
|
30
|
+
facebook_stream = GnipStream::FacebookClient.new("http://yourstreamingurl.gnip.com", "someuser", "password")
|
31
|
+
facebook_stream.consume do |message|
|
32
|
+
puts message
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
##Contributors
|
37
|
+
|
38
|
+
* [Ryan Weald](https://github.com/rweald)
|
39
|
+
* [Sharethrough Team](https://github.com/sharethrough)
|
40
|
+
|
41
|
+
##License
|
42
|
+
MIT. See [LICENSE](https://github.com/rweald/gnip-stream/blob/master/LICENSE) file for more details.
|
43
|
+
|
44
|
+
Special thanks to [Sharethrough](http://www.sharethrough.com/)
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/gnip-stream.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "gnip-stream/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "gnip-stream"
|
7
|
+
s.version = GnipStream::VERSION
|
8
|
+
s.authors = ["Ryan Weald"]
|
9
|
+
s.email = ["ryan@weald.com"]
|
10
|
+
s.homepage = "https://github.com/rweald/gnip-stream"
|
11
|
+
s.summary = %q{}
|
12
|
+
s.description = %q{}
|
13
|
+
|
14
|
+
s.rubyforge_project = "gnip-stream"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "rspec"
|
22
|
+
|
23
|
+
s.add_dependency "em-http-request", ">= 1.0.0"
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module GnipStream
|
2
|
+
class DataBuffer
|
3
|
+
attr_accessor :pattern
|
4
|
+
def initialize(pattern)
|
5
|
+
@pattern = pattern
|
6
|
+
@buffer = ""
|
7
|
+
end
|
8
|
+
|
9
|
+
def process(chunk)
|
10
|
+
@buffer.concat(chunk)
|
11
|
+
end
|
12
|
+
|
13
|
+
def complete_entries
|
14
|
+
entries = []
|
15
|
+
while (match_data = @buffer.match(@pattern))
|
16
|
+
entries << match_data.captures[0]
|
17
|
+
@buffer = match_data.captures[1]
|
18
|
+
end
|
19
|
+
entries
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module GnipStream
|
2
|
+
class ErrorReconnect
|
3
|
+
def initialize(source_class, method_name)
|
4
|
+
@source_class = source_class
|
5
|
+
@method_name = method_name
|
6
|
+
@reconnect_attempts = 0
|
7
|
+
end
|
8
|
+
|
9
|
+
def attempt_to_reconnect(error_message)
|
10
|
+
@error_message = error_message
|
11
|
+
if @reconnect_attempts < 5
|
12
|
+
@reconnect_attempts +=1
|
13
|
+
sleep(2)
|
14
|
+
@source_class.send(@method_name)
|
15
|
+
else
|
16
|
+
reconnect_failed_raise_error
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def reconnect_failed_raise_error
|
21
|
+
raise @error_message
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'gnip-stream/xml_stream'
|
2
|
+
|
3
|
+
module GnipStream
|
4
|
+
class FacebookClient
|
5
|
+
def initialize(url, username, password)
|
6
|
+
@stream = XmlStream.new(url, "authorization" => [username, password])
|
7
|
+
@error_handler = ErrorReconnect.new(self, :consume)
|
8
|
+
@connection_close_handler = ErrorReconnect.new(self, :consume)
|
9
|
+
configure_handlers
|
10
|
+
end
|
11
|
+
|
12
|
+
def configure_handlers
|
13
|
+
@stream.on_error { |error| @error_handler.attempt_to_reconnect("Gnip Connection Error. Reason was: #{error.inspect}") }
|
14
|
+
@stream.on_connection_close { @connection_close_handler.attempt_to_reconnect("Gnip Connection Closed") }
|
15
|
+
end
|
16
|
+
|
17
|
+
def consume(&block)
|
18
|
+
@stream.on_message(&block)
|
19
|
+
@stream.connect
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'gnip-stream/stream_delegate'
|
2
|
+
|
3
|
+
module GnipStream
|
4
|
+
class JsonStream
|
5
|
+
include StreamDelegate
|
6
|
+
def initialize(url, headers={})
|
7
|
+
json_processor = DataBuffer.new(Regexp.new(/^(\{.*\})\s\s(.*)/))
|
8
|
+
@stream = Stream.new(url, json_processor, headers)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module GnipStream
|
2
|
+
class PowertrackAuthentication
|
3
|
+
attr_accessor :cookies, :location
|
4
|
+
def initialize(url, username, password)
|
5
|
+
@url = url
|
6
|
+
@username = username
|
7
|
+
@password = password
|
8
|
+
end
|
9
|
+
|
10
|
+
def authenticate
|
11
|
+
EM.run do
|
12
|
+
http = EM::HttpRequest.new(@url).get(
|
13
|
+
:head => {"authorization" => [@username, @password]})
|
14
|
+
http.headers { |head| parse_response_header(head) }
|
15
|
+
http.callback { EM.stop }
|
16
|
+
http.error do
|
17
|
+
raise "Gnip Authentication Failed. Reason was #{http.error}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_response_header(header)
|
23
|
+
@location = header["LOCATION"]
|
24
|
+
@cookies = (header["SET_COOKIE"].first.split(";")[0..2].join(";"))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'gnip-stream/powertrack_authentication'
|
2
|
+
module GnipStream
|
3
|
+
class PowertrackClient
|
4
|
+
def initialize(url, username, password)
|
5
|
+
@authentication = PowertrackAuthentication.new(url, username, password)
|
6
|
+
@stream = JsonStream.new(url)
|
7
|
+
@error_handler = ErrorReconnect.new(self, :consume)
|
8
|
+
@connection_close_handler = ErrorReconnect.new(self, :consume)
|
9
|
+
configure_handlers
|
10
|
+
end
|
11
|
+
|
12
|
+
def configure_handlers
|
13
|
+
@stream.on_error { |error| @error_handler.attempt_to_reconnect("Gnip Connection Error. Reason was: #{error.inspect}") }
|
14
|
+
@stream.on_connection_close { @connection_close_handler.attempt_to_reconnect("Gnip Connection Closed") }
|
15
|
+
end
|
16
|
+
|
17
|
+
def consume(&block)
|
18
|
+
@client_callback = block
|
19
|
+
@stream.on_message(&@client_callback)
|
20
|
+
authenticate
|
21
|
+
@stream.connect
|
22
|
+
end
|
23
|
+
|
24
|
+
def authenticate
|
25
|
+
@authentication.authenticate
|
26
|
+
@stream.url = @authentication.location
|
27
|
+
@stream.headers = {"cookie" => @authentication.cookies}
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'em-http-request'
|
3
|
+
|
4
|
+
module GnipStream
|
5
|
+
class Stream
|
6
|
+
|
7
|
+
attr_accessor :headers, :options, :url, :username, :password
|
8
|
+
|
9
|
+
def initialize(url, processor, headers={})
|
10
|
+
@url = url
|
11
|
+
@headers = headers
|
12
|
+
@processor = processor
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_message(&block)
|
16
|
+
@on_message = block
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_connection_close(&block)
|
20
|
+
@on_connection_close = block
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_error(&block)
|
24
|
+
@on_error = block
|
25
|
+
end
|
26
|
+
|
27
|
+
def connect
|
28
|
+
EM.run do
|
29
|
+
http = EM::HttpRequest.new(@url, :inactivity_timeout => 0).get(:head => @headers)
|
30
|
+
http.stream { |chunk| process_chunk(chunk) }
|
31
|
+
http.callback {
|
32
|
+
handle_connection_close(http)
|
33
|
+
EM.stop
|
34
|
+
}
|
35
|
+
http.errback {
|
36
|
+
handle_error(http)
|
37
|
+
EM.stop
|
38
|
+
}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def process_chunk(chunk)
|
43
|
+
@processor.process(chunk)
|
44
|
+
@processor.complete_entries.each do |entry|
|
45
|
+
EM.defer { @on_message.call(entry) }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def handle_error(http_connection)
|
50
|
+
@on_error.call(http_connection)
|
51
|
+
end
|
52
|
+
|
53
|
+
def handle_connection_close(http_connection)
|
54
|
+
@on_connection_close.call(http_connection)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module GnipStream
|
2
|
+
|
3
|
+
module StreamDelegate
|
4
|
+
#Magic Method that will delegate all
|
5
|
+
# method calls to underlying stream if possible
|
6
|
+
def method_missing(m, *args, &block)
|
7
|
+
if @stream.respond_to?(m)
|
8
|
+
@stream.send(m, *args, &block)
|
9
|
+
else
|
10
|
+
super(m, *args, &block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'gnip-stream/stream_delegate'
|
2
|
+
module GnipStream
|
3
|
+
class XmlStream
|
4
|
+
include StreamDelegate
|
5
|
+
def initialize(url, headers={})
|
6
|
+
xml_processor = DataBuffer.new(Regexp.new(/^(\<entry.*?\<\/entry\>)(.*)/m))
|
7
|
+
@stream = Stream.new(url, xml_processor, headers)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/lib/gnip-stream.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "gnip-stream/version"
|
2
|
+
|
3
|
+
require 'gnip-stream/stream'
|
4
|
+
require 'gnip-stream/data_buffer'
|
5
|
+
require 'gnip-stream/json_stream'
|
6
|
+
require 'gnip-stream/xml_stream'
|
7
|
+
require 'gnip-stream/powertrack_client'
|
8
|
+
require 'gnip-stream/facebook_client'
|
9
|
+
require 'gnip-stream/error_reconnect'
|
10
|
+
|
11
|
+
module GnipStream
|
12
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gnip-stream/data_buffer'
|
3
|
+
|
4
|
+
describe GnipStream::DataBuffer do
|
5
|
+
subject { GnipStream::DataBuffer.new(/(test)(.*)/) }
|
6
|
+
describe "#initialize" do
|
7
|
+
it "accepts a regex pattern that will be used to match complete entries" do
|
8
|
+
pattern = Regexp.new(/hello/)
|
9
|
+
GnipStream::DataBuffer.new(pattern).pattern.should == pattern
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#process" do
|
14
|
+
it "appends the data to the buffer" do
|
15
|
+
subject.process("hello")
|
16
|
+
subject.instance_variable_get(:@buffer).should == "hello"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#complete_entries" do
|
21
|
+
it "returns a list of complete entries" do
|
22
|
+
subject.process("test")
|
23
|
+
subject.complete_entries.should == ["test"]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gnip-stream/error_reconnect'
|
3
|
+
|
4
|
+
require 'spec_helper'
|
5
|
+
|
6
|
+
describe GnipStream::ErrorReconnect do
|
7
|
+
let(:fake_stream) { double("fake stream that causes errors") }
|
8
|
+
subject { GnipStream::ErrorReconnect.new(fake_stream, :connect) }
|
9
|
+
before { subject.stub(:sleep) }
|
10
|
+
describe "#attempt_to_reconnect" do
|
11
|
+
it "should call the specified method on the class generating the error if reconnect count is less than 5" do
|
12
|
+
fake_stream.should_receive(:connect)
|
13
|
+
subject.attempt_to_reconnect("failed to reconnect")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should raise an error with the specified error_message if reconnect fails maximum number of times" do
|
17
|
+
subject.instance_variable_set(:@reconnect_attempts, 6)
|
18
|
+
lambda {subject.attempt_to_reconnect("failed to reconnect")}.should raise_error(/reconnect/)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gnip-stream/facebook_client'
|
3
|
+
|
4
|
+
describe GnipStream::FacebookClient do
|
5
|
+
let(:fake_stream) { double("GnipStream::XmlStream").as_null_object }
|
6
|
+
before { GnipStream::XmlStream.stub(:new => fake_stream) }
|
7
|
+
subject { GnipStream::FacebookClient.new("http://example.com", "user", "password") }
|
8
|
+
|
9
|
+
describe "#consume" do
|
10
|
+
it "setup the client callback" do
|
11
|
+
fake_stream.should_receive(:on_message)
|
12
|
+
subject.consume
|
13
|
+
end
|
14
|
+
|
15
|
+
it "connects to the stream" do
|
16
|
+
fake_stream.should_receive(:connect)
|
17
|
+
subject.consume
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "configure_handlers" do
|
22
|
+
it "sets up the appropriate error and close handlers" do
|
23
|
+
fake_stream.should_receive(:on_error).twice
|
24
|
+
fake_stream.should_receive(:on_connection_close).twice
|
25
|
+
subject.configure_handlers
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gnip-stream/json_stream'
|
3
|
+
|
4
|
+
describe GnipStream::JsonStream do
|
5
|
+
subject { GnipStream::JsonStream.new("http://example.com") }
|
6
|
+
|
7
|
+
describe "#initialize" do
|
8
|
+
it "creates underlying stream object with a json specific data buffer" do
|
9
|
+
GnipStream::Stream.should_receive(:new) do |url, processor, headers|
|
10
|
+
url.should == "http://example.com"
|
11
|
+
end
|
12
|
+
GnipStream::JsonStream.new("http://example.com")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#method_missing" do
|
17
|
+
let(:underlying_stream) { double("GnipStream::Stream") }
|
18
|
+
before do
|
19
|
+
GnipStream::Stream.stub(:new => underlying_stream)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "delegates all available methods to the underlying stream class" do
|
23
|
+
underlying_stream.should_receive(:connect)
|
24
|
+
subject.connect
|
25
|
+
end
|
26
|
+
|
27
|
+
it "raises a method not found error on self if underlying stream can not respond to the method" do
|
28
|
+
lambda { subject.foobar }.should raise_error(NoMethodError)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gnip-stream/powertrack_authentication'
|
3
|
+
|
4
|
+
describe GnipStream::PowertrackAuthentication do
|
5
|
+
subject { GnipStream::PowertrackAuthentication.new("http://example.com",
|
6
|
+
"user", "password") }
|
7
|
+
describe "#authenticate" do
|
8
|
+
let(:fake_request) { double("fake request") }
|
9
|
+
it "should make a request to the GNIP API to receive access cookie" do
|
10
|
+
EM::HttpRequest.should_receive(:new).with("http://example.com").and_return(fake_request)
|
11
|
+
fake_request.should_receive(:get) do |args|
|
12
|
+
args[:head].should == {'authorization' => ["user", "password"]}
|
13
|
+
EM.stop
|
14
|
+
double.as_null_object
|
15
|
+
end
|
16
|
+
|
17
|
+
subject.authenticate
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#parse_response_header" do
|
22
|
+
it "should set the stream url based on 'LOCATION' header" do
|
23
|
+
subject.parse_response_header({"SET_COOKIE" => ["session_token=foobar; domain=.gnip.com; path=/;
|
24
|
+
expires=Wed, 13-Jul-2011 22:10:10 GMT _base_session=hello; path=/; HttpOnly"]})
|
25
|
+
subject.cookies.should == "session_token=foobar; domain=.gnip.com; path=/"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should set the url that we can stream data from" do
|
29
|
+
subject.parse_response_header("LOCATION" => "http://example.com", "SET_COOKIE" => ["session_token=foobar; domain=.gnip.com; path=/;
|
30
|
+
expires=Wed, 13-Jul-2011 22:10:10 GMT _base_session=hello; path=/; HttpOnly"])
|
31
|
+
subject.location.should == "http://example.com"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gnip-stream/powertrack_client'
|
3
|
+
|
4
|
+
describe GnipStream::PowertrackClient do
|
5
|
+
let(:fake_stream) { double("GnipStream::JsonStream").as_null_object }
|
6
|
+
let(:fake_auth) { double("GnipStream::PowertrackAuthentication").as_null_object }
|
7
|
+
before do
|
8
|
+
GnipStream::JsonStream.stub(:new => fake_stream)
|
9
|
+
GnipStream::PowertrackAuthentication.stub(:new => fake_auth)
|
10
|
+
end
|
11
|
+
|
12
|
+
subject { GnipStream::PowertrackClient.new("http://example.com", "user", "password") }
|
13
|
+
|
14
|
+
describe "#initialize" do
|
15
|
+
it "initializes a PowertrackAuthentication instance" do
|
16
|
+
GnipStream::PowertrackAuthentication.should_receive(:new)
|
17
|
+
subject
|
18
|
+
end
|
19
|
+
|
20
|
+
it "initializes an instance JsonStream" do
|
21
|
+
GnipStream::JsonStream.should_receive(:new)
|
22
|
+
subject
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "configure_handlers" do
|
27
|
+
it "sets up the appropriate error and close handlers" do
|
28
|
+
fake_stream.should_receive(:on_error).twice
|
29
|
+
fake_stream.should_receive(:on_connection_close).twice
|
30
|
+
subject.configure_handlers
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#authenticate" do
|
35
|
+
it "performs the necessary authentication and passes appropriate credentials to stream" do
|
36
|
+
fake_auth.should_receive(:authenticate)
|
37
|
+
fake_auth.should_receive(:location).and_return("http://example.com")
|
38
|
+
fake_auth.should_receive(:cookies).and_return("some cookie")
|
39
|
+
|
40
|
+
fake_stream.should_receive(:url=).with("http://example.com")
|
41
|
+
fake_stream.should_receive(:headers=)
|
42
|
+
subject.authenticate
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#consume" do
|
47
|
+
it "setup the client callback" do
|
48
|
+
fake_stream.should_receive(:on_message)
|
49
|
+
subject.consume
|
50
|
+
end
|
51
|
+
|
52
|
+
it "connects to the stream" do
|
53
|
+
fake_stream.should_receive(:connect)
|
54
|
+
subject.consume
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'gnip-stream/stream'
|
4
|
+
|
5
|
+
describe GnipStream::Stream do
|
6
|
+
let(:fake_processor) { double("json processor", :process => self,
|
7
|
+
:complete_entries => ["hello"])}
|
8
|
+
subject { GnipStream::Stream.new("http://example.com", fake_processor) }
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "allows you to define custom headers" do
|
12
|
+
headers = {"keep-alive" => false}
|
13
|
+
stream = GnipStream::Stream.new("http://example.com", fake_processor, headers)
|
14
|
+
stream.headers.should == headers
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#on_message" do
|
19
|
+
let(:on_message_block) { proc{ puts "hello world" } }
|
20
|
+
it "accepts a block that will be called every time a message is received" do
|
21
|
+
subject.on_message(&on_message_block)
|
22
|
+
subject.instance_variable_get(:@on_message).should == on_message_block
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#on_connection_close" do
|
27
|
+
let(:on_connection_close_block) { proc{ puts "hello world" } }
|
28
|
+
it "accepts a block that will be called every time a message is received" do
|
29
|
+
subject.on_connection_close(&on_connection_close_block)
|
30
|
+
subject.instance_variable_get(:@on_connection_close).should == on_connection_close_block
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#on_error" do
|
35
|
+
let(:on_error_block) { proc{ puts "hello world" } }
|
36
|
+
it "accepts a block that will be called every time a message is received" do
|
37
|
+
subject.on_error(&on_error_block)
|
38
|
+
subject.instance_variable_get(:@on_error).should == on_error_block
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#process_chunk" do
|
43
|
+
let(:on_message_block) { proc{ |message| message.to_s } }
|
44
|
+
before do
|
45
|
+
subject.on_message(&on_message_block)
|
46
|
+
EM.stub(:defer)
|
47
|
+
end
|
48
|
+
it "passes the chunk of data off to the processor object for processing" do
|
49
|
+
fake_processor.should_receive(:process).with("hello world")
|
50
|
+
subject.process_chunk("hello world")
|
51
|
+
end
|
52
|
+
|
53
|
+
it "calls the client supplied callback on a seperate thread for each message" do
|
54
|
+
EventMachine.should_receive(:defer)
|
55
|
+
subject.process_chunk("hello")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gnip-stream/xml_stream'
|
3
|
+
|
4
|
+
describe GnipStream::XmlStream do
|
5
|
+
subject { GnipStream::XmlStream.new("http://example.com") }
|
6
|
+
describe "#initialize" do
|
7
|
+
it "creates underlying stream object with a json specific data buffer" do
|
8
|
+
GnipStream::Stream.should_receive(:new) do |url, processor, headers|
|
9
|
+
url.should == "http://example.com"
|
10
|
+
end
|
11
|
+
GnipStream::XmlStream.new("http://example.com")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#method_missing" do
|
16
|
+
let(:underlying_stream) { double("GnipStream::Stream") }
|
17
|
+
before do
|
18
|
+
GnipStream::Stream.stub(:new => underlying_stream)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "delegates all available methods to the underlying stream class" do
|
22
|
+
underlying_stream.should_receive(:connect)
|
23
|
+
subject.connect
|
24
|
+
end
|
25
|
+
|
26
|
+
it "raises a method not found error on self if underlying stream can not respond to the method" do
|
27
|
+
lambda { subject.foobar }.should raise_error(NoMethodError)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gnip-stream
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ryan Weald
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-10-21 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &70139514960160 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70139514960160
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: em-http-request
|
27
|
+
requirement: &70139514958620 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70139514958620
|
36
|
+
description: ''
|
37
|
+
email:
|
38
|
+
- ryan@weald.com
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- .pryrc
|
45
|
+
- .rvmrc
|
46
|
+
- .travis.yml
|
47
|
+
- Gemfile
|
48
|
+
- LICENSE
|
49
|
+
- README.md
|
50
|
+
- Rakefile
|
51
|
+
- gnip-stream.gemspec
|
52
|
+
- lib/gnip-stream.rb
|
53
|
+
- lib/gnip-stream/data_buffer.rb
|
54
|
+
- lib/gnip-stream/error_reconnect.rb
|
55
|
+
- lib/gnip-stream/facebook_client.rb
|
56
|
+
- lib/gnip-stream/json_stream.rb
|
57
|
+
- lib/gnip-stream/powertrack_authentication.rb
|
58
|
+
- lib/gnip-stream/powertrack_client.rb
|
59
|
+
- lib/gnip-stream/stream.rb
|
60
|
+
- lib/gnip-stream/stream_delegate.rb
|
61
|
+
- lib/gnip-stream/version.rb
|
62
|
+
- lib/gnip-stream/xml_stream.rb
|
63
|
+
- spec/gnip-stream/data_buffer_spec.rb
|
64
|
+
- spec/gnip-stream/error_reconnect_spec.rb
|
65
|
+
- spec/gnip-stream/facebook_client_spec.rb
|
66
|
+
- spec/gnip-stream/json_stream_spec.rb
|
67
|
+
- spec/gnip-stream/powertrack_authentication_spec.rb
|
68
|
+
- spec/gnip-stream/powertrack_client_spec.rb
|
69
|
+
- spec/gnip-stream/stream_spec.rb
|
70
|
+
- spec/gnip-stream/xml_stream_spec.rb
|
71
|
+
- spec/spec_helper.rb
|
72
|
+
homepage: https://github.com/rweald/gnip-stream
|
73
|
+
licenses: []
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project: gnip-stream
|
92
|
+
rubygems_version: 1.8.10
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: ''
|
96
|
+
test_files:
|
97
|
+
- spec/gnip-stream/data_buffer_spec.rb
|
98
|
+
- spec/gnip-stream/error_reconnect_spec.rb
|
99
|
+
- spec/gnip-stream/facebook_client_spec.rb
|
100
|
+
- spec/gnip-stream/json_stream_spec.rb
|
101
|
+
- spec/gnip-stream/powertrack_authentication_spec.rb
|
102
|
+
- spec/gnip-stream/powertrack_client_spec.rb
|
103
|
+
- spec/gnip-stream/stream_spec.rb
|
104
|
+
- spec/gnip-stream/xml_stream_spec.rb
|
105
|
+
- spec/spec_helper.rb
|