isomorfeus-data 2.4.2 → 2.5.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.
@@ -1,84 +0,0 @@
1
- module Isomorfeus
2
- module Data
3
- class DocumentAccelerator
4
- def self.finalize(fer_acc)
5
- proc { fer_acc.close_index }
6
- end
7
-
8
- attr_reader :doc_class, :doc_class_name
9
- attr_accessor :index
10
-
11
- def initialize(doc_class, &block)
12
- @doc_class = doc_class
13
- @doc_class_name = doc_class.name
14
- if block_given?
15
- res = block.call(self)
16
- @index = res unless @index
17
- else
18
- @index_path = File.expand_path(File.join(Isomorfeus.data_documents_path, @doc_class_name.underscore))
19
- open_index
20
- end
21
- ObjectSpace.define_finalizer(self, self.class.finalize(self))
22
- end
23
-
24
- def destroy_index
25
- close_index
26
- FileUtils.rm_rf(@index_path)
27
- end
28
-
29
- def close_index
30
- @index.close
31
- end
32
-
33
- def create_doc(document)
34
- @index.add_document(document)
35
- end
36
-
37
- def destroy_doc(key)
38
- id = get_doc_id(key)
39
- @index.delete(id) if id
40
- true
41
- end
42
-
43
- def load_doc(key)
44
- id = get_doc_id(key)
45
- @index.doc(id)&.load&.to_h if id
46
- end
47
-
48
- def save_doc(key, document)
49
- id = get_doc_id(key)
50
- if id
51
- @index.update(id, document)
52
- true
53
- end
54
- end
55
-
56
- def search_each(query, options, &block)
57
- @index.search_each(query, options, &block)
58
- end
59
-
60
- def each(&block)
61
- @index.each(&block)
62
- end
63
-
64
- private
65
-
66
- def get_doc_id(key)
67
- # special characters must be escaped, characters taken from the ferret query parser documentation
68
- escaped_key = key.gsub(/([\\\&\:\(\)\[\]\{\}\!\"\~\^\|\<\>\=\*\?\+\-\s])/, '\\\\\1')
69
- top_docs = @index.search("key:\"#{escaped_key}\"", limit: 1)
70
- id = top_docs.hits[0].doc if top_docs.total_hits == 1
71
- end
72
-
73
- def open_index
74
- FileUtils.mkdir_p(Isomorfeus.data_documents_path) unless Dir.exist?(Isomorfeus.data_documents_path)
75
- field_infos = Isomorfeus::Ferret::Index::FieldInfos.new(store: :yes, index: :yes, term_vector: :with_positions_offsets)
76
- @index = Isomorfeus::Ferret::Index::Index.new(path: @index_path, key: :key, auto_flush: true, lock_retry_time: 5, field_infos: field_infos)
77
- @index.field_infos.add_field(:key, store: :yes, index: :yes, term_vector: :no) unless @index.field_infos[:key]
78
- @doc_class.field_options.each do |field, options|
79
- @index.field_infos.add_field(field, options) unless @index.field_infos[field]
80
- end
81
- end
82
- end
83
- end
84
- end
@@ -1,79 +0,0 @@
1
- module Isomorfeus
2
- module Data
3
- class ObjectExpander
4
- class << self
5
- def finalize(ins)
6
- proc { ins.environment.close rescue nil }
7
- end
8
- end
9
-
10
- attr_accessor :environment
11
-
12
- def initialize(class_name:, compress: false, &block)
13
- if block_given?
14
- res = block.call(self)
15
- self.environment = res unless self.environment
16
- else
17
- @env_path = File.expand_path(File.join(Isomorfeus.data_object_envs_path, class_name.underscore))
18
- open_environment
19
- end
20
- @db = self.environment.database('objects', create: true)
21
- @index_db = self.environment.database('index', create: true, dupsort: true)
22
- @compress = compress
23
- @use_class_cache = !Isomorfeus.development?
24
- ObjectSpace.define_finalizer(self, self.class.finalize(self))
25
- end
26
-
27
- def create_object(sid_s, obj)
28
- Isomorfeus::Hamster::Marshal.dump(@db, sid_s, obj, class_cache: @use_class_cache, compress: @compress)
29
- end
30
-
31
- def destroy_object(sid_s)
32
- @db.delete(sid_s) rescue nil
33
- true
34
- end
35
-
36
- def load_object(sid_s)
37
- Isomorfeus::Hamster::Marshal.load(@db, sid_s, class_cache: @use_class_cache)
38
- end
39
-
40
- def save_object(sid_s, obj)
41
- Isomorfeus::Hamster::Marshal.dump(@db, sid_s, obj, class_cache: @use_class_cache, compress: @compress)
42
- end
43
-
44
- def index_delete(key, val)
45
- @index_db.delete(key, val) rescue nil
46
- end
47
-
48
- def index_get(key)
49
- @index_db.get(key)
50
- end
51
-
52
- def index_put(key, val)
53
- environment.transaction { @index_db.put(key, val) }
54
- end
55
-
56
- def each(readonly: true, &block)
57
- @db.each(readonly: readonly) do |key, obj|
58
- block.call(Isomorfeus::Hamster::Marshal.unserialize(obj, class_cache: @use_class_cache))
59
- end
60
- end
61
-
62
- def search(val_key, &block)
63
- @index_db.each_value(val_key, &block)
64
- end
65
-
66
- private
67
-
68
- def open_environment
69
- FileUtils.mkdir_p(@env_path) unless Dir.exist?(@env_path)
70
- begin
71
- self.environment = Isomorfeus::Hamster.new(@env_path, mapsize: Isomorfeus.hamster_mapsize)
72
- rescue RangeError
73
- self.environment = Isomorfeus::Hamster.new(@env_path, mapsize: 2_147_483_647)
74
- STDERR.puts "Isomorfeus::Data Warning: Hamster Object Store limited to 2Gb because of platform restrictions."
75
- end
76
- end
77
- end
78
- end
79
- end
@@ -1,10 +0,0 @@
1
- module LucidDocument
2
- class Base
3
- def self.inherited(base)
4
- base.include(LucidDocument::Mixin)
5
- if RUBY_ENGINE != 'opal'
6
- Isomorfeus.add_valid_data_class(base)
7
- end
8
- end
9
- end
10
- end
@@ -1,197 +0,0 @@
1
- module LucidDocument
2
- module Mixin
3
- def self.included(base)
4
- base.include(Isomorfeus::Data::FieldSupport)
5
- base.extend(Isomorfeus::Data::GenericClassApi)
6
- base.include(Isomorfeus::Data::GenericInstanceApi)
7
- base.include(LucidI18n::Mixin)
8
-
9
- base.instance_exec do
10
- def escape_string(s)
11
- s.gsub(/([\\\&\:\(\)\[\]\{\}\!\"\~\^\|\<\>\=\*\?\+\-\s])/, '\\\\\1')
12
- end
13
- end
14
-
15
- def [](name)
16
- send(name)
17
- end
18
-
19
- def []=(name, val)
20
- send("#{name}=", val)
21
- end
22
-
23
- def changed!
24
- @_changed = true
25
- end
26
-
27
- def to_transport
28
- hash = { 'fields' => _get_selected_fields }
29
- hash['revision'] = revision if revision
30
- result = { @class_name => { @key => hash }}
31
- result.deep_merge!(@class_name => { @previous_key => { new_key: @key}}) if @previous_key
32
- result
33
- end
34
-
35
- if RUBY_ENGINE == 'opal'
36
- def initialize(key: nil, revision: nil, fields: nil, _loading: false)
37
- @key = key.nil? ? SecureRandom.uuid : key.to_s
38
- @class_name = self.class.name
39
- @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
40
- _update_paths
41
- @_revision = revision ? revision : Redux.fetch_by_path(:data_state, :revision, @class_name, @key)
42
- @_changed = false
43
- loaded = loaded?
44
- if loaded
45
- raw_fields = Redux.fetch_by_path(*@_store_path)
46
- if `raw_fields === null`
47
- if fields
48
- _validate_fields(fields)
49
- @_changed_fields = fields
50
- else
51
- @_changed_fields = {}
52
- end
53
- elsif raw_fields && fields && ::Hash.new(raw_fields) != fields
54
- _validate_fields(fields)
55
- @_changed_fields = fields
56
- else
57
- @_changed_fields = {}
58
- end
59
- else
60
- fields = {} unless fields
61
- _validate_fields(fields) unless _loading
62
- @_changed_fields = fields
63
- end
64
- end
65
-
66
- def _load_from_store!
67
- @_changed_fields = {}
68
- @_changed = false
69
- end
70
-
71
- def _update_paths
72
- @_store_path = [:data_state, @class_name, @key, :fields]
73
- end
74
-
75
- def each(&block)
76
- fields.each(&block)
77
- end
78
- else # RUBY_ENGINE
79
- Isomorfeus.add_valid_data_class(base) unless base == LucidDocument::Base
80
-
81
- base.instance_exec do
82
- def instance_from_transport(instance_data, _included_items_data)
83
- key = instance_data[self.name].keys.first
84
- revision = instance_data[self.name][key].key?('revision') ? instance_data[self.name][key]['revision'] : nil
85
- fields = instance_data[self.name][key].key?('fields') ? instance_data[self.name][key]['fields'].transform_keys!(&:to_sym) : nil
86
- new(key: key, revision: revision, fields: fields)
87
- end
88
-
89
- def props_from_data(instance_data)
90
- key = instance_data[self.name].keys.first
91
- revision = instance_data[self.name][key].key?('revision') ? instance_data[self.name][key]['revision'] : nil
92
- fields = instance_data[self.name][key].key?('fields') ? instance_data[self.name][key]['fields'].transform_keys!(&:to_sym) : nil
93
- LucidProps.new({ key: key, revision: revision }.merge!(fields))
94
- end
95
-
96
- def setup_index(&block)
97
- @_setup_index_block = block
98
- end
99
-
100
- def document_accelerator
101
- return @document_accelerator if @document_accelerator
102
- @document_accelerator = if @_setup_index_block
103
- Isomorfeus::Data::DocumentAccelerator.new(self, &@_setup_index_block)
104
- else
105
- Isomorfeus::Data::DocumentAccelerator.new(self)
106
- end
107
- end
108
-
109
- def each(&block)
110
- self.document_accelerator.each do |doc|
111
- doc = doc.to_h
112
- key = doc.delete(:key)
113
- block.call(self.new(key: key, fields: doc))
114
- end
115
- end
116
-
117
- def search(query, options = {})
118
- top_docs = []
119
- self.document_accelerator.search_each(query, options) do |id|
120
- doc = self.document_accelerator.index.doc(id)&.to_h
121
- if doc
122
- key = doc.delete(:key)
123
- top_docs << self.new(key: key, fields: doc)
124
- end
125
- end
126
- top_docs
127
- end
128
-
129
- execute_create do
130
- doc = self.fields.dup
131
- if self.key.nil?
132
- u = SecureRandom.uuid
133
- doc[:key] = u
134
- self.key = u
135
- else
136
- doc[:key] = self.key
137
- end
138
- self.class.document_accelerator.create_doc(doc)
139
- self
140
- end
141
-
142
- execute_destroy do |key:|
143
- self.document_accelerator.destroy_doc(key)
144
- end
145
-
146
- execute_load do |key:|
147
- doc = self.document_accelerator.load_doc(key)
148
- if doc
149
- doc.delete(:key)
150
- self.new(key: key, fields: doc)
151
- end
152
- end
153
-
154
- execute_save do
155
- doc = self.fields.dup
156
- if self.key.nil?
157
- u = SecureRandom.uuid
158
- doc[:key] = u
159
- self.key = u
160
- self.class.document_accelerator.create_doc(doc)
161
- else
162
- doc[:key] = self.key
163
- self.class.document_accelerator.save_doc(self.key, doc)
164
- end
165
- self
166
- end
167
- end
168
-
169
- def initialize(key: nil, revision: nil, fields: nil)
170
- @key = key.nil? ? SecureRandom.uuid : key.to_s
171
- @class_name = self.class.name
172
- @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
173
- @_revision = revision
174
- @_changed = false
175
- fields = {} unless fields
176
- _validate_fields(fields)
177
- @_raw_fields = fields
178
- end
179
-
180
- def _unchange!
181
- @_changed = false
182
- end
183
-
184
- def each(&block)
185
- @_raw_fields.each(&block)
186
- end
187
-
188
- def reload
189
- new_instance = self.class.load(key: @key)
190
- @_raw_fields = new_instance.fields
191
- _unchange!
192
- self
193
- end
194
- end # RUBY_ENGINE
195
- end
196
- end
197
- end