Module: Async::Background::Web::SQL

Defined in:
lib/async/background/web/sql.rb

Constant Summary collapse

BEGIN_READ_TRANSACTION =
'BEGIN'.freeze
COMMIT =
'COMMIT'.freeze
ROLLBACK =
'ROLLBACK'.freeze
QUERY_ONLY =
'PRAGMA query_only = ON'.freeze
BUSY_TIMEOUT =
'PRAGMA busy_timeout = 2000'.freeze
BASE_COLUMNS =
%w[id class_name args options].freeze
STATUS_PREDICATE =
{
  executing: "status = 'running' AND started_at IS NOT NULL",
  claimed: "status = 'running' AND started_at IS NULL",
  pending: "status = 'pending'",
  done: "status = 'done'",
  failed: "status = 'failed'"
}.freeze
EXTRA_COLUMNS =
{
  executing: %w[started_at locked_by locked_at],
  claimed: %w[locked_at locked_by],
  pending: %w[created_at run_at],
  done: %w[finished_at duration_ms],
  failed: %w[finished_at duration_ms last_error_class last_error_message]
}.freeze
KEYSET =
{
  executing: ['started_at', :asc],
  claimed: ['locked_at', :asc],
  pending: ['run_at', :asc],
  done: ['finished_at', :desc],
  failed: ['finished_at', :desc]
}.freeze
ORDER_SQL =
{asc: 'ORDER BY %<column>s, id', desc: 'ORDER BY %<column>s DESC, id DESC'}.freeze
SEEK_SQL =
{asc: '(%<column>s, id) > (?, ?)', desc: '(%<column>s, id) < (?, ?)'}.freeze
OVERVIEW_EXECUTING =
count_query(:executing)
OVERVIEW_CLAIMED =
count_query(:claimed)
OVERVIEW_PENDING =
count_query(:pending)
OVERVIEW_DONE =
count_query(:done)
OVERVIEW_FAILED =
count_query(:failed)
OVERVIEW_NEXT_PENDING =
"SELECT MIN(run_at) FROM jobs WHERE #{STATUS_PREDICATE.fetch(:pending)}".freeze
EXECUTING =
list_query(:executing)
CLAIMED =
list_query(:claimed)
DONE =
list_query(:done)
FAILED =
list_query(:failed)
PENDING =
list_query(:pending)
DONE_AFTER =
list_query(:done, seek: true)
FAILED_AFTER =
list_query(:failed, seek: true)
PENDING_AFTER =
list_query(:pending, seek: true)

Class Method Summary collapse

Class Method Details

.columns_for(status) ⇒ Object



41
42
43
# File 'lib/async/background/web/sql.rb', line 41

def self.columns_for(status)
  (BASE_COLUMNS + EXTRA_COLUMNS.fetch(status)).join(', ')
end

.count_query(status) ⇒ Object



45
46
47
# File 'lib/async/background/web/sql.rb', line 45

def self.count_query(status)
  "SELECT COUNT(*) FROM jobs WHERE #{STATUS_PREDICATE.fetch(status)}".freeze
end

.list_query(status, seek: false) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/async/background/web/sql.rb', line 49

def self.list_query(status, seek: false)
  column, direction = KEYSET.fetch(status)
  predicate = STATUS_PREDICATE.fetch(status)
  predicate += " AND #{format(SEEK_SQL.fetch(direction), column: column)}" if seek

  <<~SQL.freeze
    SELECT #{columns_for(status)}
    FROM jobs
    WHERE #{predicate}
    #{format(ORDER_SQL.fetch(direction), column: column)}
    LIMIT ?
  SQL
end