Class: Xfers::Etcd::Mutex

Inherits:
Object
  • Object
show all
Defined in:
lib/xfers/etcd/mutex.rb

Overview

Mutex class for distributed lock

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, ttl: 60, conn: nil) ⇒ Xfers::Etcd::Mutex

Create a new mutex instance

Parameters:

  • name (String)

    the mutex name. The mutex instance with the same name will be treat as indivisual mutex which try to lock the same resource.

  • ttl (Integer) (defaults to: 60)

    the time-to-live in seconds of this mutex when mutex lock perform, the lock will be released after this time elapses, unless refreshed.



18
19
20
21
22
23
24
25
26
# File 'lib/xfers/etcd/mutex.rb', line 18

def initialize(name, ttl: 60, conn: nil)
  Xfers::Etcd::Client.valid_string_argument?("name", name)
  @key = "/etcd_mutex/#{name}"
  @lease_id = nil
  @ttl = ttl
  @revision = -1
  @conn = conn
  @uuid = SecureRandom.uuid
end

Instance Attribute Details

#keyObject (readonly)

Returns the value of attribute key.



8
9
10
# File 'lib/xfers/etcd/mutex.rb', line 8

def key
  @key
end

#uuidObject (readonly)

Returns the value of attribute uuid.



8
9
10
# File 'lib/xfers/etcd/mutex.rb', line 8

def uuid
  @uuid
end

Instance Method Details

#destroy!Boolean

Force destroy the lock key

Returns:

  • (Boolean)

    true if the lock key destroyed, false otherwise



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/xfers/etcd/mutex.rb', line 144

def destroy!
  @conn.synchronize do |conn|
    response = conn.transaction do |txn|
      txn.compare = [
        txn.version(@key, :greater, 0)
      ]

      txn.success = [
        txn.del(@key)
      ]

      txn.failure = []
    end
    response.succeeded
  end
end

#lock(timeout = 10) {|mutex| ... } ⇒ Boolean

Acquire the lock

Parameters:

  • timeout (Integer) (defaults to: 10)

    Maximum time in seconds to wait before returning. 0 means return immediately if lock fail, and < 0 means wait forever.

Yield Parameters:

Returns:

  • (Boolean)

    true if the lock has been acquired, false otherwise



36
37
38
# File 'lib/xfers/etcd/mutex.rb', line 36

def lock(timeout = 10, &block)
  lock_impl(false, timeout, &block)
end

#lock!(timeout = 10) {|mutex| ... }

This method returns an undefined value.

Acquire the lock, and raise error when failed to acquire/relase lock

Parameters:

  • timeout (Integer) (defaults to: 10)

    Maximum time in seconds to wait before returning. 0 means return immediately if lock fail, and < 0 means wait forever.

Yield Parameters:

Raises:

  • (Xfers::Etcd::LockError)

    if timeout or failed to acquire lock

  • (Xfers::Etcd::UnockError)

    if failed to release lock



51
52
53
# File 'lib/xfers/etcd/mutex.rb', line 51

def lock!(timeout = 10, &block)
  lock_impl(true, timeout, &block)
end

#lock_exist?Boolean

Check if this lock already existed

Returns:

  • (Boolean)

    true if the lock existed, false otherwise



185
186
187
188
189
# File 'lib/xfers/etcd/mutex.rb', line 185

def lock_exist?
  @conn.synchronize do |conn|
    conn.get(@key, { count_only: true }).count > 0
  end
end

#locked?Boolean

Check if this lock is currently acquired

Returns:

  • (Boolean)

    true if the lock has been acquired, false otherwise



174
175
176
177
178
179
180
# File 'lib/xfers/etcd/mutex.rb', line 174

def locked?
  @conn.synchronize do |conn|
    kv = conn.get(@key)
    return true if kv && kv.value == @uuid
    false
  end
end

#refreshInteger

Refresh the time-to-live on this lock

Returns:

  • (Integer)

    the remaining TTL in seconds of this lock



164
165
166
167
168
169
# File 'lib/xfers/etcd/mutex.rb', line 164

def refresh
  @conn.synchronize do |conn|
    raise NameError, "No lease associated with this lock" unless @lease_id
    conn.lease_keep_alive_once(@lease_id)
  end
end

#try_lock {|mutex| ... } ⇒ Boolean

Try to acquire the lock, and return false immediately when failed to acquire/relase lock

Yield Parameters:

Returns:

  • (Boolean)

    true if the lock has been acquired, false otherwise



60
61
62
# File 'lib/xfers/etcd/mutex.rb', line 60

def try_lock(&block)
  lock_impl(false, 0, &block)
end

#try_lock! {|mutex| ... }

This method returns an undefined value.

Try to acquire the lock and raise error immediately when failed to acquire/relase lock

Yield Parameters:

Raises:

  • (Xfers::Etcd::LockError)

    if failed to acquire lock

  • (Xfers::Etcd::UnockError)

    when failed to release lock



72
73
74
# File 'lib/xfers/etcd/mutex.rb', line 72

def try_lock!(&block)
  lock_impl(true, 0, &block)
end

#unlockBoolean

Release the lock

Returns:

  • (Boolean)

    lock released success or not



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/xfers/etcd/mutex.rb', line 125

def unlock
  @conn.synchronize do |conn|
    response = conn.transaction do |txn|
      txn.compare = [
        txn.value(@key, :equal, @uuid)
      ]

      txn.success = [
        txn.del(@key)
      ]

      txn.failure = []
    end
    response.succeeded
  end
end