Module: ZK::Mongoid::Locking
- Defined in:
- lib/zk/mongoid.rb
Overview
provides a lock_for_update method based on the current class name and Mongoid document _id.
Before use (in one of your Rails initializers, for example) you should assign either a ZK::Client or ZK::Pool subclass to ZK::Mongoid::Locking.zk_lock_pool.
this class assumes the availability of a 'logger' method in the mixee
Constant Summary collapse
- VALID_MODES =
[:exclusive, :shared].freeze
- @@zk_lock_pool =
nil
Class Method Summary collapse
Instance Method Summary collapse
-
#assert_locked_for_share!(name = nil) ⇒ Object
raises MustBeShareLockedException if we're not currently inside a shared lock (optionally with +name+).
-
#assert_locked_for_update!(name = nil) ⇒ Object
raises MustBeExclusivelyLockedException if we're not currently inside a lock (optionally with +name+).
-
#lock_for_update(name = nil) ⇒ Object
(also: #with_exclusive_lock)
Provides a re-entrant zookeeper-based lock of a record.
-
#locked_for_share?(name = nil) ⇒ Boolean
:nodoc:.
-
#locked_for_update?(name = nil) ⇒ Boolean
:nodoc:.
- #with_shared_lock(name = nil) ⇒ Object
-
#zk_lock_name(name = nil) ⇒ Object
:nodoc:.
Class Method Details
.zk_lock_pool ⇒ Object
17 18 19 |
# File 'lib/zk/mongoid.rb', line 17 def self.zk_lock_pool @@zk_lock_pool end |
.zk_lock_pool=(pool) ⇒ Object
21 22 23 |
# File 'lib/zk/mongoid.rb', line 21 def self.zk_lock_pool=(pool) @@zk_lock_pool = pool end |
Instance Method Details
#assert_locked_for_share!(name = nil) ⇒ Object
raises MustBeShareLockedException if we're not currently inside a shared lock (optionally with +name+)
100 101 102 |
# File 'lib/zk/mongoid.rb', line 100 def assert_locked_for_share!(name=nil) raise ZK::Exceptions::MustBeShareLockedException unless locked_for_share?(name) end |
#assert_locked_for_update!(name = nil) ⇒ Object
raises MustBeExclusivelyLockedException if we're not currently inside a lock (optionally with +name+)
94 95 96 |
# File 'lib/zk/mongoid.rb', line 94 def assert_locked_for_update!(name=nil) raise ZK::Exceptions::MustBeExclusivelyLockedException unless locked_for_update?(name) end |
#lock_for_update(name = nil) ⇒ Object Also known as: with_exclusive_lock
Provides a re-entrant zookeeper-based lock of a record.
This also makes it possible to detect if the record has been locked before performing a potentially dangerous operation by using the assert_locked_for_update! instance method
Locks are re-entrant per-thread, but will work as a mutex between threads.
You can optionally provide a 'name' which will act as a sub-lock of sorts. For example, if you are going to create an embedded document, and only want one process to be able to create it at a time (without clobbering one another), but don't want to lock the entire record, you can specify a name for the lock, that way the same code running elsewhere will synchronize based on the parent record and the particular action specified by +name+.
==== Example
use of "name"
class Thing include Mongoid::Document include ZK::Mongoid::Locking
:parent, :inverse_of => :thing
end
class Parent include Mongoid::Document include ZK::Mongoid::Locking
:thing
def lets_create_a_thing
lock_for_update('thing_creation') do
raise "We already got one! it's very nice!" if thing
do_something_that_might_take_a_while
create_thing
end
end
end
Now, while the creation of the Thing is synchronized, other processes can update other aspects of Parent.
74 75 76 77 78 79 80 81 |
# File 'lib/zk/mongoid.rb', line 74 def lock_for_update(name=nil) if locked_for_update?(name) logger.debug { "we are locked for update, yield to the block" } yield else zk_with_lock(:mode => :exclusive, :name => name) { yield } end end |
#locked_for_share?(name = nil) ⇒ Boolean
:nodoc:
108 109 110 |
# File 'lib/zk/mongoid.rb', line 108 def locked_for_share?(name=nil) #:nodoc: zk_mongoid_lock_registry[:shared].include?(zk_lock_name(name)) end |
#locked_for_update?(name = nil) ⇒ Boolean
:nodoc:
104 105 106 |
# File 'lib/zk/mongoid.rb', line 104 def locked_for_update?(name=nil) #:nodoc: zk_mongoid_lock_registry[:exclusive].include?(zk_lock_name(name)) end |
#with_shared_lock(name = nil) ⇒ Object
84 85 86 87 88 89 90 |
# File 'lib/zk/mongoid.rb', line 84 def with_shared_lock(name=nil) if locked_for_share?(name) yield else zk_with_lock(:mode => :shared, :name => name) { yield } end end |
#zk_lock_name(name = nil) ⇒ Object
:nodoc:
112 113 114 |
# File 'lib/zk/mongoid.rb', line 112 def zk_lock_name(name=nil) #:nodoc: [self.class.to_s, self.id.to_s, name].compact.join('-') end |