Previously, it would usually use 2 queries if inside a transaction, or 4 queries if outside a transaction. This replaces the UPDATE then INSERT query approach with an INSERT SELECT (UPDATE RETURNING) approach in a single query. As this is a single query and not multiple queries, it does not need a transaction. If the UPDATE does not update a row, then no rows will be inserted. This approach also opens up the ability to create multiple semaphores in a single query, if the first argument is an array or a dataset. That will be used in an upcoming commit. This changes the return value of Semaphore.incr when provided a single id from returning a Semaphore instance to returning the Semaphore uuid. Only SemSnap#incr cares about the return value, so update that to fetch the Semaphore.
58 lines
1.1 KiB
Ruby
58 lines
1.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class SemSnap
|
|
def initialize(strand_id, deferred: false)
|
|
@deferred = deferred
|
|
@strand_id = strand_id
|
|
@extant = Hash.new { |h, k| h[k.intern] = [] }
|
|
@defer_delete = []
|
|
|
|
Semaphore.where(strand_id: @strand_id).each do |sem|
|
|
add_semaphore_instance_to_snapshot(sem)
|
|
end
|
|
end
|
|
|
|
def self.use(strand_id)
|
|
new(strand_id, deferred: true).use do |snap|
|
|
yield snap
|
|
end
|
|
end
|
|
|
|
def use
|
|
yield self
|
|
ensure
|
|
apply
|
|
end
|
|
|
|
def set?(name)
|
|
name = name.intern
|
|
@extant.include?(name)
|
|
end
|
|
|
|
def decr(name)
|
|
name = name.intern
|
|
ids = @extant.delete(name)
|
|
return unless ids && ids.length > 0
|
|
@defer_delete.concat(ids)
|
|
apply unless @deferred
|
|
end
|
|
|
|
def incr(name)
|
|
if (semaphore = Semaphore.incr(@strand_id, name))
|
|
add_semaphore_instance_to_snapshot(Semaphore.with_pk(semaphore))
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def apply
|
|
return if @defer_delete.empty?
|
|
Semaphore.where(strand_id: @strand_id, id: @defer_delete).destroy
|
|
@defer_delete.clear
|
|
end
|
|
|
|
def add_semaphore_instance_to_snapshot(sem)
|
|
@extant[sem.name.intern] << sem.id
|
|
end
|
|
end
|