Class: WorkerPlugins::SwitchQuery

Inherits:
ApplicationService show all
Defined in:
app/services/worker_plugins/switch_query.rb

Instance Method Summary collapse

Methods inherited from ApplicationService

#db_now_value, #mysql?, #postgres?, #quote, #quote_column, #quote_table, #sqlite?

Instance Method Details

#any_unlinked_candidate?Boolean

Returns:

  • (Boolean)


22
23
24
25
26
27
28
29
30
# File 'app/services/worker_plugins/switch_query.rb', line 22

def any_unlinked_candidate?
  add_service = WorkerPlugins::AddQuery.new(query:, workplace:)

  add_service
    .query
    .distinct
    .where("NOT EXISTS (#{add_service.existing_workplace_link_exists_sql})")
    .exists?
end

#performObject



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'app/services/worker_plugins/switch_query.rb', line 4

def perform
  # Decide mode *before* running the insert. Deciding it from AddQuery's
  # post-insert `affected_count` would make concurrent "add" toggles
  # destructive: if request A's INSERT commits first, overlapping
  # request B would see `affected_count == 0` from its own (no-op)
  # INSERT and flip to RemoveQuery, wiping out what A just added. A
  # pre-insert EXISTS probe keeps the race window small in the same
  # way the previous candidate-pluck approach did, without materializing
  # any ids into Ruby.
  if any_unlinked_candidate?
    add_result = WorkerPlugins::AddQuery.execute!(query:, workplace:)
    succeed!(affected_count: add_result.fetch(:affected_count), mode: :created)
  else
    remove_result = WorkerPlugins::RemoveQuery.execute!(query:, workplace:)
    succeed!(affected_count: remove_result.fetch(:affected_count), mode: :destroyed)
  end
end