Class: Familia::Lock
- Defined in:
- lib/familia/data_type/types/lock.rb
Instance Attribute Summary collapse
-
#features_enabled ⇒ Object
included
from Features
readonly
Returns the value of attribute features_enabled.
- #logical_database(val = nil) ⇒ Object included from DataType::ClassMethods
-
#parent ⇒ Object
included
from DataType::ClassMethods
Returns the value of attribute parent.
-
#prefix ⇒ Object
included
from DataType::ClassMethods
Returns the value of attribute prefix.
-
#suffix ⇒ Object
included
from DataType::ClassMethods
Returns the value of attribute suffix.
-
#uri(val = nil) ⇒ Object
included
from DataType::ClassMethods
Returns the value of attribute uri.
Attributes included from Settings
#current_key_version, #default_expiration, #delim, #encryption_hkdf_salt, #encryption_hkdf_salt_history, #encryption_keys, #encryption_personalization, #encryption_personalization_history, #logical_database, #prefix, #raise_on_unsaved_parent_write, #schema_path, #schema_validator, #schemas, #strict_write_order, #suffix, #transaction_mode
Instance Method Summary collapse
-
#acquire(token = nil, ttl: 10) ⇒ String, false
Acquire a lock with optional TTL.
- #force_unlock! ⇒ Object
- #held_by?(token) ⇒ Boolean
-
#initialize(*args) ⇒ Lock
constructor
A new instance of Lock.
- #locked? ⇒ Boolean
- #release(token) ⇒ Object
Methods included from DataType::ScalarBase
Methods included from Features::Autoloader
autoload_files, included, normalize_to_config_name
Methods included from DataType::Serialization
#deserialize_value, #deserialize_values, #deserialize_values_with_nil, #serialize_value, #strip_legacy_json_encoding
Methods included from DataType::DatabaseCommands
#current_expiration, #delete!, #echo, #exists?, #expire, #expireat, #move, #persist, #rename, #renamenx, #type
Methods included from DataType::Connection
Methods included from Connection::Behavior
#connect, #create_dbclient, #multi, #normalize_uri, #pipeline, #pipelined, #transaction, #uri=, #url, #url=
Methods included from Settings
#configure, #default_suffix, #dirty_write_warnings, #dirty_write_warnings=, #pipelined_mode, #pipelined_mode=
Methods included from Base
add_feature, #as_json, #expired?, #expires?, find_feature, #generate_id, #to_json, #to_s, #ttl, #update_expiration, #uuid
Constructor Details
#initialize(*args) ⇒ Lock
Returns a new instance of Lock.
7 8 9 10 |
# File 'lib/familia/data_type/types/lock.rb', line 7 def initialize(*args) super @opts[:default] = nil end |
Instance Attribute Details
#features_enabled ⇒ Object (readonly) Originally defined in module Features
Returns the value of attribute features_enabled.
#logical_database(val = nil) ⇒ Object Originally defined in module DataType::ClassMethods
#parent ⇒ Object Originally defined in module DataType::ClassMethods
Returns the value of attribute parent.
#prefix ⇒ Object Originally defined in module DataType::ClassMethods
Returns the value of attribute prefix.
#suffix ⇒ Object Originally defined in module DataType::ClassMethods
Returns the value of attribute suffix.
#uri(val = nil) ⇒ Object Originally defined in module DataType::ClassMethods
Returns the value of attribute uri.
Instance Method Details
#acquire(token = nil, ttl: 10) ⇒ String, false
Acquire a lock with optional TTL
With a positive ttl this is a single atomic SET NX EX command, so the value and its expiry land together -- a crash can never strand a permanent TTL-less lock (previously SETNX followed by EXPIRE).
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/familia/data_type/types/lock.rb', line 25 def acquire(token = nil, ttl: 10) if Fiber[:familia_transaction] || Fiber[:familia_pipeline] raise Familia::OperationModeError, 'Lock#acquire cannot run inside a transaction or pipeline: ' \ 'the NX verdict resolves at EXEC, after the caller has already ' \ 'proceeded. Acquire the lock outside the block.' end # An explicitly passed nil would serialize to "" -- honor the documented # auto-generation contract instead. token ||= SecureRandom.uuid # Reject invalid TTLs before touching the server return false if ttl&.<=(0) if ttl # redis-rb returns true/false for SET with NX (BoolifySet). Token goes # through serialize_value so held_by?/release comparisons stay # consistent (identity for plain strings). return dbclient.set(dbkey, serialize_value(token), nx: true, ex: ttl) ? token : false end # nil TTL: setnx applies the :expiration feature's default TTL via # update_expiration when present; otherwise the key stays TTL-less. success = setnx(token) # Handle both integer (1/0) and boolean (true/false) return values [1, true].include?(success) ? token : false end |
#force_unlock! ⇒ Object
68 69 70 |
# File 'lib/familia/data_type/types/lock.rb', line 68 def force_unlock! del end |
#held_by?(token) ⇒ Boolean
64 65 66 |
# File 'lib/familia/data_type/types/lock.rb', line 64 def held_by?(token) value == token end |
#locked? ⇒ Boolean
60 61 62 |
# File 'lib/familia/data_type/types/lock.rb', line 60 def locked? !value.nil? end |
#release(token) ⇒ Object
54 55 56 57 58 |
# File 'lib/familia/data_type/types/lock.rb', line 54 def release(token) # Lua script to atomically check token and delete script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" dbclient.eval(script, [dbkey], [token]) == 1 end |