Class: Valkyrie::Storage::VersionedDisk
- Inherits:
-
Object
- Object
- Valkyrie::Storage::VersionedDisk
- Defined in:
- lib/valkyrie/storage/versioned_disk.rb
Overview
The VersionedDisk adapter implements versioned storage on disk by storing the timestamp of the file’s creation as part of the file name (v-timestamp-filename.jpg). If the current file is deleted it creates a DeletionMarker, which is an empty file with “deletionmarker” in the name of the file.
Defined Under Namespace
Classes: VersionId
Constant Summary collapse
- PROTOCOL =
'versiondisk://'
Instance Attribute Summary collapse
-
#base_path ⇒ Object
readonly
Returns the value of attribute base_path.
-
#file_mover ⇒ Object
readonly
Returns the value of attribute file_mover.
-
#path_generator ⇒ Object
readonly
Returns the value of attribute path_generator.
Instance Method Summary collapse
- #current_timestamp ⇒ Object
-
#delete(id:) ⇒ Object
Delete the file on disk associated with the given identifier.
- #file_path(version_id) ⇒ Object
-
#find_by(id:) ⇒ Valkyrie::StorageAdapter::File
Return the file associated with the given identifier.
- #find_versions(id:) ⇒ Array<Valkyrie::StorageAdapter::File>
-
#handles?(id:) ⇒ Boolean
True if this adapter can handle this type of identifer.
-
#initialize(base_path:, path_generator: ::Valkyrie::Storage::Disk::BucketedStorage, file_mover: FileUtils.method(:cp)) ⇒ VersionedDisk
constructor
A new instance of VersionedDisk.
-
#protocol ⇒ String
Identifier prefix.
-
#supports?(feature) ⇒ Boolean
True if the adapter supports the given feature.
- #upload(file:, original_filename:, resource: nil, paused: false, **extra_arguments) ⇒ Valkyrie::StorageAdapter::File
- #upload_version(id:, file:, paused: false) ⇒ Object
- #version_files(id:) ⇒ Object
-
#version_id(id) ⇒ Object
VersionId A VersionId value that’s resolved a current reference, so we can access the ‘version_id` and current reference.
Constructor Details
#initialize(base_path:, path_generator: ::Valkyrie::Storage::Disk::BucketedStorage, file_mover: FileUtils.method(:cp)) ⇒ VersionedDisk
Returns a new instance of VersionedDisk.
12 13 14 15 16 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 12 def initialize(base_path:, path_generator: ::Valkyrie::Storage::Disk::BucketedStorage, file_mover: FileUtils.method(:cp)) @base_path = Pathname.new(base_path.to_s) @path_generator = path_generator.new(base_path: base_path) @file_mover = file_mover end |
Instance Attribute Details
#base_path ⇒ Object (readonly)
Returns the value of attribute base_path.
9 10 11 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 9 def base_path @base_path end |
#file_mover ⇒ Object (readonly)
Returns the value of attribute file_mover.
9 10 11 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 9 def file_mover @file_mover end |
#path_generator ⇒ Object (readonly)
Returns the value of attribute path_generator.
9 10 11 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 9 def path_generator @path_generator end |
Instance Method Details
#current_timestamp ⇒ Object
34 35 36 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 34 def Time.now.strftime("%s%L") end |
#delete(id:) ⇒ Object
Delete the file on disk associated with the given identifier.
90 91 92 93 94 95 96 97 98 99 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 90 def delete(id:) id = version_id(id).resolve_current if id.current? id.version_files.each do |version_id| FileUtils.rm_rf(version_id.file_path) end elsif File.exist?(id.file_path) FileUtils.rm_rf(id.file_path) end end |
#file_path(version_id) ⇒ Object
115 116 117 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 115 def file_path(version_id) version_id.to_s.gsub(/^#{Regexp.escape(protocol)}/, '') end |
#find_by(id:) ⇒ Valkyrie::StorageAdapter::File
Return the file associated with the given identifier
80 81 82 83 84 85 86 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 80 def find_by(id:) version_id = version_id(id) raise Valkyrie::StorageAdapter::FileNotFound if version_id.nil? || version_id&.deletion_marker? Valkyrie::StorageAdapter::File.new(id: version_id.current_reference_id.id, io: ::Valkyrie::Storage::Disk::LazyFile.open(version_id.file_path, 'rb'), version_id: version_id.id) rescue Errno::ENOENT raise Valkyrie::StorageAdapter::FileNotFound end |
#find_versions(id:) ⇒ Array<Valkyrie::StorageAdapter::File>
103 104 105 106 107 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 103 def find_versions(id:) version_files(id: id).select { |x| !x.to_s.include?("deletionmarker") }.map do |file| find_by(id: Valkyrie::ID.new("#{protocol}#{file}")) end end |
#handles?(id:) ⇒ Boolean
Returns true if this adapter can handle this type of identifer.
60 61 62 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 60 def handles?(id:) id.to_s.start_with?("#{protocol}#{base_path}") end |
#protocol ⇒ String
Returns identifier prefix.
72 73 74 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 72 def protocol PROTOCOL end |
#supports?(feature) ⇒ Boolean
Returns true if the adapter supports the given feature.
66 67 68 69 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 66 def supports?(feature) return true if feature == :versions || feature == :version_deletion false end |
#upload(file:, original_filename:, resource: nil, paused: false, **extra_arguments) ⇒ Valkyrie::StorageAdapter::File
23 24 25 26 27 28 29 30 31 32 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 23 def upload(file:, original_filename:, resource: nil, paused: false, **extra_arguments) = new_path = path_generator.generate(resource: resource, file: file, original_filename: "v-#{}-#{original_filename}") # If we've gone faster than milliseconds here, pause a millisecond and # re-call. Probably only an issue for test suites. return sleep(0.001) && upload(file: file, original_filename: original_filename, resource: resource, paused: true, **extra_arguments) if !paused && File.exist?(new_path) FileUtils.mkdir_p(new_path.parent) file_mover.call(file.try(:path) || file.try(:disk_path), new_path) find_by(id: Valkyrie::ID.new("#{protocol}#{new_path}")) end |
#upload_version(id:, file:, paused: false) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 43 def upload_version(id:, file:, paused: false) = # Get the existing version_id so we can calculate the next path from it. current_version_id = version_id(id) current_version_id = current_version_id.version_files[1] if current_version_id.deletion_marker? existing_path = current_version_id.file_path new_path = Pathname.new(existing_path.gsub(current_version_id.version, .to_s)) # If we've gone faster than milliseconds here, pause a millisecond and # re-call. return sleep(0.001) && upload_version(id: id, file: file, paused: true) if !paused && File.exist?(new_path) FileUtils.mkdir_p(new_path.parent) file_mover.call(file.try(:path) || file.try(:disk_path), new_path) find_by(id: Valkyrie::ID.new("#{protocol}#{new_path}")) end |
#version_files(id:) ⇒ Object
109 110 111 112 113 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 109 def version_files(id:) root = Pathname.new(file_path(id)) id = VersionId.new(id) root.parent.children.select { |file| file.basename.to_s.end_with?(id.filename) }.sort.reverse end |
#version_id(id) ⇒ Object
Returns VersionId A VersionId value that’s resolved a current reference, so we can access the ‘version_id` and current reference.
121 122 123 124 125 |
# File 'lib/valkyrie/storage/versioned_disk.rb', line 121 def version_id(id) id = VersionId.new(id) return id unless id.versioned? id.resolve_current end |