realm-elasticsearch 0.7.0 → 0.7.3
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 +4 -4
- data/README.md +40 -0
- data/Rakefile +19 -0
- metadata +25 -14
- data/lib/realm-elasticsearch.rb +0 -8
- data/lib/realm/elasticsearch/gateway.rb +0 -51
- data/lib/realm/elasticsearch/plugin.rb +0 -16
- data/lib/realm/elasticsearch/rake_tasks.rb +0 -40
- data/lib/realm/elasticsearch/repository.rb +0 -118
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: acda028de64439232c09263509ce32717e19e34b0845c6e40ee3da69f89f3ead
|
4
|
+
data.tar.gz: b05e2cb65596bbeacf951af3d14ef4cfd28e59bbb0c8cb62c37a3a6bd19509f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a0e53f266e2d48b0e21401e66c0d661682976fa954d1ae2db1e00a433403cb2845c925e0917e8ead489a8d8f2bdb2db28c3fec5e8af75c00eaf757f5b77a093
|
7
|
+
data.tar.gz: 99a15268d00a042d40d9753cbb99827923c693527d64c28cc62ddf1209860735d04b5093cf968287eb6aa3a5e565b36b9842c4cb11f2c520839e0510606c33a3
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# Realm
|
2
|
+
|
3
|
+
Domain layer framework following Domain-driven/CQRS design principles.
|
4
|
+
|
5
|
+
[](https://buildkite.com/reevoo/realm)
|
6
|
+
|
7
|
+
## Service layers
|
8
|
+
|
9
|
+
We follow the standard MVC design pattern of Rails but giving the model layer more structure and guidance regarding where
|
10
|
+
to put your code. The model is split into domain layer (using our [Realm](https://github.com/reevoo/smart-mono/tree/master/gems/realm) library)
|
11
|
+
and persistence layer (using [ROM](https://rom-rb.org/) library). The individual components are explained in the following section.
|
12
|
+
|
13
|
+

|
14
|
+
|
15
|
+
Advanced components are shown in lighter color, those will be needed only later on as the service domain logic grows.
|
16
|
+
|
17
|
+
## Model layer components
|
18
|
+
|
19
|
+

|
20
|
+
|
21
|
+
Each service has one **domain** module which consists of multiple [**aggregate**](https://martinfowler.com/bliki/DDD_Aggregate.html) modules.
|
22
|
+
Aggregate is a cluster of domain objects that can be treated as a single unit. The only way for outer world to communicate
|
23
|
+
with aggregate is by **queries** and **commands**. Query exposes aggregate's internal state and command changes it.
|
24
|
+
The state of an aggregate is represented by tree of **entities** with one being the aggregate root and zero or more dependent
|
25
|
+
entities with *belongs_to* relation to the root entity. The state of an aggregate (entity tree) is persisted
|
26
|
+
and retrieved by **repository**. There is generally one repository per aggregate unless we split the read/write
|
27
|
+
(query/command) persistence model for that particular domain. The repository uses **relations** to access the database
|
28
|
+
tables. Each relation class represents one table.
|
29
|
+
|
30
|
+
|
31
|
+
## Where to put my code as it grows?
|
32
|
+
|
33
|
+
TODO
|
34
|
+
|
35
|
+
|
36
|
+
## Roadmap
|
37
|
+
|
38
|
+
- [ ] Support Ruby 3
|
39
|
+
- [ ] Make it work outside of Rails engines
|
40
|
+
- [ ] Support multiple persistence gateways in one runtime
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'rdoc/task'
|
10
|
+
|
11
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
12
|
+
rdoc.rdoc_dir = 'rdoc'
|
13
|
+
rdoc.title = 'Realm'
|
14
|
+
rdoc.options << '--line-numbers'
|
15
|
+
rdoc.rdoc_files.include('README.md')
|
16
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'bundler/gem_tasks'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: realm-elasticsearch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- developers@reevoo.com
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: elasticsearch
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.4'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: zeitwerk
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.4'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.4'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: pry-byebug
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,22 +108,19 @@ dependencies:
|
|
94
108
|
- - ">="
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '0'
|
97
|
-
description:
|
98
|
-
email:
|
111
|
+
description:
|
112
|
+
email:
|
99
113
|
executables: []
|
100
114
|
extensions: []
|
101
115
|
extra_rdoc_files: []
|
102
116
|
files:
|
103
|
-
-
|
104
|
-
-
|
105
|
-
|
106
|
-
- lib/realm/elasticsearch/rake_tasks.rb
|
107
|
-
- lib/realm/elasticsearch/repository.rb
|
108
|
-
homepage:
|
117
|
+
- README.md
|
118
|
+
- Rakefile
|
119
|
+
homepage:
|
109
120
|
licenses:
|
110
121
|
- MIT
|
111
122
|
metadata: {}
|
112
|
-
post_install_message:
|
123
|
+
post_install_message:
|
113
124
|
rdoc_options: []
|
114
125
|
require_paths:
|
115
126
|
- lib
|
@@ -124,8 +135,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
124
135
|
- !ruby/object:Gem::Version
|
125
136
|
version: '0'
|
126
137
|
requirements: []
|
127
|
-
rubygems_version: 3.1.
|
128
|
-
signing_key:
|
138
|
+
rubygems_version: 3.1.4
|
139
|
+
signing_key:
|
129
140
|
specification_version: 4
|
130
141
|
summary: Elasticsearch plugin for Realm
|
131
142
|
test_files: []
|
data/lib/realm-elasticsearch.rb
DELETED
@@ -1,51 +0,0 @@
|
|
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
|
@@ -1,16 +0,0 @@
|
|
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
|
@@ -1,40 +0,0 @@
|
|
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
|
@@ -1,118 +0,0 @@
|
|
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
|