lib/sdb_lock.rb in sdb_lock-0.0.2 vs lib/sdb_lock.rb in sdb_lock-0.1.0

- old
+ new

@@ -1,9 +1,8 @@ require "sdb_lock/version" +require 'aws-sdk' -require 'aws' - # Lock using SimpleDB conditional put. # # Create instance. # lock = SdbLock.new('my_app_lock', access_key_id: YOUR_AWS_ACCESS_KEY, secret_access_key: YOUR_AWS_SECRET) # @@ -33,35 +32,48 @@ # Constructor # # @param [String] domain_name SimpleDB domain name # @param [Hash] options def initialize(domain_name, options = {}) - @sdb = AWS::SimpleDB.new(options) - options = options.dup - if options.has_key?(:create_domain) - @sdb.domains.create(domain_name) if options[:create_domain] - options.delete(:create_domain) + @sdb = ::Aws::SimpleDB::Client.new(options) + @domain_name = domain_name + unless domains.include? @domain_name + @sdb.create_domain(domain_name: @domain_name) + @domains = @sdb.list_domains.domain_names end - @domain = @sdb.domains[domain_name] end # Try to lock resource_name # # @param [String] resource_name name to lock # @return [TrueClass] true when locked, unless false def try_lock(resource_name) - attributes = {LOCK_TIME => format_time(Time.now), unless: LOCK_TIME} - item(resource_name).attributes.set(attributes) + attributes = [ + { + name: LOCK_TIME, + value: format_time(Time.now) + } + ] + + @sdb.put_attributes( + domain_name: @domain_name, + item_name: resource_name, + attributes: attributes, + expected: { + name: LOCK_TIME, + exists: false + } + ) if block_given? begin yield ensure unlock(resource_name) end end true - rescue AWS::SimpleDB::Errors::ConditionalCheckFailed + rescue ::Aws::SimpleDB::Errors::ConditionalCheckFailed false end # lock resource_name # It blocks until lock is succeeded. @@ -88,26 +100,39 @@ end # Unlock resource_name # @param [String] resource_name name to unlock def unlock(resource_name, expected_lock_time = nil) - if expected_lock_time - item(resource_name).attributes.delete(LOCK_TIME, if: {LOCK_TIME => expected_lock_time}) + expected = if expected_lock_time + { + name: LOCK_TIME, + value: expected_lock_time, + exists: true + } else - item(resource_name).attributes.delete(LOCK_TIME) + {} end + + @sdb.delete_attributes( + domain_name: @domain_name, + item_name: resource_name, + expected: expected + ) true - rescue AWS::SimpleDB::Errors::ConditionalCheckFailed + rescue ::Aws::SimpleDB::Errors::ConditionalCheckFailed false end # Locked time for resource_name # @return [Time] locked time, nil if it is not locked def locked_time(resource_name) - attribute = item(resource_name).attributes[LOCK_TIME] - lock_time_string = attribute.values.first - Time.at(lock_time_string.to_i) if lock_time_string + attributes = item(resource_name) + unless attributes.empty? + attributes.each do |a| + break Time.at(a.value.to_i) if a.name == LOCK_TIME + end + end end # All locked resources # # @param [Fixnum] age_in_seconds select resources older than this seconds @@ -115,11 +140,12 @@ if age_in_seconds cond = older_than(age_in_seconds) else cond = "`#{LOCK_TIME}` is not null" end - @domain.items.where(cond).map(&:name) + statement = "SELECT * FROM #{@domain_name} WHERE #{cond}" + @sdb.select(select_expression: statement).items.map { |i| i.name } end # Unlock old resources. # It is needed if any program failed to unlock by an unexpected exception # or network failure etc. @@ -128,21 +154,30 @@ # @return [Array<String>] unlocked resource names def unlock_old(age_in_seconds) targets = locked_resources(age_in_seconds) unlocked = [] targets.each do |resource_name| - values = item(resource_name).attributes[LOCK_TIME].values - next if !values || !values.first || values.first > format_time(Time.now - age_in_seconds) - succ = unlock(resource_name, values.first) + value = item(resource_name).each do |attribute| + break attribute.value if attribute.name == LOCK_TIME + end + next if !value || value > format_time(Time.now - age_in_seconds) + succ = unlock(resource_name, value) unlocked << resource_name if succ end unlocked end private + def domains + @domains ||= @sdb.list_domains.domain_names + end + def item(resource_name) - @domain.items[resource_name] + @sdb.get_attributes( + domain_name: @domain_name, + item_name: resource_name + ).attributes end # Format time to compare lexicographically def format_time(time) # 12 digits is enough until year 9999