Class: ForemanTasks::Lock

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/foreman_tasks/lock.rb

Defined Under Namespace

Classes: LockConflict

Constant Summary collapse

:link_resource
OWNER_LOCK_NAME =
:task_owner
ALL_LOCK_NAME =

not really intedet to be created in database, but it’s used for explicitly stating that the all the locks for resource should be used

:all
RESERVED_LOCK_NAMES =
[LINK_LOCK_NAME, OWNER_LOCK_NAME, ALL_LOCK_NAME]

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.colliding_locks(resource, uuid, *lock_names) ⇒ Object



109
110
111
112
# File 'app/models/foreman_tasks/lock.rb', line 109

def colliding_locks(resource, uuid, *lock_names)
  build_locks(resource, lock_names, uuid).
      inject([]) { |collisions, lock| collisions.concat lock.colliding_locks.to_a }
end

.exclusive!(resource, uuid) ⇒ Object

Locks the resource so that no other task can lock it while running. No other task related to the resource is not allowed (even not-locking ones) A typical usecase is resource deletion, where it’s good idea to make sure nothing else related to the resource is really running.



77
78
79
# File 'app/models/foreman_tasks/lock.rb', line 77

def exclusive!(resource, uuid)
  build_exclusive_locks(resource, uuid).each(&:save!)
end

.exclusive?(resource) ⇒ Boolean

Returns:

  • (Boolean)


81
82
83
# File 'app/models/foreman_tasks/lock.rb', line 81

def exclusive?(resource)
  build_exclusive_locks(resource).all?(&:available?)
end

.link!(resource, uuid) ⇒ Object

Assigns the resource to the task to easily track the task in context of the resource. This doesn’t prevent other actions to lock the resource and should be used only for actions that tolerate other actions to be performed on the resource. Usually, this shouldn’t needed to be done through the action directly, because the lock should assign it’s parrent objects to the action srecursively (using related_resources method in model objects)



121
122
123
# File 'app/models/foreman_tasks/lock.rb', line 121

def link!(resource, uuid)
  build_link(resource, uuid).save!
end

.link?(resource, uuid) ⇒ Boolean

Returns:

  • (Boolean)


125
126
127
# File 'app/models/foreman_tasks/lock.rb', line 125

def link?(resource, uuid)
  build_link(resource, uuid).available?
end

.lock!(resource, uuid, *lock_names) ⇒ Object

Locks the resource so that no other task can lock it while running. Other not-locking tasks are tolerated.

The lock names allow to specify what locks should be activated. It has to be a subset of names defined in model’s class available_locks method

When no lock name is specified, the resource is locked against all the available locks.

It also looks at related_resources method of the resource to calcuate all the related resources (recursively) and links the task to them as well.



97
98
99
# File 'app/models/foreman_tasks/lock.rb', line 97

def lock!(resource, uuid, *lock_names)
  build_locks(resource, lock_names, uuid).each(&:save!)
end

.lockable?(resource, uuid, *lock_names) ⇒ Boolean

Returns:

  • (Boolean)


101
102
103
# File 'app/models/foreman_tasks/lock.rb', line 101

def lockable?(resource, uuid, *lock_names)
  build_locks(resource, lock_names, uuid).all?(&:available?)
end

.locked?(resource, uuid, *lock_names) ⇒ Boolean

Returns:

  • (Boolean)


105
106
107
# File 'app/models/foreman_tasks/lock.rb', line 105

def locked?(resource, uuid, *lock_names)
  not lockable?(resource, uuid, *lock_names)
end

.owner!(user, uuid) ⇒ Object

Records the information about the user that triggered the task



130
131
132
# File 'app/models/foreman_tasks/lock.rb', line 130

def owner!(user, uuid)
  build_owner(user, uuid).save!
end

Instance Method Details

#available?Boolean

returns true if it’s possible to aquire this kind of lock

Returns:

  • (Boolean)


54
55
56
# File 'app/models/foreman_tasks/lock.rb', line 54

def available?
  not colliding_locks.any?
end

#colliding_locksObject

returns a scope of the locks colliding with this one



59
60
61
62
63
64
65
66
67
68
69
# File 'app/models/foreman_tasks/lock.rb', line 59

def colliding_locks
  task_ids = task.self_and_parents.map(&:id)
  colliding_locks_scope = Lock.active.where(Lock.arel_table[:task_id].not_in(task_ids))
  colliding_locks_scope = colliding_locks_scope.where(name:          name,
                                                      resource_id:   resource_id,
                                                      resource_type: resource_type)
  unless self.exclusive?
    colliding_locks_scope = colliding_locks_scope.where(:exclusive => true)
  end
  return colliding_locks_scope
end