diff --git a/lib/valkyrie/persistence/solr/orm_converter.rb b/lib/valkyrie/persistence/solr/orm_converter.rb index 113bc4a4b..47101190e 100644 --- a/lib/valkyrie/persistence/solr/orm_converter.rb +++ b/lib/valkyrie/persistence/solr/orm_converter.rb @@ -24,7 +24,7 @@ def internal_resource end def attributes - attribute_hash.merge("id" => id, internal_resource: internal_resource, created_at: created_at, updated_at: updated_at) + attribute_hash.merge("id" => id, internal_resource: internal_resource, created_at: created_at, updated_at: updated_at, optimistic_lock_token: version) end def created_at @@ -35,6 +35,10 @@ def updated_at DateTime.parse(solr_document["timestamp"] || solr_document.fetch("created_at_dtsi").to_s).utc end + def version + solr_document.fetch('_version_', nil) + end + def id solr_document.fetch('id').sub(/^id-/, '') end diff --git a/lib/valkyrie/specs/shared_specs/locking_query.rb b/lib/valkyrie/specs/shared_specs/locking_query.rb new file mode 100644 index 000000000..0129960cf --- /dev/null +++ b/lib/valkyrie/specs/shared_specs/locking_query.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true +RSpec.shared_examples 'a Valkyrie locking query provider' do + before do + raise 'adapter must be set with `let(:adapter)`' unless + defined? adapter + class CustomLockingQueryResource < Valkyrie::Resource + enable_optimistic_locking + attribute :id, Valkyrie::Types::ID.optional + attribute :title + end + end + after do + Object.send(:remove_const, :CustomLockingQueryResource) + end + + let(:query_service) { adapter.query_service } unless defined? query_service + let(:persister) { adapter.persister } + subject { adapter.query_service } + + it "retrieves the lock token and casts it to optimistic_lock_token attribute" do + resource = CustomLockingQueryResource.new(title: "My Title") + resource = persister.save(resource: resource) + resource = query_service.find_by(id: resource.id) + # we can't know the value in the general case + expect(resource.optimistic_lock_token).not_to be_empty + end +end diff --git a/spec/valkyrie/persistence/solr/query_service_spec.rb b/spec/valkyrie/persistence/solr/query_service_spec.rb index 5a9365634..7c2d36a1d 100644 --- a/spec/valkyrie/persistence/solr/query_service_spec.rb +++ b/spec/valkyrie/persistence/solr/query_service_spec.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'spec_helper' require 'valkyrie/specs/shared_specs' +require 'valkyrie/specs/shared_specs/locking_query' RSpec.describe Valkyrie::Persistence::Solr::QueryService do before do @@ -8,7 +9,33 @@ client.delete_by_query("*:*") client.commit end + let(:adapter) { Valkyrie::Persistence::Solr::MetadataAdapter.new(connection: client) } let(:client) { RSolr.connect(url: SOLR_TEST_URL) } it_behaves_like "a Valkyrie query provider" + it_behaves_like "a Valkyrie locking query provider" + + describe "optimistic locking" do + let(:query_service) { adapter.query_service } unless defined? query_service + let(:persister) { adapter.persister } + + before do + class CustomLockingResource < Valkyrie::Resource + enable_optimistic_locking + attribute :id, Valkyrie::Types::ID.optional + attribute :title + end + end + + after do + Object.send(:remove_const, :CustomLockingResource) + end + + it "retrieves the lock token and casts it to optimistic_lock_token attribute" do + resource = persister.save(resource: CustomLockingResource.new(title: "My Title")) + resource = query_service.find_by(id: resource.id) + query_doc = (query_service.connection.get 'select', params: { q: "id:#{resource.id}" })["response"]["docs"].first + expect(resource.optimistic_lock_token.first).to eq query_doc["_version_"] + end + end end