lib/isomorfeus/data/object_accelerator.rb in isomorfeus-data-2.5.5 vs lib/isomorfeus/data/object_accelerator.rb in isomorfeus-data-22.9.0.rc1
- old
+ new
@@ -9,149 +9,141 @@
attr_accessor :store
def initialize(ruby_class)
@object_class = ruby_class
@object_class_name = ruby_class.name
- @class_cache = Isomorfeus.production?
+ @class_cache = !Isomorfeus.development?
@store_path = File.expand_path(File.join(Isomorfeus.data_documents_path, "#{@object_class_name.underscore}"))
open_store
ObjectSpace.define_finalizer(self, self.class.finalize(self))
end
- def object_from_ref(ref, already_loaded)
- return nil if !ref || ref.empty?
- _, iso, type_class_name, key = ref.split('---')
- raise "not a valid object reference '#{ref}'" unless iso == "iso-object-reference"
- raise "invalid data class #{type_class_name}" unless Isomorfeus.valid_data_class_name?(type_class_name)
- type_class = Isomorfeus.cached_data_class(type_class_name)
- type_class.load(key: key, _already_loaded: already_loaded)
+ def serialize(o)
+ Oj.dump(o, mode: :strict)
end
- def serialize(obj)
- Oj.dump(obj, mode: :object, circular: true, class_cache: @class_cache)
+ def unserialize(s)
+ Oj.load(s, mode: :strict)
end
- def unserialize(v)
- Oj.load(v, mode: :object, circular: true, class_cache: @class_cache)
- end
-
def destroy_store
- close_store
+ close_store rescue nil
FileUtils.rm_rf(@store_path)
end
def close_store
@store.close
end
+ def exist?(sid_s:)
+ !!get_object_id(sid_s)
+ end
+
+ def exist_by_field?(field:, value:)
+ top_docs = @store.search("#{field}:\"#{serialize(value)}\"")
+ top_docs.total_hits > 0
+ end
+
def search_each(query, options, &block)
@store.search_each(query, options, &block)
+ rescue => e
+ return nil if e.message.include?('frt_sort.c')
+ raise e
end
def each(&block)
- ft = @object_class.field_types
- @store.each do |doc|
- hash = doc.to_h do |k, v|
- [k, unserialize_or_load(v, ft[k], {})]
- end
- block.call hash
- end
+ @store.each { |doc| block.call(doc[:key]) }
end
- def create_object(key, fields, already_saved)
- ft = @object_class.field_types
- hash = fields.to_h do |k, v|
- [k, serialize_or_save(v, ft[k], already_saved)]
+ def create(sid_s:, fields:, level: 10)
+ id = get_object_id(sid_s)
+ return false if id
+ data = fields.to_h do |k, v|
+ [k, serialize(v)]
end
- @store.add_document(hash.merge!({key: key}))
+ data[:_revision] = serialize(1)
+ data[:key] = sid_s
+ @store.add_document(data)
+ true
+ rescue => e
+ @store.flush
+ raise e if level < 1
+ create(sid_s: sid_s, fields: fields, level: level - 1)
end
- def destroy_object(key)
- id = get_object_id(key)
+ def destroy(sid_s:)
+ id = get_object_id(sid_s)
@store.delete(id) if id
end
- def load_object(key: nil, id: nil, already_loaded: {})
- hash = nil
- id = get_object_id(key) if key
- if id
- ft = @object_class.field_types
- hash = @store.doc(id)&.to_h do |k, v|
- [k, unserialize_or_load(v, ft[k], already_loaded)]
+ def load(sid_s: nil, id: nil)
+ id = get_object_id(sid_s) if sid_s
+ return nil unless id
+ data = @store.doc(id)&.to_h
+ if data
+ data.delete(:key)
+ data = data.to_h do |k, v|
+ [k, unserialize(v)]
end
end
- hash
+ data
end
- def save_object(key, fields, already_saved)
- id = get_object_id(key)
- return create_object(key, fields, already_saved) unless id
- ft = @object_class.field_types
- hash = fields.to_h do |k, v|
- [k, serialize_or_save(v, ft[k], already_saved)]
- end
- @store.update(id, hash.merge!({key: key}))
- true
+ def field(sid_s:, field:)
+ id = get_object_id(sid_s) if sid_s
+ return nil unless id
+ doc = @store.doc(id)
+ v = doc[field]
+ unserialize(v) if v
end
- private
-
- def unserialize_or_load(v, t, already_loaded)
- return unserialize(v) if t == :attribute
- if t == :object && v
- if v.is_a?(Array)
- v = v.map { |e| object_from_ref(e, already_loaded) }
- v.compact!
- return v
- else
- return nil if v.empty?
- return object_from_ref(v, already_loaded)
- end
- end
- v
+ def load_sid_s(id:)
+ doc = @store.doc(id)
+ return doc[:key] if doc
end
- def serialize_or_save(v, t, already_saved)
- return serialize(v) if t == :attribute
- if t == :object && v
- if v.is_a?(Array)
- v = v.compact
- v.map! { |e| create_or_save(e, already_saved) }
- v.compact!
- return v
- else
- return create_or_save(v, already_saved)
- end
- end
- v
+ def revision(sid_s:)
+ id = get_object_id(sid_s)
+ doc = @store.doc(id) if id
+ return unserialize(doc[:_revision]) if doc
end
- def create_or_save(v, already_saved)
- if get_object_id(v.key)
- v.save(_already_saved: already_saved)
- else
- v.create
+ def save(sid_s:, fields:, revision:, id: nil, level: 10)
+ id = get_object_id(sid_s) unless id
+ return false unless id
+ data = fields.to_h do |k, v|
+ [k, serialize(v)]
end
- v.ref_s
+ data[:key] = sid_s
+ data[:_revision] = serialize(revision)
+ @store.update(id, data)
+ true
+ rescue => e
+ @store.flush
+ raise e if level < 1
+ save(sid_s: sid_s, fields: fields, revision: revision, id: id, level: level - 1)
end
- def get_object_id(key)
+ def escape(string)
# special characters must be escaped, characters taken from the ferret query parser documentation
- escaped_key = key.gsub(/([\\\&\:\(\)\[\]\{\}\!\"\~\^\|\<\>\=\*\?\+\-\s])/, '\\\\\1')
- top_docs = @store.search("key:\"#{escaped_key}\"", limit: 1)
- id = top_docs.hits[0].doc if top_docs.total_hits == 1
+ string.gsub(/([\\\&\:\(\)\[\]\{\}\!\"\~\^\|\<\>\=\*\?\+\-\s])/, '\\\\\1')
end
+ private
+
+ def get_object_id(sid_s)
+ top_docs = @store.search("key:\"#{sid_s}\"", limit: 1)
+ top_docs.hits[0].doc if top_docs.total_hits == 1
+ end
+
def open_store
FileUtils.mkdir_p(Isomorfeus.data_documents_path) unless Dir.exist?(Isomorfeus.data_documents_path)
- field_infos = Isomorfeus::Ferret::Index::FieldInfos.new(store: :yes, index: :yes, term_vector: :no)
+ field_infos = Isomorfeus::Ferret::Index::FieldInfos.new(store: :yes, index: :no, term_vector: :no)
+ @object_class.field_options.each { |field, options| field_infos.add_field(field, options) }
+ field_infos.add_field(:key, store: :yes, index: :yes, term_vector: :yes)
@store = Isomorfeus::Ferret::Index::Index.new(path: @store_path, key: :key, auto_flush: true, lock_retry_time: 5, field_infos: field_infos)
- @store.field_infos.add_field(:key, store: :yes, index: :yes, term_vector: :yes) unless @store.field_infos[:key]
- @object_class.field_options.each do |field, options|
- @store.field_infos.add_field(field, options) unless @store.field_infos[field]
- end
end
end
end
end