Class: Flightdeck::JobsQuery
- Inherits:
-
Object
- Object
- Flightdeck::JobsQuery
- Defined in:
- app/models/flightdeck/jobs_query.rb
Overview
Builds every jobs list in Flightdeck.
Rule zero: everything goes through SolidQueue's own models, so multi-database routing comes for free and the host's connection is never touched.
Two shapes of query, chosen by state:
* an execution-backed state drives from its own table (that is what makes
the state true) and then loads the matching jobs;
* "all" and "finished" drive from solid_queue_jobs and have their state
annotated afterwards.
The arguments and error columns are never in a list's driving query.
Both are fetched afterwards for the current page only, and truncated in SQL
so a page of pathological payloads still costs a bounded number of bytes.
Defined Under Namespace
Classes: InvalidState
Constant Summary collapse
- STATES =
%i[all ready scheduled in_progress blocked finished failed].freeze
- ARGUMENTS_PREVIEW_BYTES =
Enough that the ActiveJob envelope (job_class, job_id, queue_name…) is comfortably past and the arguments themselves are in the prefix.
800- ERROR_PREVIEW_BYTES =
1_000
Instance Attribute Summary collapse
-
#before_id ⇒ Object
readonly
Returns the value of attribute before_id.
-
#class_name ⇒ Object
readonly
Returns the value of attribute class_name.
-
#count_cap ⇒ Object
readonly
Returns the value of attribute count_cap.
-
#limit ⇒ Object
readonly
Returns the value of attribute limit.
-
#q ⇒ Object
readonly
Returns the value of attribute q.
-
#queue_name ⇒ Object
readonly
Returns the value of attribute queue_name.
-
#state ⇒ Object
readonly
Returns the value of attribute state.
Class Method Summary collapse
-
.state_counts(**filters) ⇒ Object
Counts for the state tabs, each capped independently.
Instance Method Summary collapse
-
#count ⇒ Object
Capped so that a jobs table with tens of millions of rows cannot turn a page render into a full scan.
- #count_capped? ⇒ Boolean
- #execution_backed? ⇒ Boolean
-
#filtered_relation ⇒ Object
The filtered relation with no ordering, limit or cursor — what bulk "apply to all matching" re-runs server-side.
- #filters? ⇒ Boolean
-
#initialize(state: :all, class_name: nil, queue_name: nil, q: nil, before_id: nil, limit: nil, count_cap: nil) ⇒ JobsQuery
constructor
A new instance of JobsQuery.
- #model ⇒ Object
- #next_cursor ⇒ Object
- #next_page? ⇒ Boolean
- #rows ⇒ Object
Constructor Details
#initialize(state: :all, class_name: nil, queue_name: nil, q: nil, before_id: nil, limit: nil, count_cap: nil) ⇒ JobsQuery
Returns a new instance of JobsQuery.
30 31 32 33 34 35 36 37 38 39 |
# File 'app/models/flightdeck/jobs_query.rb', line 30 def initialize(state: :all, class_name: nil, queue_name: nil, q: nil, before_id: nil, limit: nil, count_cap: nil) @state = normalize_state(state) @class_name = class_name.presence @queue_name = queue_name.presence @q = q.presence @before_id = before_id.presence && Integer(before_id, exception: false) @limit = (limit || Flightdeck.config.per_page).to_i.clamp(1, 200) @count_cap = (count_cap || Flightdeck.config.count_cap).to_i end |
Instance Attribute Details
#before_id ⇒ Object (readonly)
Returns the value of attribute before_id.
28 29 30 |
# File 'app/models/flightdeck/jobs_query.rb', line 28 def before_id @before_id end |
#class_name ⇒ Object (readonly)
Returns the value of attribute class_name.
28 29 30 |
# File 'app/models/flightdeck/jobs_query.rb', line 28 def class_name @class_name end |
#count_cap ⇒ Object (readonly)
Returns the value of attribute count_cap.
28 29 30 |
# File 'app/models/flightdeck/jobs_query.rb', line 28 def count_cap @count_cap end |
#limit ⇒ Object (readonly)
Returns the value of attribute limit.
28 29 30 |
# File 'app/models/flightdeck/jobs_query.rb', line 28 def limit @limit end |
#q ⇒ Object (readonly)
Returns the value of attribute q.
28 29 30 |
# File 'app/models/flightdeck/jobs_query.rb', line 28 def q @q end |
#queue_name ⇒ Object (readonly)
Returns the value of attribute queue_name.
28 29 30 |
# File 'app/models/flightdeck/jobs_query.rb', line 28 def queue_name @queue_name end |
#state ⇒ Object (readonly)
Returns the value of attribute state.
28 29 30 |
# File 'app/models/flightdeck/jobs_query.rb', line 28 def state @state end |
Class Method Details
.state_counts(**filters) ⇒ Object
Counts for the state tabs, each capped independently.
85 86 87 88 89 90 |
# File 'app/models/flightdeck/jobs_query.rb', line 85 def self.state_counts(**filters) STATES.index_with do |state| query = new(**filters.except(:state, :before_id), state: state) { count: query.count, capped: query.count_capped? } end end |
Instance Method Details
#count ⇒ Object
Capped so that a jobs table with tens of millions of rows cannot turn a
page render into a full scan. Views render count_capped? as "500,000+".
Cached for one poll interval: the state tabs and the sidebar issue several of these per render, and a count that is at most one poll stale is exactly as fresh as the page it appears on. Mutations wrap themselves in Cache.bypass so an action's own response never shows pre-action numbers.
59 60 61 62 63 64 |
# File 'app/models/flightdeck/jobs_query.rb', line 59 def count @count ||= Flightdeck::Cache.fetch("count", state, count_cap, cache_filters, expires_in: Flightdeck.config.poll_interval) do filtered_relation.limit(count_cap).count end end |
#count_capped? ⇒ Boolean
66 |
# File 'app/models/flightdeck/jobs_query.rb', line 66 def count_capped? = count >= count_cap |
#execution_backed? ⇒ Boolean
82 |
# File 'app/models/flightdeck/jobs_query.rb', line 82 def execution_backed? = model != SolidQueue::Job |
#filtered_relation ⇒ Object
The filtered relation with no ordering, limit or cursor — what bulk "apply to all matching" re-runs server-side.
74 75 76 |
# File 'app/models/flightdeck/jobs_query.rb', line 74 def filtered_relation @filtered_relation ||= apply_filters(model.all) end |
#filters? ⇒ Boolean
68 69 70 |
# File 'app/models/flightdeck/jobs_query.rb', line 68 def filters? class_name.present? || queue_name.present? || q.present? end |
#model ⇒ Object
78 79 80 |
# File 'app/models/flightdeck/jobs_query.rb', line 78 def model @model ||= JobRow.model_for(state) || SolidQueue::Job end |
#next_cursor ⇒ Object
45 46 47 48 |
# File 'app/models/flightdeck/jobs_query.rb', line 45 def next_cursor rows @next_cursor end |
#next_page? ⇒ Boolean
50 |
# File 'app/models/flightdeck/jobs_query.rb', line 50 def next_page? = next_cursor.present? |
#rows ⇒ Object
41 42 43 |
# File 'app/models/flightdeck/jobs_query.rb', line 41 def rows @rows ||= build_rows end |