solid_queue_tui 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/exe/sqtui +20 -1
  3. data/lib/solid_queue_tui/actions/discard_job.rb +4 -21
  4. data/lib/solid_queue_tui/actions/discard_scheduled_job.rb +5 -21
  5. data/lib/solid_queue_tui/actions/dispatch_scheduled_job.rb +4 -23
  6. data/lib/solid_queue_tui/actions/enqueue_recurring_task.rb +12 -0
  7. data/lib/solid_queue_tui/actions/retry_job.rb +14 -59
  8. data/lib/solid_queue_tui/actions/toggle_queue_pause.rb +19 -0
  9. data/lib/solid_queue_tui/application.rb +73 -17
  10. data/lib/solid_queue_tui/cli.rb +15 -8
  11. data/lib/solid_queue_tui/components/header.rb +26 -27
  12. data/lib/solid_queue_tui/components/help_bar.rb +1 -0
  13. data/lib/solid_queue_tui/components/job_table.rb +14 -2
  14. data/lib/solid_queue_tui/data/failed_query.rb +37 -91
  15. data/lib/solid_queue_tui/data/jobs_query.rb +90 -123
  16. data/lib/solid_queue_tui/data/processes_query.rb +10 -34
  17. data/lib/solid_queue_tui/data/queues_query.rb +6 -15
  18. data/lib/solid_queue_tui/data/recurring_tasks_query.rb +36 -0
  19. data/lib/solid_queue_tui/data/stats.rb +9 -27
  20. data/lib/solid_queue_tui/railtie.rb +9 -0
  21. data/lib/solid_queue_tui/version.rb +1 -1
  22. data/lib/solid_queue_tui/views/blocked_view.rb +126 -46
  23. data/lib/solid_queue_tui/views/concerns/filterable.rb +128 -0
  24. data/lib/solid_queue_tui/views/dashboard_view.rb +2 -1
  25. data/lib/solid_queue_tui/views/failed_view.rb +62 -72
  26. data/lib/solid_queue_tui/views/finished_view.rb +54 -67
  27. data/lib/solid_queue_tui/views/in_progress_view.rb +124 -44
  28. data/lib/solid_queue_tui/views/queues_view.rb +119 -35
  29. data/lib/solid_queue_tui/views/recurring_tasks_view.rb +202 -0
  30. data/lib/solid_queue_tui/views/scheduled_view.rb +74 -8
  31. data/lib/solid_queue_tui.rb +15 -4
  32. data/lib/tasks/solid_queue_tui.rake +8 -0
  33. metadata +16 -24
  34. data/lib/solid_queue_tui/connection.rb +0 -58
