Merge pull request #680 from carlolars/webdav_invalidate_cache_fixes

Webdav invalidate cache fixes
This commit is contained in:
Karel Picman 2017-02-27 09:20:42 +01:00 committed by GitHub
commit 816ac0684a
6 changed files with 131 additions and 1 deletions

View File

@ -260,6 +260,9 @@ class DmsfFile < ActiveRecord::Base
end
end
end
# Must invalidate source parent folder cache before moving
RedmineDmsf::Webdav::Cache.invalidate_item(propfind_cache_key)
self.container_type = self.container_type
self.container_id = container.id

View File

@ -270,7 +270,7 @@ class DmsfFileRevision < ActiveRecord::Base
format2.sub!('%v', self.version)
format2.sub!('%i', self.dmsf_file.id.to_s)
format2.sub!('%r', self.id.to_s)
format2 + ext if ext
format2 += ext if ext
format2
end

View File

@ -73,6 +73,12 @@ module RedmineDmsf
l.save!
reload
locks.reload
# Invalidate PROPFIND (for parent folder)
RedmineDmsf::Webdav::Cache.invalidate_item(self.propfind_cache_key)
# Invalidate PROPSTATS
RedmineDmsf::Webdav::Cache.delete("PROPSTATS/#{RedmineDmsf::Webdav::ProjectResource.create_project_name(self.project)}/#{self.dmsf_path_str}") if self.is_a?(DmsfFolder)
RedmineDmsf::Webdav::Cache.delete("PROPSTATS/#{self.id}-#{self.last_revision.id}") if self.is_a?(DmsfFile)
return l
end
@ -136,6 +142,13 @@ module RedmineDmsf
end
end
end
# Invalidate PROPFIND (for parent folder)
RedmineDmsf::Webdav::Cache.invalidate_item(self.propfind_cache_key)
# Invalidate PROPSTATS
RedmineDmsf::Webdav::Cache.delete("PROPSTATS/#{RedmineDmsf::Webdav::ProjectResource.create_project_name(self.project)}/#{self.dmsf_path_str}") if self.is_a?(DmsfFolder)
RedmineDmsf::Webdav::Cache.delete("PROPSTATS/#{self.id}-#{self.last_revision.id}") if self.is_a?(DmsfFile)
reload
locks.reload
end

View File

@ -273,6 +273,9 @@ module RedmineDmsf
if dest.exist?
MethodNotAllowed
else
# Must invalidate source parent folder cache before moving
RedmineDmsf::Webdav::Cache.invalidate_item(folder.propfind_cache_key)
if(parent.projectless_path == '/') #Project root
folder.dmsf_folder_id = nil
else
@ -337,6 +340,8 @@ module RedmineDmsf
else
if (project == resource.project) && (file.last_revision.size == 0)
# Moving a zero sized file within the same project, just update the dmsf_folder
# Must invalidate source parent folder cache before moving
RedmineDmsf::Webdav::Cache.invalidate_item(file.propfind_cache_key)
file.dmsf_folder = f
else
return InternalServerError unless file.move_to(resource.project, f)

View File

@ -104,6 +104,13 @@ module RedmineDmsf
def file
nil
end
# Available properties
def properties
%w(creationdate displayname getlastmodified getetag resourcetype getcontenttype getcontentlength supportedlock lockdiscovery).collect do |prop|
{:name => prop, :ns_href => 'DAV:'}
end
end
def project_id
self.project.id if self.project

View File

@ -372,4 +372,106 @@ class DmsfWebdavPropfindTest < RedmineDmsf::Test::IntegrationTest
assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid")
end
def test_propfind_depth1_on_project1_for_admin_with_cache_and_locks
RedmineDmsf::Webdav::Cache.init_testcache
log_user 'admin', 'admin' # login as admin
assert !User.current.anonymous?, 'Current user is anonymous'
assert_difference 'RedmineDmsf::Webdav::Cache.cache.instance_variable_get(:@data).count', +7 do
xml_http_request :propfind, "/dmsf/webdav/#{@project1.identifier}", nil,
@admin.merge!({:HTTP_DEPTH => '1'})
assert_response 207 # MultiStatus
end
# Verify that everything exists in the cache as it should
assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder1.title}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder6.title}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file1.id}-#{@file1.last_revision.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file9.id}-#{@file9.last_revision.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file10.id}-#{@file10.last_revision.id}")
# Lock a file and verify that the PROPSTATS for the file and the PROPFIND were deleted
assert @file1.lock!, "File failed to be locked by #{User.current.name}"
assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder1.title}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder6.title}")
assert !RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file1.id}-#{@file1.last_revision.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file9.id}-#{@file9.last_revision.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file10.id}-#{@file10.last_revision.id}")
assert_difference 'RedmineDmsf::Webdav::Cache.cache.instance_variable_get(:@data).count', +1 do
xml_http_request :propfind, "/dmsf/webdav/#{@project1.identifier}", nil,
@admin.merge!({:HTTP_DEPTH => '1'})
assert_response 207 # MultiStatus
end
assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}")
assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file1.id}-#{@file1.last_revision.id}")
# Unlock a file and verify that the PROPSTATS for the file and the PROPFIND were deleted
assert @file1.unlock!, "File failed to be unlocked by #{User.current.name}"
assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder1.title}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder6.title}")
assert !RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file1.id}-#{@file1.last_revision.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file9.id}-#{@file9.last_revision.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file10.id}-#{@file10.last_revision.id}")
assert_difference 'RedmineDmsf::Webdav::Cache.cache.instance_variable_get(:@data).count', +1 do
xml_http_request :propfind, "/dmsf/webdav/#{@project1.identifier}", nil,
@admin.merge!({:HTTP_DEPTH => '1'})
assert_response 207 # MultiStatus
end
assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}")
assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file1.id}-#{@file1.last_revision.id}")
# Lock a folder and verify that the PROPSTATS for the file and the PROPFIND were deleted
assert @folder1.lock!, "File failed to be locked by #{User.current.name}"
assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}")
assert !RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder1.title}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder6.title}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file1.id}-#{@file1.last_revision.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file9.id}-#{@file9.last_revision.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file10.id}-#{@file10.last_revision.id}")
assert_difference 'RedmineDmsf::Webdav::Cache.cache.instance_variable_get(:@data).count', +1 do
xml_http_request :propfind, "/dmsf/webdav/#{@project1.identifier}", nil,
@admin.merge!({:HTTP_DEPTH => '1'})
assert_response 207 # MultiStatus
end
assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}")
assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder1.title}")
# Unlock a folder and verify that the PROPSTATS for the file and the PROPFIND were deleted
assert @folder1.unlock!, "File failed to be unlocked by #{User.current.name}"
assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}")
assert !RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder1.title}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder6.title}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file1.id}-#{@file1.last_revision.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file9.id}-#{@file9.last_revision.id}")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@file10.id}-#{@file10.last_revision.id}")
assert_difference 'RedmineDmsf::Webdav::Cache.cache.instance_variable_get(:@data).count', +1 do
xml_http_request :propfind, "/dmsf/webdav/#{@project1.identifier}", nil,
@admin.merge!({:HTTP_DEPTH => '1'})
assert_response 207 # MultiStatus
end
assert RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}")
assert !RedmineDmsf::Webdav::Cache.exist?("PROPFIND/#{@project1.id}.invalid")
assert RedmineDmsf::Webdav::Cache.exist?("PROPSTATS/#{@project1.identifier}/#{@folder1.title}")
end
end