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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0bdbf9e0dd47a5bf591f0336e92461449ee4e10e460a277a114f1dd457eb77c5
4
- data.tar.gz: b2c421396d4408724ae61918b62521cb6c1bf320450b246d9cd58f10bf321edd
3
+ metadata.gz: acda028de64439232c09263509ce32717e19e34b0845c6e40ee3da69f89f3ead
4
+ data.tar.gz: b05e2cb65596bbeacf951af3d14ef4cfd28e59bbb0c8cb62c37a3a6bd19509f4
5
5
  SHA512:
6
- metadata.gz: 2cf0977b9f7a3962519ded00de041b7e0b8e3c9f54259a6907130bfed7ae3cfc1a825e92137477ccddf45dbbb690de8bbc291b5e4184ff5b5c7adb60cb1b250b
7
- data.tar.gz: b7dcccfcbe26ce6cb68dee2176fd3489a05a2626ad8e77d1426a3d54879152d0329abe52f8b2128d1b17a5a51d608f0dab26665553c3427ff4ed69024ab9ad8c
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
+ [![Build status](https://badge.buildkite.com/346cce75f6c31e0a41bb98b198e85eb6b722243624459fad9c.svg)](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
+ ![Service layers](https://confluence-connect.gliffy.net/embed/image/d02d04b1-5e40-415f-b7ba-3a631efa9bf3.png?utm_medium=live&utm_source=custom)
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
+ ![Service external components](https://confluence-connect.gliffy.net/embed/image/c593fcc2-304e-47c3-8e3c-b0cc09e0ed54.png?utm_medium=live&utm_source=custom)
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.0
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-06-21 00:00:00.000000000 Z
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
- - 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:
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.6
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: []
@@ -1,8 +0,0 @@
1
- # rubocop:disable Naming/FileName
2
- # frozen_string_literal: true
3
-
4
- Dir[File.join(File.dirname(__FILE__), 'realm', '**', '*.rb')].sort.each do |f|
5
- require f
6
- end
7
-
8
- # rubocop:enable Naming/FileName
@@ -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