@@ -0,0 +1,202 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidQueueTui
4
+ module Views
5
+ class RecurringTasksView
6
+ def initialize(tui)
7
+ @tui = tui
8
+ @table_state = RatatuiRuby::TableState.new(nil)
9
+ @table_state.select(0)
10
+ @selected_row = 0
11
+ @tasks = []
12
+ @confirm_action = nil
13
+ end
14
+
15
+ def update(tasks:)
16
+ @tasks = tasks
17
+ @selected_row = @selected_row.clamp(0, [@tasks.size - 1, 0].max)
18
+ @table_state.select(@selected_row)
19
+ end
20
+
21
+ def render(frame, area)
22
+ if @confirm_action
23
+ confirm_area, content_area = @tui.layout_split(
24
+ area,
25
+ direction: :vertical,
26
+ constraints: [
27
+ @tui.constraint_length(3),
28
+ @tui.constraint_fill(1)
29
+ ]
30
+ )
31
+ render_confirm(frame, confirm_area)
32
+ render_table(frame, content_area)
33
+ else
34
+ render_table(frame, area)
35
+ end
36
+ end
37
+
38
+ def handle_input(event)
39
+ if @confirm_action
40
+ handle_confirm_input(event)
41
+ else
42
+ handle_normal_input(event)
43
+ end
44
+ end
45
+
46
+ def selected_item
47
+ return nil if @tasks.empty? || @selected_row >= @tasks.size
48
+ @tasks[@selected_row]
49
+ end
50
+
51
+ def capturing_input?
52
+ !!@confirm_action
53
+ end
54
+
55
+ def bindings
56
+ if @confirm_action
57
+ [
58
+ { key: "y", action: "Confirm" },
59
+ { key: "n/Esc", action: "Cancel" }
60
+ ]
61
+ else
62
+ [
63
+ { key: "j/k", action: "Navigate" },
64
+ { key: "N", action: "Run Now" },
65
+ { key: "G/g", action: "Bottom/Top" }
66
+ ]
67
+ end
68
+ end
69
+
70
+ def breadcrumb = "recurring"
71
+
72
+ private
73
+
74
+ def handle_normal_input(event)
75
+ case event
76
+ in { type: :key, code: "j" } | { type: :key, code: "up" }
77
+ move_selection(-1)
78
+ in { type: :key, code: "k" } | { type: :key, code: "down" }
79
+ move_selection(1)
80
+ in { type: :key, code: "g" }
81
+ jump_to_top
82
+ in { type: :key, code: "G" }
83
+ jump_to_bottom
84
+ in { type: :key, code: "N" }
85
+ @confirm_action = :run_now if selected_item
86
+ nil
87
+ else
88
+ nil
89
+ end
90
+ end
91
+
92
+ def handle_confirm_input(event)
93
+ case event
94
+ in { type: :key, code: "y" }
95
+ @confirm_action = nil
96
+ task = selected_item
97
+ return nil unless task
98
+ Actions::EnqueueRecurringTask.call(task.key)
99
+ :refresh
100
+ in { type: :key, code: "n" } | { type: :key, code: "esc" }
101
+ @confirm_action = nil
102
+ nil
103
+ else
104
+ nil
105
+ end
106
+ end
107
+
108
+ def move_selection(delta)
109
+ return if @tasks.empty?
110
+ @selected_row = (@selected_row + delta).clamp(0, @tasks.size - 1)
111
+ @table_state.select(@selected_row)
112
+ end
113
+
114
+ def jump_to_top
115
+ @selected_row = 0
116
+ @table_state.select(0)
117
+ end
118
+
119
+ def jump_to_bottom
120
+ return if @tasks.empty?
121
+ @selected_row = @tasks.size - 1
122
+ @table_state.select(@selected_row)
123
+ end
124
+
125
+ def render_table(frame, area)
126
+ columns = [
127
+ { key: :key, label: "KEY", width: :fill },
128
+ { key: :class_name, label: "CLASS", width: :fill },
129
+ { key: :schedule, label: "SCHEDULE", width: 20 },
130
+ { key: :queue_name, label: "QUEUE", width: 14 },
131
+ { key: :last_enqueued_at, label: "LAST ENQUEUED", width: 20 },
132
+ { key: :next_time, label: "NEXT", width: 20 }
133
+ ]
134
+
135
+ rows = @tasks.map do |task|
136
+ {
137
+ key: task.key,
138
+ class_name: task.class_name || task.command || "n/a",
139
+ schedule: task.schedule,
140
+ queue_name: task.queue_name || "default",
141
+ last_enqueued_at: time_ago(task.last_enqueued_at),
142
+ next_time: time_until(task.next_time)
143
+ }
144
+ end
145
+
146
+ table = Components::JobTable.new(
147
+ @tui,
148
+ title: "Recurring Tasks",
149
+ columns: columns,
150
+ rows: rows,
151
+ selected_row: @selected_row,
152
+ empty_message: "No recurring tasks configured"
153
+ )
154
+
155
+ table.render(frame, area, @table_state)
156
+ end
157
+
158
+ def render_confirm(frame, area)
159
+ task = selected_item
160
+ message = "Run '#{task&.key}' (#{task&.class_name || task&.command}) now? [y/n]"
161
+
162
+ frame.render_widget(
163
+ @tui.paragraph(
164
+ text: " #{message}",
165
+ style: @tui.style(fg: :yellow, modifiers: [:bold]),
166
+ block: @tui.block(
167
+ title: " Confirm ",
168
+ title_style: @tui.style(fg: :red, modifiers: [:bold]),
169
+ borders: [:all],
170
+ border_type: :rounded,
171
+ border_style: @tui.style(fg: :red)
172
+ )
173
+ ),
174
+ area
175
+ )
176
+ end
177
+
178
+ def time_ago(time)
179
+ return "Never" unless time
180
+ seconds = (Time.now.utc - time).to_i
181
+ return "just now" if seconds < 5
182
+ "#{humanize_duration(seconds)} ago"
183
+ end
184
+
185
+ def time_until(time)
186
+ return "n/a" unless time
187
+ seconds = (time - Time.now.utc).to_i
188
+ return "now" if seconds <= 0
189
+ "in #{humanize_duration(seconds)}"
190
+ end
191
+
192
+ def humanize_duration(seconds)
193
+ case seconds.abs
194
+ when 0..59 then "#{seconds.abs}s"
195
+ when 60..3599 then "#{seconds.abs / 60}m"
196
+ when 3600..86399 then "#{seconds.abs / 3600}h"
197
+ else "#{seconds.abs / 86400}d"
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
@@ -3,33 +3,74 @@
3
3
  module SolidQueueTui
