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.
- checksums.yaml +4 -4
- data/README.md +2 -4
- data/lib/isomorfeus/data/config.rb +0 -8
- data/lib/isomorfeus/data/field_support.rb +108 -48
- data/lib/isomorfeus/data/generic_class_api.rb +10 -2
- data/lib/isomorfeus/data/generic_instance_api.rb +18 -4
- data/lib/isomorfeus/data/handler/generic.rb +0 -1
- data/lib/isomorfeus/data/object_accelerator.rb +105 -40
- data/lib/isomorfeus/data/version.rb +1 -1
- data/lib/isomorfeus-data.rb +0 -7
- data/lib/isomorfeus_data/lucid_object/mixin.rb +108 -146
- metadata +10 -29
- data/lib/isomorfeus/data/attribute_support.rb +0 -174
- data/lib/isomorfeus/data/document_accelerator.rb +0 -84
- data/lib/isomorfeus/data/object_expander.rb +0 -79
- data/lib/isomorfeus_data/lucid_document/base.rb +0 -10
- data/lib/isomorfeus_data/lucid_document/mixin.rb +0 -197
@@ -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,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
|