dpla-analysand 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/CHANGELOG +67 -0
- data/Gemfile +8 -0
- data/LICENSE +22 -0
- data/README +48 -0
- data/Rakefile +22 -0
- data/analysand.gemspec +33 -0
- data/bin/analysand +27 -0
- data/lib/analysand.rb +3 -0
- data/lib/analysand/bulk_response.rb +14 -0
- data/lib/analysand/change_watcher.rb +280 -0
- data/lib/analysand/config_response.rb +25 -0
- data/lib/analysand/connection_testing.rb +52 -0
- data/lib/analysand/database.rb +322 -0
- data/lib/analysand/errors.rb +60 -0
- data/lib/analysand/http.rb +90 -0
- data/lib/analysand/instance.rb +255 -0
- data/lib/analysand/reading.rb +26 -0
- data/lib/analysand/response.rb +35 -0
- data/lib/analysand/response_headers.rb +18 -0
- data/lib/analysand/session_response.rb +16 -0
- data/lib/analysand/status_code_predicates.rb +25 -0
- data/lib/analysand/streaming_view_response.rb +90 -0
- data/lib/analysand/version.rb +3 -0
- data/lib/analysand/view_response.rb +24 -0
- data/lib/analysand/view_streaming/builder.rb +142 -0
- data/lib/analysand/viewing.rb +95 -0
- data/lib/analysand/writing.rb +71 -0
- data/script/setup_database.rb +45 -0
- data/spec/analysand/a_response.rb +70 -0
- data/spec/analysand/change_watcher_spec.rb +102 -0
- data/spec/analysand/database_spec.rb +243 -0
- data/spec/analysand/database_writing_spec.rb +488 -0
- data/spec/analysand/instance_spec.rb +205 -0
- data/spec/analysand/response_spec.rb +26 -0
- data/spec/analysand/view_response_spec.rb +44 -0
- data/spec/analysand/view_streaming/builder_spec.rb +73 -0
- data/spec/analysand/view_streaming_spec.rb +122 -0
- data/spec/fixtures/vcr_cassettes/get_config.yml +40 -0
- data/spec/fixtures/vcr_cassettes/get_many_config.yml +40 -0
- data/spec/fixtures/vcr_cassettes/head_request_with_etag.yml +40 -0
- data/spec/fixtures/vcr_cassettes/reload_config.yml +114 -0
- data/spec/fixtures/vcr_cassettes/unauthorized_put_config.yml +43 -0
- data/spec/fixtures/vcr_cassettes/view.yml +40 -0
- data/spec/smoke/database_thread_spec.rb +59 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/support/database_access.rb +40 -0
- data/spec/support/example_isolation.rb +86 -0
- data/spec/support/test_parameters.rb +39 -0
- metadata +283 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 43f7060645db528706131e0bb8c6feaa5311cb45
|
4
|
+
data.tar.gz: a9d1a3d8e8434f3039d7b0f441a4053000b1bca4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 510cc920abf5f1fa85b82ed86e7d0f8fb4276761a424626122bfa79025c6795b4692481706a57208dde8b5916b0ff3afd4e151a7b496935dfbf84bd384688f29
|
7
|
+
data.tar.gz: 1b247083c79d19ec91aa958712f6e7e7d3d80d33546914b3a7776b62ede70745d71ddea5c5f2e1142f5cb3ffe8ade9e7f8e191df6f4e851b3e0d9c2cd02f3a7d
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CHANGELOG
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
Issue numbers refer to issues on Analysand's Github tracker:
|
2
|
+
https://github.com/yipdw/analysand/issues
|
3
|
+
|
4
|
+
3.0.2 (2014-12-01)
|
5
|
+
-----------------
|
6
|
+
|
7
|
+
* Change Celluloid dependency to ~> 0.16.0.
|
8
|
+
|
9
|
+
3.0.1 (2014-01-14)
|
10
|
+
------------------
|
11
|
+
|
12
|
+
* Change Celluloid dependency to ~> 0.15.0.
|
13
|
+
|
14
|
+
3.0.0 (2013-07-08)
|
15
|
+
------------------
|
16
|
+
|
17
|
+
* Change Celluloid dependency to 0.14.
|
18
|
+
|
19
|
+
3.0.0.pre2 (2013-04-15)
|
20
|
+
-----------------------
|
21
|
+
|
22
|
+
* Change Celluloid dependency to 0.13.
|
23
|
+
Please note: Analysand does not require celluloid/autostart. It's up to you
|
24
|
+
to decide whether or not you need that for your application.
|
25
|
+
|
26
|
+
3.0.0.pre (2013-02-26)
|
27
|
+
----------------------
|
28
|
+
|
29
|
+
* Instance#set_config renamed to Instance#put_config
|
30
|
+
* Instance#put_admin, Instance#delete_admin for db admin setup
|
31
|
+
* JSON encoding/decoding removed from Instance#*_config methods: all values are
|
32
|
+
sent to/received from CouchDB verbatim. This means that you'll have to quote all values,
|
33
|
+
e.g.
|
34
|
+
|
35
|
+
instance.set_config("stats/rate", 1200)
|
36
|
+
|
37
|
+
becomes
|
38
|
+
|
39
|
+
instance.put_config("stats/rate", '"1200"')
|
40
|
+
|
41
|
+
|
42
|
+
x.y.z (2012-12-31)
|
43
|
+
------------------
|
44
|
+
|
45
|
+
* Analysand::Writing#bulk_docs! now raises BulkOperationFailed on 401 responses
|
46
|
+
|
47
|
+
2.0.0 (2012-11-29)
|
48
|
+
------------------
|
49
|
+
|
50
|
+
* Instance#establish_session and Instance#renew_session now return a (session,
|
51
|
+
Analysand::Response pair)
|
52
|
+
* Share HTTP code between Database and Instance
|
53
|
+
* Session handling on Instance rewritten: #post_session, #get_session
|
54
|
+
* New response methods: #cookies, #session_cookie
|
55
|
+
|
56
|
+
1.1.0 (2012-11-03)
|
57
|
+
------------------
|
58
|
+
|
59
|
+
* View streaming (#3)
|
60
|
+
* ChangeWatchers now pass credentials when checking CouchDB status (#4)
|
61
|
+
* Some code organization cleanups
|
62
|
+
* require "analysand" now loads the Database and Instance classes
|
63
|
+
|
64
|
+
1.0.1 (2012-10-01)
|
65
|
+
------------------
|
66
|
+
|
67
|
+
* Initial release
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 David Yip
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
1. Analysand
|
2
|
+
|
3
|
+
Analysand is a CouchDB client library of dubious worth. It was extracted from
|
4
|
+
the a-m-v.org catalog application:
|
5
|
+
https://code.ninjawedding.org/git/amvorg-underground/catalog.git.
|
6
|
+
|
7
|
+
Analysand was written for Ruby 1.9. It is known to work on Ruby 1.9.3-p194 and
|
8
|
+
Rubinius 2.0.0.
|
9
|
+
|
10
|
+
2. Features
|
11
|
+
|
12
|
+
* GET, PUT, DELETE on databases
|
13
|
+
* GET, PUT, DELETE, HEAD, COPY on documents
|
14
|
+
* GET, PUT on document attachments
|
15
|
+
* GET, POST on views
|
16
|
+
* GET, PUT on server configuration
|
17
|
+
* GET, PUT, POST on arbitrary service handlers
|
18
|
+
* POST /_session
|
19
|
+
* POST /_bulk_docs
|
20
|
+
* View streaming
|
21
|
+
* Celluloid::IO-based change feed watchers
|
22
|
+
* Cookie and HTTP Basic authentication for all of the above
|
23
|
+
* Database objects can be safely shared across threads
|
24
|
+
|
25
|
+
3. Development
|
26
|
+
|
27
|
+
You'll need a CouchDB >= 1.1.0 instance. I recommend not using a CouchDB
|
28
|
+
instance that you're using for anything else; Analysand requires the presence
|
29
|
+
of specific admin and non-admin users for its test suite.
|
30
|
+
|
31
|
+
See spec/support/test_parameters.rb for usernames, passwords, and connection
|
32
|
+
information.
|
33
|
+
|
34
|
+
Naturally, we hang with all the cool kids:
|
35
|
+
|
36
|
+
* Travis CI: https://travis-ci.org/#!/yipdw/analysand
|
37
|
+
* Code Climate: https://codeclimate.com/github/yipdw/analysand
|
38
|
+
* Gemnasium: https://gemnasium.com/yipdw/analysand
|
39
|
+
|
40
|
+
4. License
|
41
|
+
|
42
|
+
Copyright 2012 David Yip; made available under the MIT license.
|
43
|
+
|
44
|
+
5. Special thanks
|
45
|
+
|
46
|
+
Fear of Tigers, 3LAU, Ellie Goulding, TeddyLoid, Susumu Hirasawa.
|
47
|
+
|
48
|
+
# vim:ts=2:sw=2:et:tw=78
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new
|
7
|
+
|
8
|
+
namespace :git do
|
9
|
+
desc 'Strip trailing whitespace from tracked source files'
|
10
|
+
task :strip_spaces do
|
11
|
+
`git ls-files`.split("\n").each do |file|
|
12
|
+
puts file
|
13
|
+
|
14
|
+
if `file '#{file}'` =~ /text/
|
15
|
+
sh "git stripspace < '#{file}' > '#{file}.out'"
|
16
|
+
mv "#{file}.out", file
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
task :default => :spec
|
data/analysand.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/analysand/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["David Yip"]
|
6
|
+
gem.email = ["yipdw@member.fsf.org"]
|
7
|
+
gem.description = %q{A terrible burden for a couch}
|
8
|
+
gem.summary = %q{A CouchDB client of dubious worth}
|
9
|
+
gem.homepage = "https://github.com/yipdw/analysand"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "dpla-analysand"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Analysand::VERSION
|
17
|
+
|
18
|
+
gem.required_ruby_version = '>= 1.9'
|
19
|
+
|
20
|
+
gem.add_dependency 'celluloid', '~> 0.16.0'
|
21
|
+
gem.add_dependency 'celluloid-io'
|
22
|
+
gem.add_dependency 'http_parser.rb'
|
23
|
+
gem.add_dependency 'json'
|
24
|
+
gem.add_dependency 'json-stream'
|
25
|
+
gem.add_dependency 'net-http-persistent'
|
26
|
+
gem.add_dependency 'rack'
|
27
|
+
gem.add_dependency 'yajl-ruby'
|
28
|
+
|
29
|
+
gem.add_development_dependency 'rake'
|
30
|
+
gem.add_development_dependency 'rspec'
|
31
|
+
gem.add_development_dependency 'vcr'
|
32
|
+
gem.add_development_dependency 'webmock'
|
33
|
+
end
|
data/bin/analysand
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
4
|
+
|
5
|
+
require 'analysand'
|
6
|
+
require 'irb'
|
7
|
+
require 'uri'
|
8
|
+
|
9
|
+
$URI = URI('http://localhost:5984/analysand_test')
|
10
|
+
|
11
|
+
def make_db(uri = $URI)
|
12
|
+
Analysand::Database.new(uri)
|
13
|
+
end
|
14
|
+
|
15
|
+
puts <<-END
|
16
|
+
------------------------------------------------------------------------------
|
17
|
+
Type make_db to make an Analysand::Database object. The default URI is
|
18
|
+
|
19
|
+
#{$URI}
|
20
|
+
|
21
|
+
To point at different databases, supply a URI object to make_db, e.g.
|
22
|
+
|
23
|
+
make_db(URI('https://couchdb.example.org:6984/supersekrit'))
|
24
|
+
------------------------------------------------------------------------------
|
25
|
+
END
|
26
|
+
|
27
|
+
IRB.start
|
data/lib/analysand.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'analysand/response'
|
2
|
+
|
3
|
+
module Analysand
|
4
|
+
##
|
5
|
+
# A subclass of Response that adjusts success? to check for individual error
|
6
|
+
# records.
|
7
|
+
class BulkResponse < Response
|
8
|
+
def success?
|
9
|
+
super && body.none? { |r| r.has_key?('error') }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# vim:ts=2:sw=2:et:tw=78
|
@@ -0,0 +1,280 @@
|
|
1
|
+
require 'celluloid'
|
2
|
+
require 'celluloid/io'
|
3
|
+
require 'analysand/connection_testing'
|
4
|
+
require 'http/parser'
|
5
|
+
require 'net/http'
|
6
|
+
require 'rack/utils'
|
7
|
+
require 'uri'
|
8
|
+
require 'yajl'
|
9
|
+
|
10
|
+
module Analysand
|
11
|
+
##
|
12
|
+
# A Celluloid::IO actor that watches the changes feed of a CouchDB database.
|
13
|
+
# When a change is received, it passes the change to a #process method.
|
14
|
+
#
|
15
|
+
# ChangeWatchers monitor changes using continuous mode and set up a heartbeat
|
16
|
+
# to fire approximately every 10 seconds.
|
17
|
+
#
|
18
|
+
# ChangeWatchers begin watching for changes as soon as they are initialized.
|
19
|
+
# To send a shutdown message:
|
20
|
+
#
|
21
|
+
# a.stop
|
22
|
+
#
|
23
|
+
# The watcher will terminate on the next heartbeat.
|
24
|
+
#
|
25
|
+
#
|
26
|
+
# Failure modes
|
27
|
+
# =============
|
28
|
+
#
|
29
|
+
# ChangeWatcher deals with the following failures in the following ways:
|
30
|
+
#
|
31
|
+
# * If Errno::ECONNREFUSED is raised whilst connecting to CouchDB, it will
|
32
|
+
# retry the connection in 30 seconds.
|
33
|
+
# * If the connection to CouchDB's changes feed is abruptly terminated, it
|
34
|
+
# dies.
|
35
|
+
# * If an exception is raised during HTTP or JSON parsing, it dies.
|
36
|
+
#
|
37
|
+
# Situations where the actor dies should be handled by a supervisor.
|
38
|
+
#
|
39
|
+
#
|
40
|
+
# Example usage
|
41
|
+
# =============
|
42
|
+
#
|
43
|
+
# class Accumulator < Analysand::ChangeWatcher
|
44
|
+
# attr_accessor :results
|
45
|
+
#
|
46
|
+
# def initialize(database)
|
47
|
+
# super(database)
|
48
|
+
#
|
49
|
+
# self.results = []
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# def process(change)
|
53
|
+
# results << change
|
54
|
+
#
|
55
|
+
# # Once a ChangeWatcher has successfully processed a change, it
|
56
|
+
# # SHOULD invoke #change_processed.
|
57
|
+
# change_processed(change)
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# a = Accumulator.new('http://localhost:5984/mydb')
|
62
|
+
#
|
63
|
+
# # or with supervision:
|
64
|
+
# a = Accumulator.supervise('http://localhost:5984/mydb')
|
65
|
+
class ChangeWatcher
|
66
|
+
include Celluloid::IO
|
67
|
+
include Celluloid::Logger
|
68
|
+
include ConnectionTesting
|
69
|
+
include Rack::Utils
|
70
|
+
|
71
|
+
# Read at most this many bytes off the socket at a time.
|
72
|
+
QUANTUM = 4096
|
73
|
+
|
74
|
+
##
|
75
|
+
# Checks services. If all services pass muster, enters a read loop.
|
76
|
+
#
|
77
|
+
# The database parameter may be either a URL-as-string or a
|
78
|
+
# Analysand::Database.
|
79
|
+
#
|
80
|
+
# If overriding the initializer, you MUST call super.
|
81
|
+
def initialize(database)
|
82
|
+
@db = database
|
83
|
+
@waiting = {}
|
84
|
+
@http_parser = ::Http::Parser.new(self)
|
85
|
+
@json_parser = Yajl::Parser.new
|
86
|
+
@json_parser.on_parse_complete = lambda { |doc| process(doc) }
|
87
|
+
|
88
|
+
async.start
|
89
|
+
end
|
90
|
+
|
91
|
+
# The URI of the changes feed. This URI incorporates any changes
|
92
|
+
# made by customize_query.
|
93
|
+
def changes_feed_uri
|
94
|
+
query = {
|
95
|
+
'feed' => 'continuous',
|
96
|
+
'heartbeat' => '10000'
|
97
|
+
}
|
98
|
+
|
99
|
+
customize_query(query)
|
100
|
+
|
101
|
+
uri = (@db.respond_to?(:uri) ? @db.uri : URI(@db)).dup
|
102
|
+
uri.path += '/_changes'
|
103
|
+
uri.query = build_query(query)
|
104
|
+
uri
|
105
|
+
end
|
106
|
+
|
107
|
+
# The connection_ok method is called before connecting to the changes feed.
|
108
|
+
# By default, it checks that there's an HTTP service listening on the
|
109
|
+
# changes feed.
|
110
|
+
#
|
111
|
+
# If the method returns true, then we connect to the changes feed and begin
|
112
|
+
# processing. If it returns false, a warning message is logged and the
|
113
|
+
# connection check will be retried in 30 seconds.
|
114
|
+
#
|
115
|
+
# This method can be overridden if you need to check additional services.
|
116
|
+
# When you override the method, make sure that you don't discard the return
|
117
|
+
# value of the original definition:
|
118
|
+
#
|
119
|
+
# # Wrong
|
120
|
+
# def connection_ok
|
121
|
+
# super
|
122
|
+
# ...
|
123
|
+
# end
|
124
|
+
#
|
125
|
+
# # Right
|
126
|
+
# def connection_ok
|
127
|
+
# ok = super
|
128
|
+
#
|
129
|
+
# ok && my_other_test
|
130
|
+
# end
|
131
|
+
def connection_ok
|
132
|
+
test_http_connection(changes_feed_uri) do |req|
|
133
|
+
customize_request(req)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def start
|
138
|
+
return if @started
|
139
|
+
|
140
|
+
@started = true
|
141
|
+
|
142
|
+
while !connection_ok
|
143
|
+
error "Some services used by #{self.class.name} did not check out ok; will retry in 30 seconds"
|
144
|
+
sleep 30
|
145
|
+
end
|
146
|
+
|
147
|
+
connect
|
148
|
+
|
149
|
+
info "#{self.class} entering read loop"
|
150
|
+
|
151
|
+
@running = true
|
152
|
+
|
153
|
+
while @running
|
154
|
+
@http_parser << @socket.readpartial(QUANTUM)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Once we're done, close things up.
|
158
|
+
@started = false
|
159
|
+
@socket.close
|
160
|
+
end
|
161
|
+
|
162
|
+
def stop
|
163
|
+
@running = false
|
164
|
+
end
|
165
|
+
|
166
|
+
##
|
167
|
+
# Can be used to set query parameters. query is a Hash. The query hash
|
168
|
+
# has two default parameters:
|
169
|
+
#
|
170
|
+
# | Key | Value |
|
171
|
+
# | feed | continuous |
|
172
|
+
# | heartbeat | 10000 |
|
173
|
+
#
|
174
|
+
# It is NOT RECOMMENDED that they be changed.
|
175
|
+
#
|
176
|
+
# By default, this does nothing. Provide behavior in a subclass.
|
177
|
+
def customize_query(query)
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# Can be used to add headers. req is a Net::HTTP::Get instance.
|
182
|
+
#
|
183
|
+
# By default, this does nothing. Provide behavior in a subclass.
|
184
|
+
def customize_request(req)
|
185
|
+
end
|
186
|
+
|
187
|
+
##
|
188
|
+
# This method should implement your change-processing logic.
|
189
|
+
#
|
190
|
+
# change is a Hash containing keys id, seq, and changes. See [0] for
|
191
|
+
# more information.
|
192
|
+
#
|
193
|
+
# By default, this does nothing. Provide behavior in a subclass.
|
194
|
+
#
|
195
|
+
# [0]: http://guide.couchdb.org/draft/notifications.html#continuous
|
196
|
+
def process(change)
|
197
|
+
end
|
198
|
+
|
199
|
+
class Waiter < Celluloid::Future
|
200
|
+
alias_method :wait, :value
|
201
|
+
end
|
202
|
+
|
203
|
+
##
|
204
|
+
# Returns an object that can be used to block a thread until a document
|
205
|
+
# with the given ID has been processed.
|
206
|
+
#
|
207
|
+
# Intended for testing.
|
208
|
+
def waiter_for(id)
|
209
|
+
@waiting[id] = true
|
210
|
+
|
211
|
+
Waiter.new do
|
212
|
+
loop do
|
213
|
+
break true if !@waiting[id]
|
214
|
+
sleep 0.1
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
##
|
220
|
+
# Notify waiters.
|
221
|
+
def change_processed(change)
|
222
|
+
@waiting.delete(change['id'])
|
223
|
+
end
|
224
|
+
|
225
|
+
##
|
226
|
+
# Http::Parser callback.
|
227
|
+
#
|
228
|
+
# @private
|
229
|
+
def on_headers_complete(parser)
|
230
|
+
status = @http_parser.status_code.to_i
|
231
|
+
|
232
|
+
raise "Request failed: expected status 200, got #{status}" unless status == 200
|
233
|
+
end
|
234
|
+
|
235
|
+
##
|
236
|
+
# Http::Parser callback.
|
237
|
+
#
|
238
|
+
# @private
|
239
|
+
def on_body(chunk)
|
240
|
+
@json_parser << chunk
|
241
|
+
end
|
242
|
+
|
243
|
+
##
|
244
|
+
# @private
|
245
|
+
def connect
|
246
|
+
req = prepare_request
|
247
|
+
uri = changes_feed_uri
|
248
|
+
|
249
|
+
info "#{self.class} connecting to #{req.path}"
|
250
|
+
|
251
|
+
@socket = TCPSocket.new(uri.host, uri.port)
|
252
|
+
|
253
|
+
# Make the request.
|
254
|
+
data = [
|
255
|
+
"GET #{req.path} HTTP/1.1"
|
256
|
+
]
|
257
|
+
|
258
|
+
req.each_header { |k, v| data << "#{k}: #{v}" }
|
259
|
+
|
260
|
+
@socket.write(data.join("\r\n"))
|
261
|
+
@socket.write("\r\n\r\n")
|
262
|
+
end
|
263
|
+
|
264
|
+
##
|
265
|
+
# @private
|
266
|
+
def disconnect
|
267
|
+
@socket.close if @socket && !@socket.closed?
|
268
|
+
end
|
269
|
+
|
270
|
+
finalizer :disconnect
|
271
|
+
|
272
|
+
##
|
273
|
+
# @private
|
274
|
+
def prepare_request
|
275
|
+
Net::HTTP::Get.new(changes_feed_uri.to_s).tap do |req|
|
276
|
+
customize_request(req)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|