4
4
  module Views
5
5
  class ScheduledView
6
+ include Filterable
7
+
8
+
9
+ LOAD_THRESHOLD = 10
10
+
6
11
  def initialize(tui)
7
12
  @tui = tui
8
13
  @table_state = RatatuiRuby::TableState.new(nil)
9
14
  @table_state.select(0)
10
15
  @selected_row = 0
11
16
  @jobs = []
17
+ @total_count = nil
18
+ @all_loaded = false
12
19
  @confirm_action = nil
20
+ init_filter
13
21
  end
14
22
 
15
23
  def update(jobs:)
16
24
  @jobs = jobs
25
+ @all_loaded = jobs.size < SolidQueueTui.page_size
17
26
  @selected_row = @selected_row.clamp(0, [@jobs.size - 1, 0].max)
18
27
  @table_state.select(@selected_row)
19
28
  end
20
29
 
30
+ def append(jobs:)
31
+ @jobs.concat(jobs)
32
+ @all_loaded = jobs.size < SolidQueueTui.page_size
33
+ end
34
+
35
+ def total_count=(count)
36
+ @total_count = count
37
+ end
38
+
39
+ def current_offset
40
+ @jobs.size
41
+ end
42
+
43
+ def reset_pagination!
44
+ @jobs = []
45
+ @total_count = nil
46
+ @all_loaded = false
47
+ @selected_row = 0
48
+ @table_state.select(0)
49
+ end
50
+
21
51
  def render(frame, area)
22
52
  if @confirm_action
23
- content_area, confirm_area = @tui.layout_split(
53
+ confirm_area, content_area = @tui.layout_split(
24
54
  area,
25
55
  direction: :vertical,
26
56
  constraints: [
27
- @tui.constraint_fill(1),
28
- @tui.constraint_length(3)
57
+ @tui.constraint_length(3),
58
+ @tui.constraint_fill(1)
29
59
  ]
30
60
  )
31
- render_table(frame, content_area)
32
61
  render_confirm(frame, confirm_area)
62
+ render_table(frame, content_area)
63
+ elsif filter_mode?
64
+ filter_area, content_area = @tui.layout_split(
65
+ area,
66
+ direction: :vertical,
67
+ constraints: [
68
+ @tui.constraint_length(3),
69
+ @tui.constraint_fill(1)
70
+ ]
71
+ )
72
+ render_filter_input(frame, filter_area)
73
+ render_table(frame, content_area)
33
74
  else
34
75
  render_table(frame, area)
35
76
  end
@@ -38,6 +79,8 @@ module SolidQueueTui
38
79
  def handle_input(event)
39
80
  if @confirm_action
40
81
  handle_confirm_input(event)
82
+ elsif filter_mode?
83
+ handle_filter_input(event)
41
84
  else
42
85
  handle_normal_input(event)
43
86
  end
@@ -49,7 +92,7 @@ module SolidQueueTui
49
92
  end
50
93
 
51
94
  def capturing_input?
52
- !!@confirm_action
95
+ filter_mode? || @confirm_action
53
96
  end
54
97
 
55
98
  def bindings
@@ -58,10 +101,13 @@ module SolidQueueTui
58
101
  { key: "y", action: "Confirm" },
59
102
  { key: "n/Esc", action: "Cancel" }
60
103
  ]
