lib/geminabox/server.rb in geminabox-0.13.7 vs lib/geminabox/server.rb in geminabox-0.13.8
- old
+ new
@@ -1,5 +1,7 @@
+require 'reentrant_flock'
+
module Geminabox
class Server < Sinatra::Base
enable :static, :methodoverride
use Rack::Session::Pool, :expire_after => 2592000
@@ -63,15 +65,15 @@
return if updated_gemspecs.empty?
Geminabox::Indexer.patch_rubygems_update_index_pre_1_8_25(indexer)
indexer.update_index
updated_gemspecs.each { |gem| dependency_cache.flush_key(gem.name) }
rescue Errno::ENOENT
- reindex(:force_rebuild)
+ with_rlock { reindex(:force_rebuild) }
rescue => e
puts "#{e.class}:#{e.message}"
puts e.backtrace.join("\n")
- reindex(:force_rebuild)
+ with_rlock { reindex(:force_rebuild) }
end
end
rescue Gem::SystemExitException
end
@@ -80,14 +82,28 @@
end
def dependency_cache
@dependency_cache ||= Geminabox::DiskCache.new(File.join(data, "_cache"))
end
- end
+ def with_rlock(&block)
+ file_class.open(settings.lockfile, File::RDWR | File::CREAT) do |f|
+ ReentrantFlock.synchronize(f, File::LOCK_EX | File::LOCK_NB, &block)
+ end
+ end
+ # This method provides a test hook, as stubbing File is painful...
+ def file_class
+ @file_class ||= File
+ end
+ def file_class=(klass)
+ @file_class = klass
+ end
+ end
+
+
before do
headers 'X-Powered-By' => "geminabox #{Geminabox::VERSION}"
end
get '/' do
@@ -183,24 +199,16 @@
end
private
def serialize_update(&block)
- with_lock(&block)
- rescue AlreadyLocked
+ with_rlock(&block)
+ rescue ReentrantFlock::AlreadyLocked
halt 503, { 'Retry-After' => settings.retry_interval }, 'Repository lock is held by another process'
end
- def with_lock
- file_class.open(settings.lockfile, File::RDWR | File::CREAT) do |f|
- raise AlreadyLocked unless f.flock(File::LOCK_EX | File::LOCK_NB)
- yield
- end
- end
-
- # This method provides a test hook, as stubbing File is painful...
- def file_class
- File
+ def with_rlock(&block)
+ self.class.with_rlock(&block)
end
def handle_incoming_gem(gem)
begin
GemStore.create(gem, params[:overwrite])