elos 0.1.0 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/bin/push +40 -0
  4. data/bin/rspec +16 -0
  5. data/db/migrate/001_create_a_entry_repos.rb +7 -0
  6. data/elos-0.1.0.gem +0 -0
  7. data/elos-1.0.3.gem +0 -0
  8. data/elos.gemspec +20 -9
  9. data/lib/elos/configuration.rb +16 -0
  10. data/lib/elos/criteria.rb +78 -0
  11. data/lib/elos/data_object.rb +30 -0
  12. data/lib/elos/errors/not_found.rb +5 -0
  13. data/lib/elos/errors/validation_failed.rb +5 -0
  14. data/lib/elos/index/core.rb +35 -0
  15. data/lib/elos/index/indexable.rb +32 -0
  16. data/lib/elos/index/locatable.rb +17 -0
  17. data/lib/elos/index/mappings.rb +25 -0
  18. data/lib/elos/index/model/assignable.rb +19 -0
  19. data/lib/elos/index/model/identifiable.rb +9 -0
  20. data/lib/elos/index/model/initializable.rb +13 -0
  21. data/lib/elos/index/model.rb +12 -0
  22. data/lib/elos/index/raw_helpers.rb +9 -0
  23. data/lib/elos/index/refreshable.rb +9 -0
  24. data/lib/elos/index/reindexable.rb +132 -0
  25. data/lib/elos/index/searchable.rb +17 -0
  26. data/lib/elos/index/subscribable.rb +14 -0
  27. data/lib/elos/index/unindexable.rb +9 -0
  28. data/lib/elos/index.rb +15 -0
  29. data/lib/elos/lock.rb +48 -0
  30. data/lib/elos/query_builder/base.rb +23 -0
  31. data/lib/elos/query_builder/builtin/match_all_query_builder.rb +5 -0
  32. data/lib/elos/query_builder/builtin/where_query_builder.rb +5 -0
  33. data/lib/elos/query_builder/filters.rb +41 -0
  34. data/lib/elos/query_builder/queries.rb +15 -0
  35. data/lib/elos/repository/adapter/active_record/scanable.rb +11 -0
  36. data/lib/elos/repository/adapter/active_record.rb +6 -0
  37. data/lib/elos/repository/adapter/elos/migratable.rb +13 -0
  38. data/lib/elos/repository/adapter/elos/model/destroyable.rb +44 -0
  39. data/lib/elos/repository/adapter/elos/model/persistable.rb +79 -0
  40. data/lib/elos/repository/adapter/elos/model/reindexable.rb +15 -0
  41. data/lib/elos/repository/adapter/elos/model/unindexable.rb +7 -0
  42. data/lib/elos/repository/adapter/elos/model/validatable.rb +8 -0
  43. data/lib/elos/repository/adapter/elos/scanable.rb +24 -0
  44. data/lib/elos/repository/adapter/elos.rb +31 -0
  45. data/lib/elos/repository/publishable.rb +26 -0
  46. data/lib/elos/result.rb +23 -0
  47. data/lib/elos/version.rb +2 -2
  48. data/lib/elos.rb +3 -3
  49. data/lib/initialize.rb +6 -0
  50. metadata +129 -2