104
+ elsif filter_mode?
105
+ filter_bindings
61
106
  else
62
107
  [
63
108
  { key: "j/k", action: "Navigate" },
64
109
  { key: "Enter", action: "Detail" },
110
+ { key: "/", action: "Filter" },
65
111
  { key: "N", action: "Run Now" },
66
112
  { key: "D", action: "Discard" },
67
113
  { key: "G/g", action: "Bottom/Top" }
@@ -69,16 +115,24 @@ module SolidQueueTui
69
115
  end
70
116
  end
71
117
 
72
- def breadcrumb = "scheduled"
118
+ def breadcrumb
119
+ @filters.empty? ? "scheduled" : "scheduled:filtered"
120
+ end
73
121
 
74
122
  private
75
123
 
124
+ def needs_more?
125
+ !@all_loaded && @selected_row >= @jobs.size - LOAD_THRESHOLD
126
+ end
127
+
76
128
  def handle_normal_input(event)
77
129
  case event
78
130
  in { type: :key, code: "j" } | { type: :key, code: "up" }
79
131
  move_selection(-1)
80
132
  in { type: :key, code: "k" } | { type: :key, code: "down" }
81
- move_selection(1)
133
+ result = move_selection(1)
134
+ return :load_more if result == :load_more
135
+ nil
82
136
  in { type: :key, code: "g" }
83
137
  jump_to_top
84
138
  in { type: :key, code: "G" }
@@ -89,6 +143,11 @@ module SolidQueueTui
89
143
  in { type: :key, code: "D" }
90
144
  @confirm_action = :discard if selected_item
91
145
  nil
146
+ in { type: :key, code: "/" }
147
+ enter_filter_mode
148
+ nil
149
+ in { type: :key, code: "esc" }
150
+ clear_filter
92
151
  else
93
152
  nil
94
153
  end
@@ -123,6 +182,7 @@ module SolidQueueTui
123
182
  return if @jobs.empty?
124
183
  @selected_row = (@selected_row + delta).clamp(0, @jobs.size - 1)
125
184
  @table_state.select(@selected_row)
185
+ :load_more if needs_more?
126
186
  end
127
187
 
128
188
  def jump_to_top
@@ -134,6 +194,7 @@ module SolidQueueTui
134
194
  return if @jobs.empty?
135
195
  @selected_row = @jobs.size - 1
136
196
  @table_state.select(@selected_row)
197
+ return :load_more if needs_more?
137
198
  end
138
199
 
139
200
  def render_table(frame, area)
@@ -143,26 +204,31 @@ module SolidQueueTui
143
204
  { key: :queue_name, label: "QUEUE", width: 14 },
144
205
  { key: :priority, label: "PRI", width: 5 },
145
206
  { key: :scheduled_at, label: "SCHEDULED AT", width: 20 },
207
+ { key: :status, label: "STATUS", width: 10, color_by: :status },
146
208
  { key: :created_at, label: "CREATED", width: 12 }
147
209
  ]
148
210
 
211
+ now = Time.now.utc
149
212
  rows = @jobs.map do |job|
213
+ delayed = job.scheduled_at && job.scheduled_at < now
150
214
  {
151
215
  id: job.id,
152
216
  class_name: job.class_name,
153
217
  queue_name: job.queue_name,
154
218
  priority: job.priority,
155
219
  scheduled_at: format_time(job.scheduled_at),
220
+ status: delayed ? "DELAYED" : "pending",
156
221
  created_at: time_ago(job.created_at)
157
222
  }
158
223
  end
159
224
 
160
225
  table = Components::JobTable.new(
161
226
  @tui,
162
- title: "Scheduled Jobs",
227
+ title: filter_title("Scheduled Jobs"),
163
228
  columns: columns,
164
229
  rows: rows,
165
230
  selected_row: @selected_row,
231
+ total_count: @total_count,
166
232
  empty_message: "No scheduled jobs"
167
233
  )
168
234
 
@@ -1,10 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "json"
4
- require "time"
5
-
6
3
  require_relative "solid_queue_tui/version"
7
- require_relative "solid_queue_tui/connection"
8
4
 
9
5
  # Data layer
10
6
  require_relative "solid_queue_tui/data/stats"
@@ -12,18 +8,24 @@ require_relative "solid_queue_tui/data/jobs_query"
12
8
  require_relative "solid_queue_tui/data/queues_query"
13
9
  require_relative "solid_queue_tui/data/processes_query"
14
10
  require_relative "solid_queue_tui/data/failed_query"
11
+ require_relative "solid_queue_tui/data/recurring_tasks_query"
15
12
 
16
13
  # Actions
17
14
  require_relative "solid_queue_tui/actions/retry_job"
18
15
  require_relative "solid_queue_tui/actions/discard_job"
19
16
  require_relative "solid_queue_tui/actions/dispatch_scheduled_job"
20
17
  require_relative "solid_queue_tui/actions/discard_scheduled_job"
18
+ require_relative "solid_queue_tui/actions/toggle_queue_pause"
19
+ require_relative "solid_queue_tui/actions/enqueue_recurring_task"
21
20
 
22
21
  # Components
23
22
  require_relative "solid_queue_tui/components/header"
24
23
  require_relative "solid_queue_tui/components/job_table"
25
24
  require_relative "solid_queue_tui/components/help_bar"
26
25
 
26
+ # View concerns
27
+ require_relative "solid_queue_tui/views/concerns/filterable"
28
+
27
29
  # Views
28
30
  require_relative "solid_queue_tui/views/dashboard_view"
29
31
  require_relative "solid_queue_tui/views/queues_view"
@@ -32,6 +34,7 @@ require_relative "solid_queue_tui/views/in_progress_view"
32
34
  require_relative "solid_queue_tui/views/blocked_view"
33
35
  require_relative "solid_queue_tui/views/scheduled_view"
34
36
  require_relative "solid_queue_tui/views/finished_view"
37
+ require_relative "solid_queue_tui/views/recurring_tasks_view"
35
38
  require_relative "solid_queue_tui/views/processes_view"
36
39
  require_relative "solid_queue_tui/views/job_detail_view"
37
40
 
@@ -43,4 +46,12 @@ require_relative "solid_queue_tui/application"
43
46
  require_relative "solid_queue_tui/cli"
44
47
 
45
48
  module SolidQueueTui
49
+ @refresh_interval = 200
50
+ @page_size = 100
51
+
52
+ class << self
53
+ attr_accessor :refresh_interval, :page_size
54
+ end
46
55
  end
56
+
57
+ require_relative "solid_queue_tui/railtie" if defined?(Rails::Railtie)
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :solid_queue_tui do
4
+ desc "Launch the Solid Queue TUI dashboard"
5
+ task start: :environment do
6
+ SolidQueueTui::CLI.run([])
7
+ end
8
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solid_queue_tui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shiva Reddy
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-02-16 00:00:00.000000000 Z
11
+ date: 2026-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ratatui_ruby
@@ -25,47 +25,33 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
- name: activerecord
28
+ name: solid_queue
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '7.0'
33
+ version: '1.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '7.0'
40
+ version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: sqlite3
42
+ name: railties
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: pg
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
47
+ version: '7.1'
48
+ type: :runtime
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
52
  - - ">="
67
53
  - !ruby/object:Gem::Version
68
- version: '0'
54
+ version: '7.1'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: rake
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -108,21 +94,25 @@ files:
108
94
  - lib/solid_queue_tui/actions/discard_job.rb
109
95
  - lib/solid_queue_tui/actions/discard_scheduled_job.rb
110
96
  - lib/solid_queue_tui/actions/dispatch_scheduled_job.rb
97
+ - lib/solid_queue_tui/actions/enqueue_recurring_task.rb
111
98
  - lib/solid_queue_tui/actions/retry_job.rb
99
+ - lib/solid_queue_tui/actions/toggle_queue_pause.rb
112
100
  - lib/solid_queue_tui/application.rb
113
101
  - lib/solid_queue_tui/cli.rb
114
102
  - lib/solid_queue_tui/components/header.rb
115
103
  - lib/solid_queue_tui/components/help_bar.rb
116
104
  - lib/solid_queue_tui/components/job_table.rb
117
- - lib/solid_queue_tui/connection.rb
118
105
  - lib/solid_queue_tui/data/failed_query.rb
119
106
  - lib/solid_queue_tui/data/jobs_query.rb
120
107
  - lib/solid_queue_tui/data/processes_query.rb
121
108
  - lib/solid_queue_tui/data/queues_query.rb
109
+ - lib/solid_queue_tui/data/recurring_tasks_query.rb
122
110
  - lib/solid_queue_tui/data/stats.rb
123
111
  - lib/solid_queue_tui/dev_reloader.rb
112
+ - lib/solid_queue_tui/railtie.rb
124
113
  - lib/solid_queue_tui/version.rb
125
114
  - lib/solid_queue_tui/views/blocked_view.rb
115
+ - lib/solid_queue_tui/views/concerns/filterable.rb
126
116
  - lib/solid_queue_tui/views/dashboard_view.rb
127
117
  - lib/solid_queue_tui/views/failed_view.rb
128
118
  - lib/solid_queue_tui/views/finished_view.rb
@@ -130,7 +120,9 @@ files:
130
120
  - lib/solid_queue_tui/views/job_detail_view.rb
131
121
  - lib/solid_queue_tui/views/processes_view.rb
132
122
  - lib/solid_queue_tui/views/queues_view.rb
123
+ - lib/solid_queue_tui/views/recurring_tasks_view.rb
133
124
  - lib/solid_queue_tui/views/scheduled_view.rb
125
+ - lib/tasks/solid_queue_tui.rake
134
126
  homepage: https://github.com/shivareddy-Aluri/solid-queue-tui
135
127
  licenses:
136
128
  - MIT
@@ -1,58 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "active_record"
4
- require "yaml"
5
-
6
- module SolidQueueTui
7
- class Connection
8
- CONFIG_FILE = "config/solid_tui.yml"
9
-
10
- # Loads config, establishes the DB connection, and returns the parsed config hash.
11
- def self.establish!
12
- config = load_config
13
-
14
- url = config["database_url"]
15
- raise ConnectionError, <<~MSG unless url
16
- No database_url found in #{CONFIG_FILE}.
17
-
18
- Create #{CONFIG_FILE} with:
19
- database_url: postgres://user:pass@localhost/myapp_queue
20
- refresh: 2
21
- MSG
22
-
23
- ActiveRecord::Base.establish_connection(url)
24
- verify_solid_queue_tables!
25
-
26
- config
27
- end
28
-
29
- def self.load_config
30
- path = File.join(Dir.pwd, CONFIG_FILE)
31
-
32
- unless File.exist?(path)
33
- raise ConnectionError, <<~MSG
34
- Config file not found: #{CONFIG_FILE}
35
-
36
- Create #{CONFIG_FILE} with:
37
- database_url: postgres://user:pass@localhost/myapp_queue
38
- refresh: 2
39
- MSG
40
- end
41
-
42
- YAML.safe_load(File.read(path), permitted_classes: [Symbol]) || {}
43
- end
44
-
45
- def self.verify_solid_queue_tables!
46
- conn = ActiveRecord::Base.connection
47
- required = %w[solid_queue_jobs solid_queue_ready_executions]
48
- missing = required.reject { |t| conn.table_exists?(t) }
49
-
50
- unless missing.empty?
51
- raise ConnectionError, "Missing Solid Queue tables: #{missing.join(', ')}. " \
52
- "Is this a Solid Queue database?"
53
- end
54
- end
55
-
56
- class ConnectionError < StandardError; end
57
- end
58
- end