em-stretcher 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: baa41f4d1deadbbb5bac9415dc9f6800fa89cff7
4
+ data.tar.gz: 79dd2a858e7cbcc507d45f50b20632656ed0635f
5
+ SHA512:
6
+ metadata.gz: e6e01ba6d3c896b6ccaadf3c519983bac59946c8ee3e3b572ec0557b9c6f9d40d9d5475737e6dd59f14aa6bca8720883f4476604b6967cd961602a957877e94b
7
+ data.tar.gz: 4b626de495880b06323803c8e6404e1244765415b0268d18459a3c6d0f301ed2ca1d58d7d765975ce0e5a1c137e1a5a6b435fff15a442a501ed292835f49a9dc
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ test.rb
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --pattern "**/spec/**/*_spec.rb" --default-path .
2
+ --color
3
+ --format documentation
@@ -0,0 +1 @@
1
+ ruby-2.0.0-p353
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in em-stretcher.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Benjamin Coe
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.
@@ -0,0 +1,151 @@
1
+ Em::Stretcher
2
+ =============
3
+
4
+ An EventMachine port of [Stretcher](https://github.com/PoseBiz/stretcher) (a Fast, Elegant, ElasticSearch client.)
5
+
6
+ Indexes
7
+ -------
8
+
9
+ **Creating an Index**
10
+
11
+ ```ruby
12
+ require 'eventmachine'
13
+ require "em-stretcher"
14
+
15
+ EM.run do
16
+ server = EM::Stretcher::Server.new
17
+
18
+ server.index('my-index').create
19
+ .callback do |result|
20
+ p result
21
+ end
22
+ .errback do |err|
23
+ p err
24
+ end
25
+ end
26
+ ```
27
+
28
+ **Deleting an Index**
29
+
30
+ ```ruby
31
+ server.index('my-index').delete
32
+ .callback do |result|
33
+ p result
34
+ end
35
+ .errback do |err|
36
+ p err
37
+ end
38
+ ```
39
+
40
+ Mappings
41
+ --------
42
+
43
+ **Creating a Mapping**
44
+
45
+ ```ruby
46
+ mapping = {
47
+ :article => {
48
+ properties: {
49
+ title: { :type => :string }
50
+ }
51
+ }
52
+ }
53
+
54
+ server.index('my-index')
55
+ .type('article')
56
+ .put_mapping(mapping)
57
+ .callback do |result|
58
+ p result
59
+ end
60
+ .errback do |err|
61
+ p err
62
+ end
63
+ ```
64
+
65
+ Indexing Documents
66
+ ------------------
67
+
68
+ ```ruby
69
+ id = 33
70
+
71
+ server.index('my-index')
72
+ .type(mapping_name)
73
+ .put(id, { title: "My Document with the id #{id}" })
74
+ .callback do |response|
75
+ p response
76
+ end
77
+ .errback do |err|
78
+ p err
79
+ end
80
+ ```
81
+
82
+ Searching for Documents
83
+ -----------------------
84
+
85
+ ```ruby
86
+ server.index('my-index').type('articles')
87
+ .search(size: 50, query: { "query_string" => { "query" => "*" } })
88
+ .documents
89
+ .callback do |r|
90
+ p r
91
+ end
92
+ ```
93
+
94
+ When One Thing Leads to Another
95
+ -------------------------------
96
+
97
+ EM::Stretcher uses [Deferrable Gratification](https://github.com/samstokes/deferrable_gratification) for chaining together dependent requests.
98
+
99
+ Here's a great example of when this comes into play:
100
+
101
+ * You index several hundred documents in parallel.
102
+ * You want to perform a search on the index, with all the documents present.
103
+
104
+ Here's how you can pull this off with Deferrable Gratification:
105
+
106
+ ```ruby
107
+ # Index some documents in parallel.
108
+ (0..50).each do |i|
109
+ server.index('my-index')
110
+ .type('articles')
111
+ .put(i, { title: "title #{i}" })
112
+ .callback do |response|
113
+ p response
114
+ end
115
+ end
116
+
117
+ # First we wait for the indexing to finish.
118
+ server.index('my-index').refresh
119
+ .bind! do
120
+
121
+ # Then we perform the search.
122
+ server.index('my-index').type('articles')
123
+ .search(size: 50, query: { "query_string" => { "query" => "*" } })
124
+ .documents
125
+ .callback do |r|
126
+ p r # all 50 results should have been returned.
127
+ end
128
+ end
129
+ ```
130
+
131
+ ## Installation
132
+
133
+ Add this line to your application's Gemfile:
134
+
135
+ gem 'em-stretcher'
136
+
137
+ And then execute:
138
+
139
+ $ bundle
140
+
141
+ Or install it yourself as:
142
+
143
+ $ gem install em-stretcher
144
+
145
+ ## Contributing
146
+
147
+ 1. Fork it ( http://github.com/bcoe/em-stretcher/fork )
148
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
149
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
150
+ 4. Push to the branch (`git push origin my-new-feature`)
151
+ 5. Create new Pull Request
@@ -0,0 +1,4 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'em/stretcher/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "em-stretcher"
8
+ spec.version = EventMachine::Stretcher::VERSION
9
+ spec.authors = ["Benjamin Coe"]
10
+ spec.email = ["ben@yesware.com"]
11
+ spec.summary = %q{EventMachine for Stretcher a Fast, Elegant, ElasticSearch client}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "stretcher"
21
+ spec.add_dependency "deferrable_gratification"
22
+ spec.add_dependency "eventmachine"
23
+ spec.add_dependency "em-http-request"
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.5"
26
+ spec.add_development_dependency "rspec"
27
+ spec.add_development_dependency "rspec-eventmachine"
28
+ spec.add_development_dependency "rake"
29
+ end
@@ -0,0 +1,19 @@
1
+ require "ostruct"
2
+ require "stretcher"
3
+ require "eventmachine"
4
+ require "deferrable_gratification"
5
+ require "em-http-request"
6
+ require "em/stretcher/server"
7
+ require "em/stretcher/version"
8
+ require "em/stretcher/search_results"
9
+ require "em/stretcher/index_type"
10
+
11
+ module EventMachine
12
+ module Stretcher
13
+ # Your code goes here...
14
+ end
15
+ end
16
+
17
+ # Enchance deferrables with bind functionality.
18
+ DG.enhance_all_deferrables!
19
+ DG.enhance! EventMachine::HttpClient
@@ -0,0 +1,22 @@
1
+ # Patch get to play nicely with EM.
2
+ module Stretcher
3
+ # Represents an index scoped to a specific type.
4
+ # Generally should be instantiated via Index#type(name).
5
+ class IndexType
6
+ # Retrieves the document by ID.
7
+ # Normally this returns the contents of _source, however, if the 'raw' flag is passed in, it will return the full response hash.
8
+ # Returns nil if the document does not exist.
9
+ #
10
+ # The :fields argument can either be a csv String or an Array. e.g. [:field1,'field2] or "field1,field2".
11
+ # If the fields parameter is passed in those fields are returned instead of _source.
12
+ #
13
+ # If, you include _source as a field, along with other fields you MUST set the raw flag to true to
14
+ # receive both fields and _source. Otherwise, only _source will be returned
15
+ def get(id, options={})
16
+ request(:get, id, options)
17
+ .bind! do |res|
18
+ res._source || res.fields
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,32 @@
1
+ # Patch search results to play nice with deferrables.
2
+ module Stretcher
3
+ # Conveniently represents elastic search results in a more compact fashion
4
+ #
5
+ # Available properties:
6
+ #
7
+ # * raw : The raw response from elastic search
8
+ # * total : The total number of matched docs
9
+ # * facets : the facets hash
10
+ # * results : The hit results with _id merged in to _source
11
+ class SearchResults
12
+ # Returns a 'prettier' version of elasticsearch results
13
+ # Also aliased as +docs+
14
+ # This will:
15
+ #
16
+ # 1. Return either '_source' or 'fields' as the base of the result
17
+ # 2. Merge any keys beginning with a '_' into it as well (such as '_score')
18
+ # 3. Copy the 'highlight' field into '_highlight'
19
+ #
20
+ def documents
21
+ raw_plain.bind! do |result|
22
+ result.hits.hits.map do |hit|
23
+ doc = extract_source(hit)
24
+ copy_underscores(hit, doc)
25
+ copy_highlight(hit, doc)
26
+ doc
27
+ end
28
+ end
29
+ end
30
+ alias_method :docs, :documents
31
+ end
32
+ end
@@ -0,0 +1,85 @@
1
+ # Patch the stretcher server to use
2
+ # deferrables rather than Faraday.
3
+ module EventMachine::Stretcher
4
+ class Server < Stretcher::Server
5
+ # Handy way to query the server, returning *only* the body
6
+ # Will fail with an exception when the status is not in the 2xx range.
7
+ #
8
+ # @param method [Symbol] HTTP method to execute.
9
+ # @param path [String] full ES API URL to hit (http://127.0.0.1:9200/_status).
10
+ # @param body [Hash] Hash ElasticSearch query body.
11
+ # @param headers [Hash] additional headers.
12
+ # @param options [Options]
13
+ # @param options.mashify [Boolean] should the response be turned into a Hashie::Mash?
14
+ # @return [Deferrable] deferrable that yields ElasticSearch response.
15
+ def request(method, path, params={}, body=nil, headers={}, options={})
16
+ options = { :mashify => true }.merge(options)
17
+
18
+ # Rather than setting up the default headers using the
19
+ # Faraday middlewear, we set them here.
20
+ http_params = {
21
+ headers: headers.merge({
22
+ :accept => 'application/json',
23
+ :user_agent => "Stretcher Ruby Gem #{Stretcher::VERSION}",
24
+ "Content-Type" => "application/json"
25
+ })
26
+ }
27
+
28
+ deferrable = EventMachine::DefaultDeferrable.new
29
+
30
+ # Allow the body to be set via a block
31
+ # es_component.rb in the stretcher library.
32
+ body_struct = OpenStruct.new
33
+ yield(body_struct) if block_given?
34
+ body ||= body_struct.body
35
+
36
+ # Update params with GET and POST parameters.
37
+ http_params[:query] = Stretcher::Util.clean_params(params) if params
38
+ http_params[:body] = JSON.dump(body) if body
39
+
40
+ # Execute :get, :post, :put, or :delete, returns a deferrable.
41
+ http = EventMachine::HttpRequest.new(path).send(method, http_params)
42
+
43
+ # We return our own deferrable, so that we can parse results.
44
+ http.callback do
45
+ check_response(http, deferrable, options)
46
+ end
47
+
48
+ http.errback do |err|
49
+ deferrable.fail(err)
50
+ end
51
+
52
+ deferrable
53
+ end
54
+
55
+ private
56
+
57
+ # Internal use only
58
+ # Check response codes from request
59
+ def check_response(res, deferrable, options)
60
+ status = res.response_header.status
61
+
62
+ if status >= 200 && status <= 299
63
+ if(options[:mashify])
64
+ begin
65
+ parsed_response = JSON.parse(res.response)
66
+ deferrable.succeed(Hashie::Mash.new(parsed_response))
67
+ rescue
68
+ deferrable.succeed(res.response)
69
+ end
70
+ else
71
+ deferrable.succeed(res.response)
72
+ end
73
+ elsif [404, 410].include? status
74
+ err_str = "Error processing request: (#{status})! #{res.req.method} URL: #{res.req.uri}"
75
+ err_str << "\n Resp Body: #{res.response}"
76
+ deferrable.fail(Stretcher::RequestError::NotFound.new(err_str))
77
+ else
78
+ err_str = "Error processing request (#{status})! #{res.req.method} URL: #{res.req.uri}"
79
+ err_str << "\n Resp Body: #{res.response}"
80
+ deferrable.fail(Stretcher::RequestError.new(err_str))
81
+ end
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,5 @@
1
+ module EventMachine
2
+ module Stretcher
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,111 @@
1
+ require "spec_helper"
2
+
3
+ describe EventMachine::Stretcher::Server do
4
+
5
+ include DeferrableModule
6
+
7
+ before(:all) { reset_index }
8
+ before(:each) { execute(type, :put_mapping, mapping) }
9
+
10
+ let(:server) { EventMachine::Stretcher::Server.new }
11
+ let(:index) { server.index(TESTING_INDEX_NAME) }
12
+ let(:type) { index.type(mapping_name) }
13
+ let(:mapping_name) { :article }
14
+ let(:mapping) do
15
+ {
16
+ mapping_name => {
17
+ properties: {
18
+ title: { :type => :string }
19
+ }
20
+ }
21
+ }
22
+ end
23
+ let(:document) do
24
+ {title: 'hello world!' }
25
+ end
26
+
27
+ describe "index" do
28
+ it "can delete an index" do
29
+ execute(index, :delete)
30
+ execute(index, :status)
31
+ error_response_should_contain 'IndexMissingException'
32
+ end
33
+
34
+ it "can create an index" do
35
+ execute(index, :delete)
36
+ execute(index, :create, {
37
+ :settings => {
38
+ :number_of_shards => 3,
39
+ :number_of_replicas => 0
40
+ }
41
+ })
42
+ execute(index, :status)
43
+ success_key_should_have_value([:_shards, :total], 3)
44
+ end
45
+ end
46
+
47
+ context "creating mappings" do
48
+ it "can create a mapping" do
49
+ type = index.type(mapping_name)
50
+ execute(type, :put_mapping, mapping)
51
+ execute(index, :get_mapping)
52
+
53
+ success_key_should_have_value([
54
+ TESTING_INDEX_NAME.to_sym,
55
+ mapping_name
56
+ ], { "properties" => { "title" => { "type"=>"string" } } })
57
+ end
58
+ end
59
+
60
+ context "documents" do
61
+ it "can index a document" do
62
+ execute(type, :put, 1, document)
63
+ execute(index, :refresh)
64
+ execute(type, :search)
65
+ success_result_count_should_equal(1)
66
+ end
67
+
68
+ it "can fetch a document by its id" do
69
+ execute(type, :put, 1, document)
70
+ execute(index, :refresh)
71
+ execute(type, :get, 1)
72
+
73
+ success_key_should_have_value(:title, 'hello world!')
74
+ end
75
+
76
+ it "should return a 404 if document is not found" do
77
+ execute(type, :get, 2)
78
+
79
+ error_response_should_contain '404'
80
+ end
81
+
82
+ it "can delete a document" do
83
+ execute(type, :put, 1, document)
84
+ execute(index, :refresh)
85
+ execute(type, :delete, 1, document)
86
+ execute(index, :refresh)
87
+
88
+ execute(type, :search)
89
+ success_result_count_should_equal(0)
90
+ end
91
+ end
92
+
93
+ describe "search" do
94
+ it "returns a document if query matches title" do
95
+ execute(type, :put, 1, document)
96
+ execute(index, :refresh)
97
+ execute(type, :search, query: { "query_string" => { "query" => "hello world" } })
98
+
99
+ success_result_count_should_equal(1)
100
+ end
101
+
102
+ it "does not return a document if query does not match title" do
103
+ execute(type, :put, 1, document)
104
+ execute(index, :refresh)
105
+ execute(type, :search, query: { "query_string" => { "query" => "zebra" } })
106
+
107
+ success_result_count_should_equal(0)
108
+ end
109
+ end
110
+
111
+ end
@@ -0,0 +1,97 @@
1
+ require "rspec"
2
+ require "rspec/em"
3
+
4
+ require_relative '../lib/em-stretcher'
5
+
6
+ TESTING_INDEX_NAME = 'em::stretcher:testing'
7
+
8
+ # Helper to reset ElasticSearch index for tests.
9
+ def reset_index
10
+ server = Stretcher::Server.new
11
+ i = server.index(TESTING_INDEX_NAME)
12
+ begin
13
+ i.delete
14
+ rescue Stretcher::RequestError::NotFound
15
+ end
16
+ server.refresh
17
+ i.create({
18
+ :settings => {
19
+ :number_of_shards => 1,
20
+ :number_of_replicas => 0
21
+ }
22
+ })
23
+ # Why do both? Doesn't hurt, and it fixes some races
24
+ server.refresh
25
+ i.refresh
26
+
27
+ attempts_left = 40
28
+
29
+ # Sometimes the index isn't instantly available
30
+ loop do
31
+ idx_metadata = server.cluster.request(:get, :state)[:metadata][:indices][i.name]
32
+ i_state = idx_metadata[:state]
33
+
34
+ break if i_state == 'open'
35
+
36
+ if attempts_left < 1
37
+ raise "Bad index state! #{i_state}. Metadata: #{idx_metadata}"
38
+ end
39
+
40
+ sleep 0.1
41
+ attempts_left -= 1
42
+ end
43
+ end
44
+
45
+ # async assertions for EventMachine specs.
46
+ DeferrableModule = RSpec::EM.async_steps do
47
+ def execute(object, method, *args, &callback)
48
+ deferrable = if args
49
+ object.send(method, *args)
50
+ else
51
+ object.send(method)
52
+ end
53
+
54
+ # Search results have their deferrable
55
+ # on the documents key.
56
+ if deferrable.respond_to?(:documents)
57
+ deferrable = deferrable.results
58
+ end
59
+
60
+ deferrable.callback do |result|
61
+ @success = result
62
+ callback.call
63
+ end
64
+
65
+ deferrable.errback do |err|
66
+ @error = err
67
+ callback.call
68
+ end
69
+ end
70
+
71
+ # recursively look for a matching key and value in hash.
72
+ def success_key_should_have_value(key, expected, &callback)
73
+ # walk the hash structure.
74
+ key = [*key]
75
+ while key.count > 0
76
+ @success = @success.send(key.shift)
77
+ end
78
+
79
+ @success.should == expected
80
+ @success = nil
81
+ callback.call
82
+ end
83
+
84
+ # confirm count of result set.
85
+ def success_result_count_should_equal(expected, &callback)
86
+ @success.count.should == expected
87
+ @success = nil
88
+ callback.call
89
+ end
90
+
91
+ # look for substring in error http_response.
92
+ def error_response_should_contain(expected, &callback)
93
+ @error.http_response.should =~ /#{expected}/
94
+ @error = nil
95
+ callback.call
96
+ end
97
+ end
metadata ADDED
@@ -0,0 +1,174 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: em-stretcher
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Benjamin Coe
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: stretcher
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: deferrable_gratification
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: eventmachine
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: em-http-request
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '1.5'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '1.5'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-eventmachine
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description:
126
+ email:
127
+ - ben@yesware.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - .gitignore
133
+ - .rspec
134
+ - .ruby-version
135
+ - Gemfile
136
+ - LICENSE.txt
137
+ - README.md
138
+ - Rakefile
139
+ - em-stretcher.gemspec
140
+ - lib/em-stretcher.rb
141
+ - lib/em/stretcher/index_type.rb
142
+ - lib/em/stretcher/search_results.rb
143
+ - lib/em/stretcher/server.rb
144
+ - lib/em/stretcher/version.rb
145
+ - spec/server_spec.rb
146
+ - spec/spec_helper.rb
147
+ homepage: ''
148
+ licenses:
149
+ - MIT
150
+ metadata: {}
151
+ post_install_message:
152
+ rdoc_options: []
153
+ require_paths:
154
+ - lib
155
+ required_ruby_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ required_rubygems_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - '>='
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ requirements: []
166
+ rubyforge_project:
167
+ rubygems_version: 2.2.1
168
+ signing_key:
169
+ specification_version: 4
170
+ summary: EventMachine for Stretcher a Fast, Elegant, ElasticSearch client
171
+ test_files:
172
+ - spec/server_spec.rb
173
+ - spec/spec_helper.rb
174
+ has_rdoc: