isomorfeus-data 2.4.2 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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