Skip to content

Commit

Permalink
Update httprb (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrkamel authored May 26, 2021
1 parent 4900131 commit 523d4b6
Show file tree
Hide file tree
Showing 16 changed files with 134 additions and 122 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
- uses: actions/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
- run: gem install bundler
- run: bundle
- run: sleep 10
- run: bundle exec rspec
Expand Down
3 changes: 2 additions & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
AllCops:
NewCops: enable
TargetRubyVersion: 2.4
TargetRubyVersion: 2.5
SuggestExtensions: false

Layout/EmptyLineBetweenDefs:
EmptyLineBetweenClassDefs: false
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@

# CHANGELOG

## v3.3.0

* Update httprb
* Changed oj default options
* Allow to set oj json options

## v3.2.1

* Fix `refresh` having a empty body breaking in elasticsearch 7.11
Expand Down
61 changes: 27 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

**Full-Featured Elasticsearch Ruby Client with a Chainable DSL**

[![Build Status](https://secure.travis-ci.org/mrkamel/search_flip.svg?branch=master)](http://travis-ci.org/mrkamel/search_flip)
[![Build](https://github.com/mrkamel/search_flip/workflows/test/badge.svg)](https://github.com/mrkamel/search_flip/actions?query=workflow%3Atest+branch%3Amaster)
[![Gem Version](https://badge.fury.io/rb/search_flip.svg)](http://badge.fury.io/rb/search_flip)

Using SearchFlip it is dead-simple to create index classes that correspond to
Expand Down Expand Up @@ -51,8 +51,7 @@ CommentIndex.search("hello world").where(available: true).sort(id: "desc").aggre

```

Finally, SearchFlip comes with a minimal set of dependencies (http-rb, hashie
and oj only).
Finally, SearchFlip comes with a minimal set of dependencies.

## Reference Docs

Expand Down Expand Up @@ -883,52 +882,46 @@ Thus, if your ORM supports `.find_each`, `#id` and `#where` you are already
good to go. Otherwise, simply add your custom implementation of those methods
that work with whatever ORM you use.

## Date and Timestamps in JSON
## JSON

Elasticsearch requires dates and timestamps to have one of the formats listed
here: [https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#strict-date-time](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#strict-date-time).

However, `JSON.generate` in ruby by default outputs something like:
SearchFlip is using the [Oj gem](https://github.com/ohler55/oj) to generate
JSON. More concretely, SearchFlip is using:

```ruby
JSON.generate(time: Time.now.utc)
# => "{\"time\":\"2018-02-22 18:19:33 UTC\"}"
Oj.dump({ key: "value" }, mode: :custom, use_to_json: true, time_format: :xmlschema, bigdecimal_as_decimal: false)
```

This format is not compatible with Elasticsearch by default. If you're on
Rails, ActiveSupport adds its own `#to_json` methods to `Time`, `Date`, etc.
However, ActiveSupport checks whether they are used in combination with
`JSON.generate` or not and adapt:
The `use_to_json` option is used for maximum compatibility, most importantly
when using rails `ActiveSupport::TimeWithZone` timestamps, which `oj` can not
serialize natively. However, `use_to_json` adds performance overhead. You can
change the json options via:

```ruby
Time.now.utc.to_json
=> "\"2018-02-22T18:18:22.088Z\""

JSON.generate(time: Time.now.utc)
=> "{\"time\":\"2018-02-22 18:18:59 UTC\"}"
SearchFlip::Config[:json_options] = {
mode: :custom,
use_to_json: false,
time_format: :xmlschema,
bigdecimal_as_decimal: false
}
```

SearchFlip is using the [Oj gem](https://github.com/ohler55/oj) to generate
JSON. More concretely, SearchFlip is using:
However, you then have to convert timestamps manually for indexation via e.g.:

```ruby
Oj.dump({ key: "value" }, mode: :custom, use_to_json: true)
```
class MyIndex
# ...

This mitigates the issues if you're on Rails:
def self.serialize(model)
{
# ...

```ruby
Oj.dump(Time.now, mode: :custom, use_to_json: true)
# => "\"2018-02-22T18:21:21.064Z\""
created_at: model.created_at.to_time
}
end
end
```

However, if you're not on Rails, you need to add `#to_json` methods to `Time`,
`Date` and `DateTime` to get proper serialization. You can either add them on
your own, via other libraries or by simply using:

```ruby
require "search_flip/to_json"
```
Please check out the oj docs for more details.

## Feature Support

Expand Down
1 change: 1 addition & 0 deletions lib/search_flip.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require "http"
require "hashie"
require "thread"
require "json"
require "oj"
require "set"

Expand Down
2 changes: 1 addition & 1 deletion lib/search_flip/bulk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def upload

return if options[:raise] == false

parsed_response = response.parse
parsed_response = SearchFlip::JSON.parse(response.to_s)

return unless parsed_response["errors"]

Expand Down
8 changes: 7 additions & 1 deletion lib/search_flip/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ module SearchFlip
bulk_limit: 1_000,
bulk_max_mb: 100,
auto_refresh: false,
instrumenter: NullInstrumenter.new
instrumenter: NullInstrumenter.new,
json_options: {
mode: :custom,
use_to_json: true,
time_format: :xmlschema,
bigdecimal_as_decimal: false
}
}
end
41 changes: 27 additions & 14 deletions lib/search_flip/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ def initialize(options = {})

def version
@version_mutex.synchronize do
@version ||= http_client.headers(accept: "application/json").get("#{base_url}/").parse["version"]["number"]
@version ||= begin
response = http_client.headers(accept: "application/json").get("#{base_url}/")

SearchFlip::JSON.parse(response.to_s)["version"]["number"]
end
end
end

Expand All @@ -40,7 +44,9 @@ def version
# @return [Hash] The raw response

def cluster_health
http_client.headers(accept: "application/json").get("#{base_url}/_cluster/health").parse
response = http_client.headers(accept: "application/json").get("#{base_url}/_cluster/health")

SearchFlip::JSON.parse(response.to_s)
end

# Uses the Elasticsearch Multi Search API to execute multiple search requests
Expand Down Expand Up @@ -71,7 +77,7 @@ def msearch(criterias)
.headers(accept: "application/json", content_type: "application/x-ndjson")
.post("#{base_url}/_msearch", body: payload)

raw_response.parse["responses"].map.with_index do |response, index|
SearchFlip::JSON.parse(raw_response.to_s)["responses"].map.with_index do |response, index|
SearchFlip::Response.new(criterias[index], response)
end
end
Expand All @@ -90,10 +96,11 @@ def msearch(criterias)
# @return [Hash] The raw response

def update_aliases(payload)
http_client
response = http_client
.headers(accept: "application/json", content_type: "application/json")
.post("#{base_url}/_aliases", body: SearchFlip::JSON.generate(payload))
.parse

SearchFlip::JSON.parse(response.to_s)
end

# Sends an analyze request to Elasticsearch. Raises
Expand All @@ -105,10 +112,11 @@ def update_aliases(payload)
# @return [Hash] The raw response

def analyze(request, params = {})
http_client
response = http_client
.headers(accept: "application/json")
.post("#{base_url}/_analyze", json: request, params: params)
.parse

SearchFlip::JSON.parse(response.to_s)
end

# Fetches information about the specified index aliases. Raises
Expand All @@ -124,10 +132,11 @@ def analyze(request, params = {})
# @return [Hash] The raw response

def get_aliases(index_name: "*", alias_name: "*")
http_client
response = http_client
.headers(accept: "application/json", content_type: "application/json")
.get("#{base_url}/#{index_name}/_alias/#{alias_name}")
.parse

SearchFlip::JSON.parse(response.to_s)
end

# Returns whether or not the associated Elasticsearch alias already
Expand Down Expand Up @@ -159,10 +168,11 @@ def alias_exists?(alias_name)
# @return [Array] The raw response

def get_indices(name = "*", params: {})
http_client
response = http_client
.headers(accept: "application/json", content_type: "application/json")
.get("#{base_url}/_cat/indices/#{name}", params: params)
.parse

SearchFlip::JSON.parse(response.to_s)
end

alias_method :cat_indices, :get_indices
Expand Down Expand Up @@ -259,10 +269,11 @@ def update_index_settings(index_name, index_settings)
# @return [Hash] The index settings

def get_index_settings(index_name)
http_client
response = http_client
.headers(accept: "application/json")
.get("#{index_url(index_name)}/_settings")
.parse

SearchFlip::JSON.parse(response.to_s)
end

# Sends a refresh request to Elasticsearch. Raises
Expand Down Expand Up @@ -310,7 +321,9 @@ def get_mapping(index_name, type_name: nil)
url = type_name ? type_url(index_name, type_name) : index_url(index_name)
params = type_name && version.to_f >= 6.7 ? { include_type_name: true } : {}

http_client.headers(accept: "application/json").get("#{url}/_mapping", params: params).parse
response = http_client.headers(accept: "application/json").get("#{url}/_mapping", params: params)

SearchFlip::JSON.parse(response.to_s)
end

# Deletes the specified index from Elasticsearch. Raises
Expand Down
2 changes: 1 addition & 1 deletion lib/search_flip/criteria.rb
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ def execute!
http_request.post("#{target.type_url}/_search", params: request_params, json: request)
end

SearchFlip::Response.new(self, http_response.parse)
SearchFlip::Response.new(self, SearchFlip::JSON.parse(http_response.to_s))
rescue SearchFlip::ConnectionError, SearchFlip::ResponseError => e
raise e unless failsafe_value

Expand Down
12 changes: 9 additions & 3 deletions lib/search_flip/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,9 @@ def include_type_name?
# @return [Hash] The specified document

def get(id, params = {})
connection.http_client.headers(accept: "application/json").get("#{type_url}/#{id}", params: params).parse
response = connection.http_client.headers(accept: "application/json").get("#{type_url}/#{id}", params: params)

SearchFlip::JSON.parse(response.to_s)
end

# Retrieves the documents specified by ids from elasticsearch.
Expand All @@ -471,7 +473,9 @@ def get(id, params = {})
# @return [Hash] The raw response

def mget(request, params = {})
connection.http_client.headers(accept: "application/json").post("#{type_url}/_mget", json: request, params: params).parse
response = connection.http_client.headers(accept: "application/json").post("#{type_url}/_mget", json: request, params: params)

SearchFlip::JSON.parse(response.to_s)
end

# Sends an analyze request to Elasticsearch. Raises
Expand All @@ -483,7 +487,9 @@ def mget(request, params = {})
# @return [Hash] The raw response

def analyze(request, params = {})
connection.http_client.headers(accept: "application/json").post("#{index_url}/_analyze", json: request, params: params).parse
response = connection.http_client.headers(accept: "application/json").post("#{index_url}/_analyze", json: request, params: params)

SearchFlip::JSON.parse(response.to_s)
end

# Sends a index refresh request to Elasticsearch. Raises
Expand Down
13 changes: 4 additions & 9 deletions lib/search_flip/json.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
module SearchFlip
class JSON
@default_options = {
mode: :custom,
use_to_json: true
}

def self.default_options
@default_options
def self.generate(obj)
Oj.dump(obj, SearchFlip::Config[:json_options])
end

def self.generate(obj)
Oj.dump(obj, default_options)
def self.parse(json)
::JSON.parse(json)
end
end
end
30 changes: 1 addition & 29 deletions lib/search_flip/to_json.rb
Original file line number Diff line number Diff line change
@@ -1,29 +1 @@
require "time"
require "date"
require "json"

class Time
def to_json(*args)
iso8601(6).to_json
end
end

class Date
def to_json(*args)
iso8601.to_json
end
end

class DateTime
def to_json(*args)
iso8601(6).to_json
end
end

if defined?(ActiveSupport)
class ActiveSupport::TimeWithZone
def to_json(*args)
iso8601(6).to_json
end
end
end
warn "[DEPRECATION] Using search_flip/to_json is not neccessary anymore"
2 changes: 1 addition & 1 deletion lib/search_flip/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module SearchFlip
VERSION = "3.2.1"
VERSION = "3.3.0"
end
1 change: 1 addition & 0 deletions search_flip.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Gem::Specification.new do |spec|

spec.add_dependency "hashie"
spec.add_dependency "http"
spec.add_dependency "json"
spec.add_dependency "oj"
spec.add_dependency "ruby2_keywords"
end
Loading

0 comments on commit 523d4b6

Please sign in to comment.