realm-elasticsearch 0.7.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.
- checksums.yaml +7 -0
- data/lib/realm-elasticsearch.rb +8 -0
- data/lib/realm/elasticsearch/gateway.rb +51 -0
- data/lib/realm/elasticsearch/plugin.rb +16 -0
- data/lib/realm/elasticsearch/rake_tasks.rb +40 -0
- data/lib/realm/elasticsearch/repository.rb +118 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0bdbf9e0dd47a5bf591f0336e92461449ee4e10e460a277a114f1dd457eb77c5
|
4
|
+
data.tar.gz: b2c421396d4408724ae61918b62521cb6c1bf320450b246d9cd58f10bf321edd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2cf0977b9f7a3962519ded00de041b7e0b8e3c9f54259a6907130bfed7ae3cfc1a825e92137477ccddf45dbbb690de8bbc291b5e4184ff5b5c7adb60cb1b250b
|
7
|
+
data.tar.gz: b7dcccfcbe26ce6cb68dee2176fd3489a05a2626ad8e77d1426a3d54879152d0329abe52f8b2128d1b17a5a51d608f0dab26665553c3427ff4ed69024ab9ad8c
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'typhoeus'
|
4
|
+
require 'elasticsearch'
|
5
|
+
require 'realm/health_status'
|
6
|
+
require_relative 'repository'
|
7
|
+
|
8
|
+
module Realm
|
9
|
+
module Elasticsearch
|
10
|
+
class Gateway
|
11
|
+
def initialize(url:, **options)
|
12
|
+
@url = url
|
13
|
+
@client_options = options.slice(:adapter, :retry_on_failure, :request_timeout)
|
14
|
+
end
|
15
|
+
|
16
|
+
def health
|
17
|
+
issues = []
|
18
|
+
index_names = Repository.subclasses.map(&:index_name)
|
19
|
+
begin
|
20
|
+
issues << 'One or more indexes missing' unless client.indices.exists(index: index_names)
|
21
|
+
rescue StandardError => e
|
22
|
+
issues << "Elasticsearch connection error: #{e.full_message}"
|
23
|
+
end
|
24
|
+
HealthStatus.from_issues(issues)
|
25
|
+
end
|
26
|
+
|
27
|
+
def method_missing(...)
|
28
|
+
client.send(...)
|
29
|
+
end
|
30
|
+
|
31
|
+
def respond_to_missing?(...)
|
32
|
+
client.respond_to?(...)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def client
|
38
|
+
@client ||= ::Elasticsearch::Client.new(default_config.merge(@client_options))
|
39
|
+
end
|
40
|
+
|
41
|
+
def default_config
|
42
|
+
{
|
43
|
+
url: @url,
|
44
|
+
adapter: :typhoeus,
|
45
|
+
retry_on_failure: 3,
|
46
|
+
request_timeout: 30,
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'realm/plugin'
|
4
|
+
require_relative 'gateway'
|
5
|
+
|
6
|
+
module Realm
|
7
|
+
module Elasticsearch
|
8
|
+
class Plugin < Realm::Plugin
|
9
|
+
def self.setup(config, container)
|
10
|
+
return unless config.persistence_gateway[:type] == :elasticsearch
|
11
|
+
|
12
|
+
container.register_factory(Gateway, **config.persistence_gateway, as: 'persistence.gateway')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Realm
|
6
|
+
module Elasticsearch
|
7
|
+
module RakeTasks
|
8
|
+
class << self
|
9
|
+
def setup(engine_name, engine_root: nil, url: ENV['ELASTICSEARCH_URL'])
|
10
|
+
return unless url
|
11
|
+
|
12
|
+
client = ::Elasticsearch::Client.new(url: url)
|
13
|
+
|
14
|
+
Rake.application.in_namespace(:es) do
|
15
|
+
Rake::Task.define_task(:create_indexes) do
|
16
|
+
with_definitions(engine_name, engine_root) do |index, config|
|
17
|
+
client.indices.create(index: index, body: config) unless client.indices.exists(index: index)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Rake::Task.define_task(:drop_indexes) do
|
22
|
+
with_definitions(engine_name, engine_root) do |index, _config|
|
23
|
+
client.indices.delete(index: index) if client.indices.exists(index: index)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def with_definitions(engine_name, engine_root)
|
32
|
+
engine_root ||= Rails.root.join('engines', engine_name.to_s)
|
33
|
+
Dir.glob(File.join(engine_root, 'elasticsearch/indexes/*.yaml')).each do |path|
|
34
|
+
yield File.basename(path, '.yaml'), YAML.safe_load(File.read(path))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'active_support/core_ext/string'
|
5
|
+
|
6
|
+
module Realm
|
7
|
+
module Elasticsearch
|
8
|
+
class Repository
|
9
|
+
def self.repo_name(value = :not_provided)
|
10
|
+
@repo_name = value.to_sym unless value == :not_provided
|
11
|
+
@repo_name = name.demodulize.underscore unless defined?(@repo_name)
|
12
|
+
@repo_name
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.index_name(value = :not_provided)
|
16
|
+
@index_name = value.to_sym unless value == :not_provided
|
17
|
+
@index_name = repo_name.pluralize unless defined?(@index_name)
|
18
|
+
@index_name
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(client)
|
22
|
+
@client = client
|
23
|
+
end
|
24
|
+
|
25
|
+
def find(id:)
|
26
|
+
single(client.get(index: index_name, id: id))
|
27
|
+
rescue ::Elasticsearch::Transport::Transport::Errors::NotFound
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def all
|
32
|
+
multiple(raw_search(query: { match_all: {} }))
|
33
|
+
end
|
34
|
+
|
35
|
+
def create(id: nil, **attrs)
|
36
|
+
client.index(index: index_name, type: '_doc', id: id, body: attrs, refresh: refresh?)
|
37
|
+
rescue ::Elasticsearch::Transport::Transport::Errors::Conflict
|
38
|
+
raise Realm::Persistence::Conflict
|
39
|
+
end
|
40
|
+
|
41
|
+
def update(id:, **attrs)
|
42
|
+
raw_update(id, doc: attrs)
|
43
|
+
end
|
44
|
+
|
45
|
+
def upsert(id:, **attrs)
|
46
|
+
raw_update(id, doc: attrs, doc_as_upsert: true)
|
47
|
+
end
|
48
|
+
|
49
|
+
def delete(id:)
|
50
|
+
client.delete(index: index_name, type: '_doc', id: id, refresh: refresh?)
|
51
|
+
true
|
52
|
+
rescue ::Elasticsearch::Transport::Transport::Errors::NotFound
|
53
|
+
false
|
54
|
+
end
|
55
|
+
|
56
|
+
def search_by(params)
|
57
|
+
multiple(raw_search(query: { bool: { must: match_params(params) } }))
|
58
|
+
end
|
59
|
+
|
60
|
+
def delete_by(params)
|
61
|
+
client.delete_by_query(
|
62
|
+
index: index_name,
|
63
|
+
refresh: refresh?,
|
64
|
+
body: { query: {
|
65
|
+
bool: {
|
66
|
+
must: match_params(params),
|
67
|
+
},
|
68
|
+
} },
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
def raw_update(id, body = {})
|
73
|
+
client.update(index: index_name, type: '_doc', id: id, body: body, refresh: refresh?)
|
74
|
+
end
|
75
|
+
|
76
|
+
def raw_search(yaml: nil, options: {}, **body)
|
77
|
+
client.search(index: index_name, body: yaml ? YAML.safe_load(yaml) : body, **options)
|
78
|
+
end
|
79
|
+
|
80
|
+
def truncate!
|
81
|
+
client.delete_by_query(
|
82
|
+
index: index_name,
|
83
|
+
body: { query: { match_all: {} } },
|
84
|
+
conflicts: 'proceed',
|
85
|
+
refresh: refresh?,
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
attr_reader :client
|
92
|
+
|
93
|
+
def refresh?
|
94
|
+
# impacts performance so should be used only in TEST env
|
95
|
+
# TODO: remove dependency on Rails
|
96
|
+
defined?(::Rails) && ::Rails.env.test?
|
97
|
+
end
|
98
|
+
|
99
|
+
def single(result)
|
100
|
+
id = result['_id'].then { |i| i.to_i.positive? ? i.to_i : i }
|
101
|
+
result['_source'].merge(id: id).deep_symbolize_keys
|
102
|
+
end
|
103
|
+
|
104
|
+
def multiple(results)
|
105
|
+
docs = results.dig('hits', 'hits').map { |doc| single(doc) }
|
106
|
+
{ docs: docs }
|
107
|
+
end
|
108
|
+
|
109
|
+
def match_params(params)
|
110
|
+
params.map { |(key, value)| { match: { key => value } } }
|
111
|
+
end
|
112
|
+
|
113
|
+
def index_name
|
114
|
+
self.class.index_name
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: realm-elasticsearch
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.7.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- developers@reevoo.com
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-06-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: elasticsearch
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '7.11'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '7.11'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: realm-core
|
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: typhoeus
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.4'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.4'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry-byebug
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
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: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
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
|
+
description:
|
98
|
+
email:
|
99
|
+
executables: []
|
100
|
+
extensions: []
|
101
|
+
extra_rdoc_files: []
|
102
|
+
files:
|
103
|
+
- lib/realm-elasticsearch.rb
|
104
|
+
- lib/realm/elasticsearch/gateway.rb
|
105
|
+
- lib/realm/elasticsearch/plugin.rb
|
106
|
+
- lib/realm/elasticsearch/rake_tasks.rb
|
107
|
+
- lib/realm/elasticsearch/repository.rb
|
108
|
+
homepage:
|
109
|
+
licenses:
|
110
|
+
- MIT
|
111
|
+
metadata: {}
|
112
|
+
post_install_message:
|
113
|
+
rdoc_options: []
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 2.7.0
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
requirements: []
|
127
|
+
rubygems_version: 3.1.6
|
128
|
+
signing_key:
|
129
|
+
specification_version: 4
|
130
|
+
summary: Elasticsearch plugin for Realm
|
131
|
+
test_files: []
|