Method: Simple::SQL::Connection#lock!

Defined in:
lib/simple/sql/connection/lock.rb

#lock!(key, key2 = nil, timeout: nil) ⇒ Object

Acquire an advisory lock.

This uses the pg_*_xact_lock locks - that once acquired, cannot be released, but will release automatically once the transaction ends. This is safer than the pg_advisory_lock group of functions.

For ease of use the key argument can also be a string - in which case we use a hash function to derive a key value. Usage example:

Simple::SQL.lock! "products", 12
Simple::SQL.ask "UPDATE products SET ... WHERE id=12"

Note that passing in a timeout value sets timeouts for all lock! invocations in this transaction.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/simple/sql/connection/lock.rb', line 41

def lock!(key, key2 = nil, timeout: nil)
  unless in_transaction?
    raise "You cannot use lock! outside of a transaction"
  end

  if key.is_a?(String)
    # calculate a 31 bit checksum < 0
    key = Digest::CRC32.hexdigest(key).to_i(16) # get a 32-bit stable checksum
    key &= ~0x80000000 # reset bit 31
    key = -key # make it negative
  end

  # shorten key, key2 to the allowed number of bits
  if key2
    key  = apply_bitmask(key, MASK_31_BITS)
    key2 = apply_bitmask(key2, MASK_31_BITS)
  else
    key  = apply_bitmask(key, MASK_63_BITS)
  end

  if timeout
    lock_w_timeout(key, key2, timeout)
  else
    lock_wo_timeout(key, key2)
  end
end