data/lib/elos/lock.rb ADDED
@@ -0,0 +1,48 @@
1
+ class Elos::Lock
2
+ include Elos::Index::Core
3
+
4
+ def self.lock(key, &block)
5
+ create_index(index_name)
6
+ id = SecureRandom.uuid
7
+ body = { doc: {}, upsert: { lock: id } }
8
+ client.update(index: index_name, type: type_name, id: key, body: body)
9
+ if client.get(index: index_name, type: type_name, id: key)['_source']['lock'] == id
10
+ if block
11
+ begin
12
+ ret = block.()
13
+ ensure
14
+ unlock(key)
15
+ end
16
+ else
17
+ true
18
+ end
19
+ end
20
+ end
21
+
22
+ def self.unlock(key)
23
+ client.delete(index: index_name, type: type_name, id: key)
24
+ rescue Elasticsearch::Transport::Transport::Errors::NotFound
25
+ end
26
+
27
+ private
28
+
29
+ def self.mappings
30
+ {
31
+ type_name => {
32
+ _all: { enabled: false },
33
+ _ttl: { enabled: true, default: '5d' },
34
+ properties: properties
35
+ }
36
+ }
37
+ end
38
+
39
+ def self.properties
40
+ {
41
+ boolean_property => %i(lock)
42
+ }.inject({}) { |m, x| m.merge(Hash[x[1].map { |y| [y, x[0]] }]) }
43
+ end
44
+
45
+ def self.boolean_property
46
+ { type: 'boolean' }
47
+ end
48
+ end
@@ -0,0 +1,23 @@
1
+ class Elos::QueryBuilder::Base
2
+ include Elos::QueryBuilder::Filters
3
+ include Elos::QueryBuilder::Queries
4
+
5
+ def initialize(params)
6
+ @params = params
7
+ end
8
+
9
+ def _build
10
+ query = build
11
+ original_query = query[:query]
12
+ filter = term_filter(:_destroyed, value: false)
13
+ query[:query] = { filtered: { query: original_query, filter: filter } }
14
+ # puts JSON.pretty_generate(query)
15
+ query
16
+ end
17
+
18
+ protected
19
+
20
+ def params
21
+ @params
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ class Elos::QueryBuilder::Builtin::MatchAllQueryBuilder < Elos::QueryBuilder::Base
2
+ def build
3
+ match_all_query
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class Elos::QueryBuilder::Builtin::WhereQueryBuilder < Elos::QueryBuilder::Base
2
+ def build
3
+ ids_query
4
+ end
5
+ end
@@ -0,0 +1,41 @@
1
+ module Elos::QueryBuilder::Filters
2
+ extend ActiveSupport::Concern
3
+
4
+ def or_filter(*filters)
5
+ filters = filters.first if filters.first.is_a?(Array)
6
+ filters.compact!
7
+ { or: filters } unless filters.empty?
8
+ end
9
+
10
+ def and_filter(*filters)
11
+ filters = filters.first if filters.first.is_a?(Array)
12
+ filters.compact!
13
+ { and: filters } unless filters.empty?
14
+ end
15
+
16
+ def term_filter(key, params_sym = nil, value: nil)
17
+ v = value.nil? ? params[params_sym || key] : value
18
+ { term: { key => v } } unless v.nil?
19
+ end
20
+
21
+ def terms_filter(key, params_sym = nil, values: nil)
22
+ v = value.nil? ? params[params_sym || key.to_s.pluralize.to_sym] : value
23
+ { terms: { key => v } } unless v.empty?
24
+ end
25
+
26
+ def exists_filter(key)
27
+ { exists: { field: key } }
28
+ end
29
+
30
+ def missing_filter(key)
31
+ { missing: { field: key } }
32
+ end
33
+
34
+ def range_filter(key, min: nil, max: nil)
35
+ return unless min || max
36
+ r = { range: { key => {} } }
37
+ r[:range][key][:gte] = min if min
38
+ r[:range][key][:lte] = max if max
39
+ r
40
+ end
41
+ end
@@ -0,0 +1,15 @@
1
+ module Elos::QueryBuilder::Queries
2
+ extend ActiveSupport::Concern
3
+
4
+ def ids_query(key = :id, value = nil)
5
+ { query: { ids: { values: value || params[key] } } }
6
+ end
7
+
8
+ def match_query(key, value)
9
+ { query: { match: { key => { query: value, operator: 'and' } } } }
10
+ end
11
+
12
+ def match_all_query
13
+ { query: { match_all: {} } }
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module Elos::Repository::Adapter::ActiveRecord::Scanable
2
+ extend ActiveSupport::Concern
3
+
4
+ class_methods do
5
+ def scan(batch_size = nil, &block)
6
+ find_each(batch_size: batch_size) do |record|
7
+ block.(record)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ module Elos::Repository::Adapter::ActiveRecord
2
+ extend ActiveSupport::Concern
3
+
4
+ include Elos::Repository::Publishable
5
+ include Elos::Repository::Adapter::ActiveRecord::Scanable
6
+ end
@@ -0,0 +1,13 @@
1
+ module Elos::Repository::Adapter::Elos::Migratable
2
+ extend ActiveSupport::Concern
3
+
4
+ class_methods do
5
+ def migrate
6
+ reindex do |old_index_name, new_index_name|
7
+ _scan(index_name: old_index_name) do |hit|
8
+ client.update(index: new_index_name, type: type_name, id: hit['_id'], body: { doc: {}, upsert: hit['_source'] })
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,44 @@
1
+ module Elos::Repository::Adapter::Elos::Model::Destroyable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ cattr_writer :physically_destroy
6
+
7
+ attr_accessor :destroyed
8
+
9
+ define_model_callbacks :destroy
10
+
11
+ before_new -> { self.destroyed = false; true }
12
+
13
+ self.physically_destroy = true
14
+ end
15
+
16
+ class_methods do
17
+ def physically_destroy?
18
+ physically_destroy
19
+ end
20
+
21
+ def physically_destroy(flag = nil)
22
+ if flag.nil?
23
+ self.class_variable_get(:@@physically_destroy)
24
+ else
25
+ self.physically_destroy = flag
26
+ end
27
+ end
28
+ end
29
+
30
+ def destroyed?
31
+ destroyed
32
+ end
33
+
34
+ def destroy
35
+ run_callbacks :destroy do
36
+ if self.class.physically_destroy?
37
+ self.class.index(self, unindex: true)
38
+ else
39
+ self.class.index(self, destroy: true)
40
+ end
41
+ self.destroyed = true
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,79 @@
1
+ module Elos::Repository::Adapter::Elos::Model::Persistable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ attr_accessor :persisted
6
+
7
+ define_model_callbacks :save, :create, :update
8
+
9
+ before_new -> { self.persisted = !!@_attrs.delete(:_persisted); true }
10
+ end
11
+
12
+ class_methods do
13
+ def create(attrs = {})
14
+ obj = new(attrs)
15
+ obj.save
16
+ obj
17
+ end
18
+
19
+ def create!(attrs = {})
20
+ obj = new(attrs)
21
+ obj.save!
22
+ obj
23
+ end
24
+ end
25
+
26
+ def persisted?
27
+ persisted
28
+ end
29
+
30
+ def save
31
+ _save
32
+ end
33
+
34
+ def save!
35
+ _save(raise_error: true)
36
+ end
37
+
38
+ def update(attrs = {})
39
+ assign_attributes(attrs)
40
+ save
41
+ end
42
+
43
+ def update!(attrs = {})
44
+ assign_attributes(attrs)
45
+ save!
46
+ end
47
+
48
+ private
49
+
50
+ def _save(raise_error: false, callback: true)
51
+ return false unless raise_error ? validate! : valid?
52
+ optionally_run_callbacks(:save, callback: callback) do
53
+ if persisted?
54
+ optionally_run_callbacks(:update, callback: callback) do
55
+ _save_core
56
+ end
57
+ else
58
+ optionally_run_callbacks(:create, callback: callback) do
59
+ _save_core
60
+ self.persisted = true
61
+ end
62
+ end
63
+ end
64
+ true
65
+ end
66
+
67
+ def optionally_run_callbacks(method, callback: true, &block)
68
+ if callback
69
+ run_callbacks(method, &block)
70
+ else
71
+ block.()
72
+ end
73
+ end
74
+
75
+ def _save_core
76
+ r = reindex
77
+ self.id ||= r
78
+ end
79
+ end
@@ -0,0 +1,15 @@
1
+ module Elos::Repository::Adapter::Elos::Model::Reindexable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ reindex -> do
6
+ scan do |obj|
7
+ obj.reindex
8
+ end
9
+ end
10
+ end
11
+
12
+ def reindex(destroy: false)
13
+ self.class.index(self, destroy: destroy)
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ module Elos::Repository::Adapter::Elos::Model::Unindexable
2
+ extend ActiveSupport::Concern
3
+
4
+ def unindex
5
+ self.class.index(obj, unindex: true)
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Elos::Repository::Adapter::Elos::Model::Validatable
2
+ extend ActiveSupport::Concern
3
+
4
+ def validate!
5
+ return true if valid?
6
+ raise Elos::Errors::ValidationFailed.new
7
+ end
8
+ end
@@ -0,0 +1,24 @@
1
+ module Elos::Repository::Adapter::Elos::Scanable
2
+ extend ActiveSupport::Concern
3
+
4
+ class_methods do
5
+ def scan(batch_size = nil, &block)
6
+ _scan(batch_size) do |hit|
7
+ block.(new(hit['_source'].merge(id: hit['_id'], _persisted: true)))
8
+ end
9
+ end
10
+
11
+ protected
12
+
13
+ def _scan(batch_size = nil, index_name: read_alias_name, &block)
14
+ batch_size ||= 100
15
+ scroll_id = client.search(index: index_name, type: type_name, search_type: :scan, scroll: '1h', body: { query: { match_all: {} }, size: batch_size })['_scroll_id']
16
+ while r = client.scroll(scroll: '1h', scroll_id: scroll_id) and (hits = r['hits']['hits']).present? do
17
+ scroll_id = r['_scroll_id']
18
+ hits.each do |hit|
19
+ block.(hit)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ module Elos::Repository::Adapter::Elos
2
+ extend ActiveSupport::Concern
3
+
4
+ include Elos::Index
5
+
6
+ included do
7
+ cattr_accessor :included_callbacks
8
+
9
+ self.included_callbacks = []
10
+
11
+ include Elos::Repository::Adapter::Elos::Migratable
12
+ include Elos::Repository::Adapter::Elos::Scanable
13
+ include Elos::Repository::Publishable
14
+ include Elos::Repository::Adapter::Elos::Model::Reindexable
15
+ include Elos::Repository::Adapter::Elos::Model::Unindexable
16
+ include Elos::Repository::Adapter::Elos::Model::Persistable
17
+ include Elos::Repository::Adapter::Elos::Model::Destroyable
18
+ include Elos::Repository::Adapter::Elos::Model::Validatable
19
+
20
+ included_callbacks.each { |callback| callback.() }
21
+
22
+ subscribe self
23
+
24
+ physically_destroy false
25
+ end
26
+
27
+ def self.reindex_all(indices = nil)
28
+ # indices ||= 結びつく全てのindexたち
29
+ # indicesのreindex全てをnestさせてその中でscanしてreindexしていく
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ module Elos::Repository::Publishable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ cattr_accessor :subscribers
6
+
7
+ self.subscribers = []
8
+
9
+ proc = -> { after_save ->(obj) { subscribers.each { |s| s.index(obj) } } }
10
+ if respond_to?(:after_save)
11
+ proc.()
12
+ else
13
+ self.included_callbacks << proc
14
+ end
15
+ end
16
+
17
+ class_methods do
18
+ def publish_reindex
19
+ scan do |obj|
20
+ subscribers.each do |klass|
21
+ klass.index(obj)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ class Elos::Result
2
+ include Enumerable
3
+
4
+ def initialize(result)
5
+ @result = result
6
+ end
7
+
8
+ def each
9
+ result.each do |item|
10
+ yield item
11
+ end
12
+ end
13
+
14
+ def pluck(key)
15
+ map { |obj| obj.send(key) }
16
+ end
17
+
18
+ protected
19
+
20
+ def result
21
+ @result
22
+ end
23
+ end
data/lib/elos/version.rb CHANGED
@@ -1,3 +1,3 @@
1
- module Elos
2
- VERSION = "0.1.0"
1
+ class Elos
2
+ VERSION = '1.0.4'
3
3
  end
data/lib/elos.rb CHANGED
@@ -1,5 +1,5 @@
1
- require "elos/version"
1
+ require_relative 'initialize'
2
2
 
3
- module Elos
4
- # Your code goes here...
3
+ class Elos
4
+ include Elos::Configuration
5
5
  end
data/lib/initialize.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'active_support/all'
5
+
6
+ ActiveSupport::Dependencies.autoload_paths << File.expand_path('../../lib', __FILE__)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tetsuri Moriya
@@ -10,6 +10,34 @@ bindir: exe
10
10
  cert_chain: []
11
11
  date: 2015-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 3.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 3.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: elasticsearch
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'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: bundler
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +66,62 @@ dependencies:
38
66
  - - "~>"
39
67
  - !ruby/object:Gem::Version
40
68
  version: '10.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: database_cleaner
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 1.2.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 1.2.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: activerecord
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: mysql2
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'
41
125
  description: Elasticsearch integration for Databases, such as ActiveRecord
42
126
  email:
43
127
  - tetsuri.moriya@gmail.com
@@ -54,10 +138,54 @@ files:
54
138
  - README.md
55
139
  - Rakefile
56
140
  - bin/console
141
+ - bin/push
142
+ - bin/rspec
57
143
  - bin/setup
144
+ - db/migrate/001_create_a_entry_repos.rb
145
+ - elos-0.1.0.gem
146
+ - elos-1.0.3.gem
58
147
  - elos.gemspec
59
148
  - lib/elos.rb
149
+ - lib/elos/configuration.rb
150
+ - lib/elos/criteria.rb
151
+ - lib/elos/data_object.rb
152
+ - lib/elos/errors/not_found.rb
153
+ - lib/elos/errors/validation_failed.rb
154
+ - lib/elos/index.rb
155
+ - lib/elos/index/core.rb
156
+ - lib/elos/index/indexable.rb
157
+ - lib/elos/index/locatable.rb
158
+ - lib/elos/index/mappings.rb
159
+ - lib/elos/index/model.rb
160
+ - lib/elos/index/model/assignable.rb
161
+ - lib/elos/index/model/identifiable.rb
162
+ - lib/elos/index/model/initializable.rb
163
+ - lib/elos/index/raw_helpers.rb
164
+ - lib/elos/index/refreshable.rb
165
+ - lib/elos/index/reindexable.rb
166
+ - lib/elos/index/searchable.rb
167
+ - lib/elos/index/subscribable.rb
168
+ - lib/elos/index/unindexable.rb
169
+ - lib/elos/lock.rb
170
+ - lib/elos/query_builder/base.rb
171
+ - lib/elos/query_builder/builtin/match_all_query_builder.rb
172
+ - lib/elos/query_builder/builtin/where_query_builder.rb
173
+ - lib/elos/query_builder/filters.rb
174
+ - lib/elos/query_builder/queries.rb
175
+ - lib/elos/repository/adapter/active_record.rb
176
+ - lib/elos/repository/adapter/active_record/scanable.rb
177
+ - lib/elos/repository/adapter/elos.rb
178
+ - lib/elos/repository/adapter/elos/migratable.rb
179
+ - lib/elos/repository/adapter/elos/model/destroyable.rb
180
+ - lib/elos/repository/adapter/elos/model/persistable.rb
181
+ - lib/elos/repository/adapter/elos/model/reindexable.rb
182
+ - lib/elos/repository/adapter/elos/model/unindexable.rb
183
+ - lib/elos/repository/adapter/elos/model/validatable.rb
184
+ - lib/elos/repository/adapter/elos/scanable.rb
185
+ - lib/elos/repository/publishable.rb
186
+ - lib/elos/result.rb
60
187
  - lib/elos/version.rb
188
+ - lib/initialize.rb
61
189
  homepage: https://github.com/pandora2000/elos
62
190
  licenses:
63
191
  - MIT
@@ -83,4 +211,3 @@ signing_key:
83
211
  specification_version: 4
84
212
  summary: Elasticsearch integration for Databases
85
213
  test_files: []
86
- has_rdoc: