class Geminabox::Store::S3
Constants
- SPLICEABLE_GZIPPED_FILES
- SPLICEABLE_TEXT_FILES
Attributes
logger[R]
Public Class Methods
new(bucket: nil, lock_manager: lock_manager, file_store: Geminabox::GemStore, logger: Logger.new(STDOUT))
click to toggle source
# File lib/geminabox/store/s3.rb, line 19 def initialize(bucket: nil, lock_manager: lock_manager, file_store: Geminabox::GemStore, logger: Logger.new(STDOUT)) @bucket = bucket @file_store = file_store @lock_manager = lock_manager @logger = logger end
Public Instance Methods
create(gem, overwrite = false)
click to toggle source
# File lib/geminabox/store/s3.rb, line 26 def create(gem, overwrite = false) @file_store.create gem, overwrite object_name = gem_object_name("/gems/" + gem.name) logger.info "Gem: local -> S3 #{object_name}" @bucket .objects[object_name] .write gem.gem_data update_metadata end
delete(path_info)
click to toggle source
Note: deleting doesn't make much sense in this case anyway, as other instances will continue serving cached copies of this gem (there's no way to notify them that gem has been deleted)
Do consider using Geminabox.allow_delete = false
# File lib/geminabox/store/s3.rb, line 45 def delete(path_info) @file_store.delete path_info @bucket.objects[gem_object_name(path_info)].delete end
reindex(&block)
click to toggle source
# File lib/geminabox/store/s3.rb, line 83 def reindex &block FileUtils.mkpath @file_store.local_path "gems" @bucket.objects.with_prefix("gems/").each do |object| path_info = "/" + object.key local_file_path = @file_store.local_path path_info file_does_not_exist = !File.exists?(local_file_path) # File.size raises an exception if file does not exist file_size = file_does_not_exist ? 0 : File.size(local_file_path) file_has_different_size = object.content_length != file_size if file_does_not_exist || file_has_different_size logger.info "Gem: S3 -> local #{local_file_path}" File.write local_file_path, object.read end end @file_store.reindex(&block) end
update_local_file(path_info)
click to toggle source
# File lib/geminabox/store/s3.rb, line 51 def update_local_file(path_info) gem_file = @file_store.local_path path_info unless File.exists? gem_file gem_object = @bucket.objects[gem_object_name(path_info)] if gem_object.exists? # Note: this will load the entire contents of the gem into # memory We might switch to using streaming IO or # temporary files if this proves to be critical in our # environment io = StringIO.new gem_object.read incoming_gem = Geminabox::IncomingGem.new io @file_store.create incoming_gem update_metadata end end @file_store.update_local_file path_info end
update_local_metadata_file(path_info)
click to toggle source
# File lib/geminabox/store/s3.rb, line 72 def update_local_metadata_file(path_info) file_name = File.basename path_info pull_file file_name do |local, remote| if file_name =~ /\.gz$/ merge_gzipped local, remote else merge_text local, remote end end end
Private Instance Methods
gem_object_name(path_info)
click to toggle source
# File lib/geminabox/store/s3.rb, line 160 def gem_object_name(path_info) # Remove loading slash from the path path_info[1..-1] end
merge_file_with_remote(file_name) { |old_contents, read| ... }
click to toggle source
# File lib/geminabox/store/s3.rb, line 124 def merge_file_with_remote file_name local_index_file = @file_store.local_path file_name if File.exists? local_index_file old_contents = File.read(local_index_file, open_args: ["rb"]) else old_contents = '' end object = s3_object(file_name) unless object.exists? old_contents else yield old_contents, object.read end end
merge_gzipped(a, b)
click to toggle source
# File lib/geminabox/store/s3.rb, line 169 def merge_gzipped(a, b) package(unpackage(a) | unpackage(b)) end
merge_text(a, b)
click to toggle source
# File lib/geminabox/store/s3.rb, line 173 def merge_text(a, b) a.to_s + b.to_s end
metadata_object_name(path_info)
click to toggle source
# File lib/geminabox/store/s3.rb, line 165 def metadata_object_name(path_info) path_info.gsub %r{/}, 'metadata/' end
package(content)
click to toggle source
# File lib/geminabox/store/s3.rb, line 181 def package(content) Gem.gzip(Marshal.dump(content)) end
pull_file(file_name, &block)
click to toggle source
# File lib/geminabox/store/s3.rb, line 152 def pull_file file_name, &block logger.info "Pull: S3 -> local #{file_name}" new_contents = merge_file_with_remote file_name, &block file_path = @file_store.local_path file_name File.write file_path, new_contents end
push_file(file_name, &block)
click to toggle source
# File lib/geminabox/store/s3.rb, line 145 def push_file file_name, &block logger.info "Push: local -> S3 #{file_name}" new_contents = merge_file_with_remote file_name, &block s3_object(file_name).write new_contents end
push_files(file_list, &block)
click to toggle source
# File lib/geminabox/store/s3.rb, line 118 def push_files file_list, &block file_list.each do |file_name| push_file file_name, &block end end
s3_object(file_name)
click to toggle source
# File lib/geminabox/store/s3.rb, line 140 def s3_object file_name object_name = metadata_object_name('/' + file_name) @bucket.objects[object_name] end
unpackage(content)
click to toggle source
# File lib/geminabox/store/s3.rb, line 177 def unpackage(content) Marshal.load(Gem.gunzip(content)) end
update_metadata()
click to toggle source
# File lib/geminabox/store/s3.rb, line 106 def update_metadata @lock_manager.lock ".metadata" do push_files SPLICEABLE_GZIPPED_FILES do |local_contents, remote_contents| merge_gzipped local_contents, remote_contents end push_files SPLICEABLE_TEXT_FILES do |local_contents, remote_contents| merge_text local_contents, remote_contents end end end